Rails 3 access nested attributes in nested form - ruby-on-rails

I have an Invoice, that contains LineItems that belong to item Items.
Invoice
client_id
LineItem
invoice_id
item_id
quantity
cost (because cost could be edited per invoice if needed)
Item
name
cost
The problem is, in the Edit form. I want to display the cost and description but I can't.
_form.html.erb
<%= form_for(#invoice) do |f| %>
<div class="field">
<%= f.label :organization_id, 'Client' %>
<%= f.collection_select :client_id, #clients, :id, :name, :prompt => 'Select' %>
</div>
<table id="invoice_items">
<tr><th>Item</th><th>Description</th><th>Unit Cost</th><th>Qty</th></tr>
<%= f.fields_for :line_items do |builder| %>
<%= render 'line_item_fields', :f => builder %>
<% end %>
</table>
<div class="actions">
<%= f.submit 'Save', :disable_with => "Processing..." %>
</div>
<% end %>
_line_items_fields.html.erb
<tr>
<td><%= f.collection_select :item_id, #items, :id, :name, :prompt => '' %></td>
<td>Description here</td>
<td><%= f.text_field :cost, :class => 'cost' %></td>
<td><%= f.text_field :quantity, :class => 'qty' %></td>
</tr>
How could I display the cost and description in a div in _line_items_fields.html.erb? I will need to display the cost in a div because later I will need to use it for jQuery to grab that value to do some calculation.

I guess you're looking for object.
Something like:
<%= f.object.cost unless f.object.cost.blank? %>

Related

Rails form_for only submitting last input

Im trying to create inputs by looping each product and have one form submission for all the inputs. Currently, the form only submits the last input. How would I make it so all the inputs get submitted?
<%= form_for :inventory do |f| %>
<% #products.each do |product| %>
<tr>
<td><%= product.name %></td>
<td><%= product.measurement %></td>
<td><%= f.number_field :amount, class: 'form-control' %></td>
<%= f.hidden_field :product_id, :value => product.id %>
</tr>
<% end %>
<%= f.submit %>
<% end %>
I dont know your use case but you can use the gem cocoon for doing that. There will also be a link to add/remove another product.
https://github.com/nathanvda/cocoon
You can iterate with each_with_index:
<%= form_for :inventory do |f| %>
<% #products.each_with_index do |product, i| %>
<tr>
<%= f.hidden_field "product_id[#{i}]", :value => product.id %>
</tr>
<% end %>
<%= f.submit %>
<% end %>
Like that the output is not very elegant (something like "product_id"=>{"0"=>"1", "1"=>"2", "2"=>"3"... }) but it's for the example to show how every hidden field needs a unique key.
You can define your params in a better way to use them in the controller, just keep them unique.

Rails - update multiple resource entries with one link

I have a table of forms
<% #group.lessons.each do |lesson| %>
<%= form_for [#group, lesson] do |f| %>
<tr id='<%= lesson.id%>' >
<td><%= f.text_field :time %></td>
<td><%= f.text_field :day %></td>
<td><%= f.text_field :subject %></td>
<td><%= f.text_field :teacher %></td>
<td><%= f.text_field :room %></td>
<td><%= f.submit 'Update'%></td>
<td><%= link_to 'Delete', [lesson.group, lesson], method: :delete%></td>
</tr>
<%end%>
<%end%>
Each form updates an entry when the "update" button is clicked. But when you edit two entries and update only one, the info you edited in the other one is gone.
I want to have a button to update each entry in the table. How do I do this?
UPDATED:
First in model:
class Group < AR::Base # possibly you'r using ActiveRecord
attr_accessible :lessons_attributes
accepts_nested_attributes_for :lessons, :allow_destroy => true
has_many :lessons
end
and then in your view: # e.g. views/groups/_form.html.erb
<table>
<%= form_for #group do |f| %>
<%= f.error_messages %>
<%= f.fields_for :lessons do |lesson_form| %>
<%= render "lessons/lesson", :f => lesson_form%>
<% end %>
<tr><td><%= f.submit 'Update'%></td></tr>
<% end %>
</table>
and in views/lessons/_lesson.html.erb
<tr>
<td>
<%= f.text_field :subject %>
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Lesson" %>
</td>
</tr>
I think this is more of an html issue than a rails issue. You simply can't submit more than one form using plain html. That's why you're losing one form when you submit the other.
What you could do however is update multiple lessons that belong to the same group using nested attributes. Here are some resources for that:
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
http://railscasts.com/episodes/196-nested-model-form-part-1
https://github.com/ryanb/nested_form

Passing a value from one view to another

I have a button on an index page that links to a new_assignment_path
<% #users.each do |user| %>
<tr>
<td><%= link_to user.name, user %></td>
<td><%= link_to 'Assign to Class', new_assignment_path, :class => 'btn btn-mini' %></td>
</tr>
<% end %>
And I want it so that when you click on it, it takes you to the new_assignment_path, and takes the dropdown select on that pages form.
<%= simple_form_for(#assignment) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :user_id, collection: User.all.collect, as: :select %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
And have the drop down automatically set to the user.id of whatever user the button was inside of.
What is the best way of doing this?
Add params[:user_id] in the selected option of your select tag
<div class="form-inputs">
<%= f.input :user_id, collection: User.all.collect, as: :select, :selected => params[:user_id] %>
</div>

Rails 3 submit a form with multiple records

I'm new to rails so this is probably a basic question. I am trying to create a form where the user can create 3 records at once. I want the user to only have to click the submit button once. I'm submitting to my Review model a name, comment, and rating. Currently, only the last record is entered into the database.
<%= form_for([#user,#review]) do |f| %>
<table>
<tr>
<td>Rank</td>
<td>Name</td>
<td>Comment</td>
</tr>
<tr>
<td>1</td>
<td><%= f.text_field :name %></td>
<td><%= f.text_field :comment %></td>
<%= f.hidden_field :rating, :value=> "5" %>
</tr>
<tr>
<td>2</td>
<td><%= f.text_field :name %></td>
<td><%= f.text_field :comment %></td>
<%= f.hidden_field :rating, :value=> "3" %>
</tr>
<tr>
<td>3</td>
<td><%= f.text_field :name %></td>
<td><%= f.text_field :comment %></td>
<%= f.hidden_field :rating, :value=> "1" %>
</tr>
</table>
<div class="actions">
<%= f.submit "Create my top 3" %>
</div>
<% end %>
Any advice is appreciated. Thanks.
I would recommend using fields_for for this:
<%= form_for([#user, :reviews]) do |f| %>
<% #reviews.each do |review| %>
<%= fields_for review do |r| %>
<%= render "reviews/form", :r => r %>
<% end %>
<% end %>
<% end %>
To make this work, you will need to build as many review objects as you require in your controller:
def new
# you could also have this in a before_filter...
#user = User.find(params[:id])
#reviews = Array.new(3) { #user.reviews.build }
end
This would create new instances of review records for this user, which is different from new records. Instances are simply Ruby objects. Now because you've called #user.reviews.build three times, you'll see three reviews in your view.
def create
#user = User.find(params[:id])
#reviews = Review.create(params[:reviews])
# Some more logic for validating the parameters passed in
end
This will create three new Review objects and link them to #user, assuming all three are valid.
You'll need to tell rails its an array. First, read this section of this article:
For your purpose, you'll need to build the form by hand:
<%= form_tag 'foo' do %>
<% [1,3,5].each do |i| %>
<%= text_field_tag 'review[][name]' %>
<%= text_field_tag 'review[][comment]' %>
<%= hidden_field_tag 'review[][rating]', :value => i %>
<% end %>
<% end %>

RoR: fields_for and partials

i am using nested_attributes for an association of products back to a transaction.
I need to add a date to the products model. I would like to add a link to set the date_select to today.
here is the view:
<% f.fields_for :trans_products do |builder| %>
<%= render 'trans_product_fields', :f => builder %>
<% end %>
and the partial:
<tr class="fields">
<td><%= f.text_field :po, :class => 'prodinfo' %></td>
<td><%= f.text_field :so, :class => 'prodinfo' %></td>
<td><%= f.text_field :product, :class => 'prodinfo' %></td>
<td><%= f.text_field :serial, :class => 'prodinfo' %></td>
<td class=bigprodinfo><%= f.date_select :pos_date, :include_blank => true, :order => [:month, :day, :year] %>
<%= link_to_function("today", "set_today('#{????}','pos_date')", :class => "today_link") %> </td>
<td><%= link_to_remove_product "remove", f %></td>
</tr>
the ???? should read transaction_trans_products_attributes_#number#, #number# shows up correctly for the textfields, the po text field reads id="transaction_trans_products_attributes_0_po" the next trans_product has id="transaction_trans_products_attributes_1_po"
how can i get this counter value into my link_to_function parameter?
thx
There should be an iteration_counter automatically set up for your collection (your collection here being called "trans_products".
According to the docs, the counter is named after the items in the array eg here it should be called "trans_product_counter"
For more info, have a look here:
http://apidock.com/rails/ActionView/Partials

Resources