RoR: fields_for and partials - ruby-on-rails

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

Related

Rails - form_for select that show my categories from db

I have Pages associated to my Categories
Now I have a form that I'm creating Pages
<%= form_for #page do |f| %>
<table>
<tr>
<td><%= f.label :title %></td>
<td><%= f.text_field :title %></td>
</tr>
<tr>
<td><%= f.label :desc %></td>
<td><%= f.text_field :desc %></td>
</tr>
<tr>
<td><%= f.label :category_id %></td>
<td><%= f.select(Page.all, :category_id, :title) %></td>
</tr>
</table>
<%= f.submit %>
<% end %>
I'm trying to create a select dropdown that will show me all the categories that I have from my db, after I select one it will assign the Page that I'm creating to the Category that I'm choosing from the select dropdown
You should use
f.select :category, Category.pluck(:title, :id)
Be aware, that if your rails version is lower, that 4.x you can only use pluck with one column.
You need to change your select tag according to this.
<%= form_for #page do |f| %>
<table>
<tr>
<td><%= f.label :title %></td>
<td><%= f.text_field :title %></td>
</tr>
<tr>
<td><%= f.label :desc %></td>
<td><%= f.text_field :desc %></td>
</tr>
<tr>
<td><%= f.label :category %></td>
<td><%= f.select(:category_id, options_from_collection_for_select(Category.all, :category_id, :title)) %></td>
</tr>
For Rails3(or may be less), if you've a Category model you can simply do.
f.select(:category, Category.select([:id,:title]).map { |c| [ c.id, c.title ] } , { include_blank: true })
collection_select is what you need:
<%= form_for #page do |f| %>
<%= f.collection_select :category_id, Category.all, :id, :title %>
<%= f.submit %>
<% end %>

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

Rails: Simpleform inside of table input type = text_area- how to set its height?

I'm using the "Simpleform" gem for my rails app and I have a form embedded in a table.
One of the elements of the form is a text_area. However, the entire row of the table is very tall because of this input type. I would like to set its height so that the rows are not so tall.
How do I do that I tried the following but that didn't seem to change anything
<% #listings.each do |listing| %>
<%= simple_form_for(listing, :html => {:multipart => true, :class=> '.form-inline'} ) do |f| %>
<tr>
<td><%= listing.id %></td>
<td><%= listing.name %></td>
<td><%= f.input :telephone %></td>
<td><%= f.input :fax %></td>
<td><%= f.input :suite %></td>
<td> <%= f.input :notes, :size => 5 %></td>
<td> <%= f.button :submit %></td>
</tr>
<% end %>
<% end %>
Any suggestions would be greatly appreciated
I think you want something like this:
<td> <%= f.input :notes, :input_html => { :rows => 5 } %></td>
The input_html option will add arbitrary attributes to the resulting HTML tag. In the case of a textarea, there is no 'size' attribute, only 'cols' or 'rows'.
I haven't tested this myself, but I've used :input_html for other HTML attributes. Let me know how you fare!
You can use the code Ben submitted:
<td> <%= f.input :notes, :input_html => { :rows => 5 } %></td>
But, it might be a better idea to use the helper classes simple form uses. From memory, and with your custom class, something like this should work:
.form-inline .text{
height: 300px;
}
This keeps styling separate in your css, as it should be.

Rails 3 access nested attributes in nested form

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? %>

How do I do this without using a double loop?

I'm attempting to use the fields_for command to combine two models edit functions. I'm editing several variables. With these variables I'd like to include some basic information that is associated with the model, such as #line_item.inventory.item. The only way I could accomplish this is by creating a double loop which doesn't work for obvious reasons. Is there a way to pass two arguments into a for loop?
ie. fields_for :line_items & #order.line_items do ???
<% f.fields_for :line_items do |f| %>
<% for line_item in #order.line_items do %>
<td><%= line_item.inventory.item %></td>
<td><%= f.text_field :inventory_id, :size => 3 %></td>
<td><%= line_item.inventory.unit2_id %></td>
<td><%= line_item.inventory.catalognumber %></td>
<td><%= f.text_field :quantity, :size => 3 %></td>
<td> <%= f.text_field :item_price, :size => 3 %></td>
<td><%= f.text_field :total_price, :size => 3 %></td>
<td><%= f.check_box :received %><b>Received</b> </td>
<td><%= f.text_field :notes %></td>
<td><%= link_to 'remove item', line_item, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
<% end %>
You should look at accepts_nested_attributes_for. When used correctly, it can solve your problem.
Assuming the encompassing form is for an order you want to add the following to the Order model, if it isn't already there.
class Order < ActiveRecord::Base
has_many :line_items
accepts_nested_attributes_for :line_items
end
And the view:
<% form_for :order do |f| %>
...
Order specific fields
...
<% f.fields_for :line_items do |line_item_form| %>
<% line_item = line_item_form.object
<td><%= line_item.inventory.item %></td>
<td><%= line_item_form.text_field :inventory_id, :size => 3 %></td>
<td><%= line_item.inventory.unit2_id %></td>
<td><%= line_item.inventory.catalognumber %></td>
<td><%= line_item_form.text_field :quantity, :size => 3 %></td>
<td> <%= line_item_form.text_field :item_price, :size => 3 %></td>
<td><%= line_item_form.text_field :total_price, :size => 3 %></td>
<td><%= line_item_form.check_box :received %><b>Received</b> </td>
<td><%= line_item_form.text_field :notes %></td>
<td><%= link_to 'remove item', line_item, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
fields_for, when used with accepts_nested_attributes_for and given an association, will loop through all items already associated with the object of the parent form builder. In all other cases fields_for does not use a loop.
First of all, if you need to do nested models I recommend you to view these three railscasts innmediately.
In your case I would start by interchanging the "for" and the "fields for":
<% for line_item in #order.line_items do %>
<% f.fields_for :line_item do |f| %>
... (snip)
<% end %>
<% end %>
Then I would realize that a I could move the entire fields_for to a partial view and use a render call with a :collection parameter:
in order.html.erb:
<%= render :partial => :line_item, :collection => order.line_items %>
in _line_item.html.erb:
<% f.fields_for :line_item do |f| %>
... etc
Now you don't have any "for". :)
Also, your "line items" are inside an "#order" object, so I imagine there's a form_for somewhere up:
<% form_for #order ... %>
...
<%= render :partial => :line_item, :collection => order.line_items %>
...
<% end %>
Now you have your views fixed. But you still have to make your Orders model "handle" its children correctly.
I'm not sure there is really a way for this, since the fields_for block and the for loop are basically 2 different things. So it's not really a "double loop".

Resources