Editing multiple rows in a table (updating multiple records) - ruby-on-rails

I have a list of payment records in Payments#index. I've been asked to make that table directly editable and to have one button that saves all the updates. So far I've only partially managed to do this by wrapping each row around a form_for for that record like so:
<tbody>
<% #payments.each do |payment| %>
<tr>
<td><%= payment.client.trading_name %></td>
<td><%= payment.date_of_payment %></td>
<td>
<%= form_for payment do |f| %>
<%= f.text_field :amount %>
<%= f.submit 'Save', class: 'table_submit' %>
<% end %>
</td>
<td>
<%= form_for payment do |f| %>
<%= f.select :sequence_type, options_for_select(%w[RCUR OOFF FRST FNAL]) %>
<%= f.submit 'Save', class: 'table_submit' %>
<% end %>
</td>
<td>
<ul>
<li><%= link_to 'Edit', edit_payment_path(payment) %></li>
<li><%= link_to 'Destroy', payment, method: :delete, data: { confirm: 'Are you sure?' } %></li>
</ul>
</td>
</tr>
<% end %>
</tbody>
Is it possible to be able to edit all the records then have one update button instead of having to save each record individually? If so, how do I go about doing that?

Its possible:
http://railscasts.com/episodes/165-edit-multiple-revised
And old version
http://railscasts.com/episodes/165-edit-multiple

Related

How do I submit 3 forms with 1 submit button?

I have a table that has X rows. I use an iterator to iterate over each object in a collection and render it in a row.
Each object/row is also associated with it's own form.
But I want to save the entire collection at once, and have it update all of the sub-forms when the user hits 1 submit button, rather than 1 for each instance of the form.
This is an example of what the code might look like:
<% #port_stocks.each do |port_stock| %>
<tr>
<td><%= number_to_currency(port_stock.purchase_price) %></td>
<td><%= port_stock.volume %></td>
<td>
<% cp = ClosedPosition.new %>
<%= simple_form_for cp, url: port_stocks_sell_order_path, method: :post, html: { class: "form-inline" } do |f| %>
<div class="form-group">
<%= f.input_field :num_units, id: "sell-ps-#{port_stock.id}", class: "form-control mx-sm-3" %>
</div>
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
</td>
</tr>
<% end %>
If there are 3 port_stock objects in the #port_stocks collection, the above form renders 3 submit buttons -- which is exactly what I don't want.
I just want 1 submit button that submits a cp related info for each port_stock object in the collection.
You could hide the submit button inside the simple_form like below:
<% #port_stocks.each do |port_stock| %>
<tr>
<td><%= number_to_currency(port_stock.purchase_price) %></td>
<td><%= port_stock.volume %></td>
<td>
<% cp = ClosedPosition.new %>
<%= simple_form_for cp, url: port_stocks_sell_order_path, method: :post, html: {class: "form-inline"} do |f| %>
<div class="form-group">
<%= f.input_field :num_units, id: "sell-ps-#{port_stock.id}", class: "form-control mx-sm-3" %>
</div>
<%= f.submit "", class: "click-me", style: "display: none;" %>
<% end %>
</td>
</tr>
<% end %>
Then have a button outside the loop like this:
<button type="button" class='btn btn-primary' onclick="submit()">Submit!</button>
Onclick of this button use JS to trigger clicks on hidden submit buttons.
<script>
function submit(){
var el = document.getElementsByClassName('click-me');
for (var i=0;i<el.length; i++) {
el[i].click();
}
}
</script>
Just an idea, following up my comment, using standard form helpers.
Wrap the table with the form:
<%= form_for :closed_position, url: {action: :port_stocks_sell_order_path, method: :post} do |form|%>
<table>
<% #port_stocks.each do |port_stock| %>
<tbody>
<tr>
<td><%= port_stock.volume %></td>
<td><%= port_stock.purchase_price %></td>
<td>
Num: <%= form.text_field "port_stock_id[#{port_stock.id}][num_units]" %>
</td>
</tr>
</tbody>
<% end %>
</table>
<%= form.submit "save" %>
<% end %>
The parameters should be something like:
{"utf8"=>"✓", "authenticity_token"=>"blahblah", "closed_position"=>{"port_stock_id"=>{"1"=>{"num_units"=>"999"}, "2"=>{"num_units"=>"888"}}}, "commit"=>"save", "method"=>"post", "controller"=>"port_stocks", "action"=>"port_stocks_sell_order_path"}
Then manage to save each ClosedPosition in the controller.

Views in ruby on rails

I am learning to code in ruby on rails environment. I created two models cars and products. I want to have a main page which have a link to cars and products. On clicking each of them they should display their own view pages. Below are view pages for cars and users respectively :
app/views/cars/index.html.erb
<p id="notice"><%= notice %></p>
<h1>Listing Cars</h1>
<table>
<thead>
<tr>
<th>Make</th>
<th>Color</th>
<th>Year</th>
<th colspan="24"></th>
</tr>
</thead>
<tbody>
<% #cars.each do |car| %>
<tr>
<td><%= car.make %></td>
<td><%= car.color %></td>
<td><%= car.year %></td>
<td><%= link_to 'Show', car %></td>
<td><%= link_to 'Edit', edit_car_path(car) %></td>
<td><%= link_to 'Destroy', car, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Car', new_car_path %>
<h4>Import that data!</h4>
<%= form_tag import_users_path, multipart: true do %>
<%= file_field_tag :file %>
<%= submit_tag "Import CSV" %>
<% end %>
</div>
app/views/users/index.html.erb
<p id="notice"><%= notice %></p>
<h1>Listing Users</h1>
<table>
<thead>
<tr>
<th>User</th>
<th>Steps</th>
<th>Distance</th>
<th>Minutes Exercised</th>
<th>Hours of Sleep</th>
<th>Calories Burned</th>
<th colspan="24"></th>
</tr>
</thead>
<tbody>
<% #users.each do |user| %>
<tr>
<td><%= user.user %></td>
<td><%= user.steps %></td>
<td><%= user.distance %></td>
<td><%= user.exercise %></td>
<td><%= user.sleep %></td>
<td><%= user.calories %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New User', new_user_path %>
<div>
<h4>Import that data!</h4>
<%= form_tag import_users_path, multipart: true do %>
<%= file_field_tag :file %>
<%= submit_tag "Import CSV" %>
<% end %>
</div>
<%= form_tag import_users_path, multipart: true, class: 'form-inline' do %>
<div class="form-group">
<%= link_to "Export CSV", users_path(format: "csv"), class: 'btn btn-primary' %>
</div>
<% end %>
I don't know how to create single main page and provide links to these views. One example would help me. Thanks in advance guys.
Say suppose you have a main page named home
In your home.html.erb write
<%= link_to "cars" cars_path %>
<%= link_to "users" users_path %>
You probably should use rails scaffold to have a look at the functional pages generated by it at first.
Try this .......
<%=link_to "cars" cars_path(car) %>
<%=link_to "users" users_path(user) %>
This link will send you to show method of the controller (users/cars). Then you need to create a show page in your views/cars/show.html.erb and views/users/show.html.erb then you can display their own view/show pages.
Hope this will work for you.
You need to understand concept of routes in rails.
Run command rake routes in your project folder. You will see mapping like this.
Prefix Verb URI Pattern Controller#Action
companies GET /companies(.:format) companies#index
So according to routes, following link will lead to index action of companies controller.
<%= link_to 'Companies', companies_path%>
As you can observe, in companies_path, companies is prefix shown in routes.
For your specific case, following links will work. In your
home.html.erb
<%=link_to "All Cars", cars_path%>
<%=link_to "All Users", users_path%>
Remember there is comma between "All Users" and users_path. Because link_to is just a method with multiple arguments.
For more info,
http://apidock.com/rails/v4.0.2/ActionView/Helpers/UrlHelper/link_to

Rails syntax error : unexpected keyword_ensure, expecting end-of-input

I am a newbie in rails and i tried creating a forum application based on a tutorial. This is my forum page but i keep getting the error:
syntax error, unexpected keyword_ensure, expecting end-of-input
Extracted source (around line #33):
30
31 <p><% if admin? %><%= link_to "New Forum", new_forum_path %><% end %></p>
here is the forum index page which is throwing the error:
<% title "Forums" %>
<table>
<tr>
<th width="70%">Forum</th>
<th width="30%">Last Post</th>
</tr>
<% for forum in #forums %>
<tr>
<td><h4><%= link_to h(forum.name), forum_path(forum.id) %></h4>
<small><%= forum.topics.count %> topics</small><br />
<%=h forum.description %></td>
<td class="right">
<% if forum.most_recent_post %>
<%= distance_of_time_in_words_to_now forum.most_recent_post.last_post_at %>
ago by
<%= link_to forum.most_recent_post.user.username, "/users/#{forum.most_recent_post.last_poster_id}" %>
<% else %>no posts<% end %>
</td>
<% if admin? %>
<td><%= link_to "Edit", edit_forum_path(forum) %>
<% end %></td>
<!-- <% end %> -->
<% if admin? %>
<td><%= link_to "Destroy", forum, :confirm => 'Are you sure?', :method => :delete %></td>
<% end %>
</tr>
<% end %>
<p><% if admin? %><%= link_to "New Forum", new_forum_path %><% end %></p>
<!-- <% end %> --> what is this doing? a html commented ERB tag will still evaluate. Remove it. if you want to comment ruby code use # instead, like <% #end %>
Properly formatted code goes a long way towards diagnosing problems like this (mismatch and the like). Try out the following:
<% title "Forums" %>
<table>
<tr>
<th width="70%">Forum</th>
<th width="30%">Last Post</th>
</tr>
<% for forum in #forums %>
<tr>
<td>
<h4><%= link_to h(forum.name), forum_path(forum.id) %></h4>
<small><%= forum.topics.count %> topics</small>
<br />
<%=h forum.description %>
</td>
<td class="right">
<% if forum.most_recent_post %>
<%= distance_of_time_in_words_to_now forum.most_recent_post.last_post_at %>
ago by
<%= link_to forum.most_recent_post.user.username, "/users/#{forum.most_recent_post.last_poster_id}" %>
<% else %>
no posts
<% end %>
</td>
<% if admin? %>
<td><%= link_to "Edit", edit_forum_path(forum) %></td>
<td><%= link_to "Destroy", forum, :confirm => 'Are you sure?', :method => :delete %></td>
<% end %>
</tr>
<% end %>
</table>
<% if admin? %>
<p><%= link_to "New Forum", new_forum_path %></p>
<% end %>
all I could see wrong is that you set end before it should here
<% if admin? %>
<td><%= link_to "Edit", edit_forum_path(forum) %>
<% end %></td>
so try to move it like this
<% if admin? %>
<td><%= link_to "Edit", edit_forum_path(forum) %>
</td><% end %>
I think you have the order of opening and closing blocks jumbled up.
if, for are all opening blocks that have to be closed at the appropriate times.
The commented-out end tag that Benjamin mentioned is actually important but misplaced and has to go between your </tr> and </table> tags to close the for forum in #forums.
I prepared a modified version with some realignments, so I could make sense of it more easily. Haven't actually tested it, though.
<% title "Forums" %>
<table>
<tr>
<th width="70%">Forum</th>
<th width="30%">Last Post</th>
</tr>
<% for forum in #forums %>
<tr>
<td>
<h4><%= link_to h(forum.name), forum_path(forum.id) %></h4>
<small><%= forum.topics.count %> topics</small><br />
<%=h forum.description %></td>
<td class="right">
<% if forum.most_recent_post %>
<%= distance_of_time_in_words_to_now forum.most_recent_post.last_post_at %>
ago by
<%= link_to forum.most_recent_post.user.username, "/users/#{forum.most_recent_post.last_poster_id}" %>
<% else %>
no posts
<% end %>
</td>
<% if admin? %>
<td>
<%= link_to "Edit", edit_forum_path(forum) %>
</td>
<% end %>
<% if admin? %>
<td><%= link_to "Destroy", forum, :confirm => 'Are you sure?', :method => :delete %></td>
<% end %>
</tr>
<% end %>
</table>
<p>
<% if admin? %>
<%= link_to "New Forum", new_forum_path %>
<% end %>
</p>

form not creating new entries

I am trying to create a form to add a transporter:
I have app/views/transporters/new.html.erb that calls a template,app/views/_form.html.erb that looks like:
<%= form_for(#transporter) do |f| %>
<% if #transporter.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#transporter.errors.count, "error") %> prohibited this transporter from being saved:</h2>
<ul>
<% #transporter.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :phone %><br>
<%= f.text_field :phone %>
</div>
<div class="field">
<%= f.label :id_number %><br>
<%= f.text_field :id_number %>
</div>
<div class="actions">
<%= f.submit 'Add transporter', class: 'btn btn-success' %>
</div>
<% end %>
<%= link_to 'Back to all transporters', transporters_path, class: "btn" %>
</div>
</div>
This is the create action in my transporters controller:
def create
#transporter = Transporter.new(transporter_params)
end
private
def transporter_params
params.require(:transporter).permit(:name, :phone, :id_number)
end
When I click Add transporter the form doesn't go anywhere. What do I have wrong?
Update:
this is my routes file:
Cowsnhills::Application.routes.draw do
resources :transporters
resources :deliveries
root 'welcome#index'
end
When I click submit the form reloads but the entries will not show on my transporters index, here is that code:
transporters controller method:
def index
#transporters = Transporter.all
end
and transporters index:
<h1>Listing transporters</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Id</th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<% #transporters.each do |transporter| %>
<tr>
<td><%= transporter.name %></td>
<td><%= transporter.phone %></td>
<td><%= transporter.id %></td>
<td><%= f.link_to_add "Add a delivery", :deliveries %></td>
<td><%= link_to 'Show transporter details', transporter %></td>
<td><%= link_to 'Edit transporter details', edit_transporter_path(transporter) %></td>
<td><%= link_to 'Delete transporter', transporter, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Transporter', new_transporter_path, class: "btn" %>
Also there's a transporter has_many deliveries and a velivery belongs_to transporter association going on
You just create a new object with your params from the form in your create action, but you don't save it.
add #transporter.save to your create action.
use
#transporter = Transporter.new(params[:transporter])
or
#transporter = Transporter.new(params["transporter"])
check my last comment to save it.

Proper arguments for initializing a model in a view?

My question template lists answers, and lets somone add a new answer for a question.
But I'm not sure where and how to initialize a new answer for this line:
<%= link_to 'New answer', new_question_answer_path(#question, Answer.new) %>
from the context below:
<p>
<b>Body:</b>
<%=h #question.body %>
</p>
<h1>Listing answers</h1>
<table>
<tr>
<th>Body</th>
</tr>
<% #question.answers.each do |answer| %>
<tr>
<td><%=h answer.body %></td>
<td><%= link_to 'Show', answer %></td>
<td><%= link_to 'Edit', edit_answer_path(answer) %></td>
<td><%= link_to 'Destroy', answer, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New answer', new_question_answer_path(#question, Answer.new) %>
<%= link_to 'Edit', edit_question_path(#question) %> |
<%= link_to 'Back', questions_path %>
If I initialize the new Answer like this:
<%= link_to 'New answer', new_question_answer_path(#question, Answer.new) %>
the URL of the next page is garbled with an inspect call to the new Answer.
Try this:
<%= link_to 'New answer', new_question_answer_path(#question) %>

Resources