Rails: loop through array to create output - ruby-on-rails

I have a model "tube" which is a database having the various data for vacuum tubes. I want to dynamically loop through all the columns and create a basic table for my "new" and "edit" pages.
I grab the attribute names like this:
<% attr_array = #tube.attribute_names %>
And I want to do something like this:
<% attr_array.each{|x| text_field :x } %>
in hopes of dynamically generating this:
<%= form_for #tube do |f| %>
<%= f.label :name, :class=>'std_label' %>:
<%= f.text_field :name, :class=>'std_input' %>
<%= f.label :functional_class, :class=>'std_label' %>:
<%= f.text_field :functional_class, :class=>'std_input' %>
<%= f.label :base_type, :class=>'std_label' %>:
<%= f.text_field :base_type, :class=>'std_input' %>
.... and so forth ....
<%= f.submit %> <% end %>
But of course this does not work, not by a long shot. How can I generate my text_field inputs dynamically based on the attribute_names array? The table I am using has about 30 attributes and I think it's silly to build them all by hand, especially given that if they change in the future then the code will break. Googling and reading the API have given me the lectures on why this doesn't work, but has left me hi and dry with a code example of what does.
Accurate help appreciated.

What about:
<%= form_for #tube do |f| %>
<% #tube.attribute_names.each do |attr| %>
<%= f.text_field attr, :class=>'std_input' %>
<%= f.label attr, :class=>'std_label' %>:
<% end %>
<%= f.submit %>
<% end %>

Related

Access attributes of associated models in Ransack

I have a dashboard that shows results fetched from users and nannies model.
In my user.rb, I have
User has_many :nannies
The nanny.rb has
Nanny belongs_to :user
User has some basic attributes (name, email, phone etc)
Nanny has other attributes (gender, hours, days etc)
Right now, I have these lines to implement Ransack and fetch users according to filters. The index method of the controller is
#users = User.ransack(params[:q])
#people = #users.result
I can filter out the results based on attributes from Nanny. The filter form in the view is like this
<%= search_form_for #users do |f| %>
<%= f.label :firstname_cont %>
<%= f.search_field :firstname_cont %>
<%= f.label :lastname_cont %>
<%= f.search_field :lastname_cont %>
<%= f.label :role_eq %>
<%= f.search_field :role_eq %>
<%= f.label :nannies_gender_cont %>
<%= f.search_field :nannies_gender_cont %>
<%= f.label :nannies_hours_eq %>
<%= f.search_field :nannies_hours_eq %>
<%= f.submit %>
<% end %>
The results are displayed like this
<% #people.each do |test| %>
<%= test.id %>
<%= test.firstname %>
<%= test.email %>
<%= test.hours %>
<% end %>
I am getting an error 'undefined method hours for User' (which obviously belongs to the Nanny model).
I need to be able to achieve the following
Load all Users and its associated Nannies
Run Ransack and filter out the results
Display all attributes from all associated models in the view
Would really appreciate any guidance/correction in this issue.
Assuming your question is how to fix undefined method hours for User:
The following solution is not really a Ransack "thing", but more just a Rails "thing":
<% #people.each do |test| %>
<%= test.id %>
<%= test.firstname %>
<%= test.email %>
<% test.nannies.each do |nanny| %>
<%= nanny.hours %>
<% end %>
<% end %>
You need to loop through each nanny that belongs to test (of which is a User record), and from there only when you can access hours value for each nanny

Rails loop through data in a form field

I would like to loop through data in my database inside my form. What I would like to do with the data is put it in labels and textboxes. How could I do this in rails? Would I just use a .each block to loop through it inside the form? The reason I have it in my database is because my client would like to be able to add the form field data himself.
For example here is something I would like to do:
<%= form_for :order do |f| %>
#fields.each do |field|
<%= f.label field.name %>
<%= f.text_field field.name %>
<% end %>
<%= f.submit %>
<% end %>
What the best way to accomplish something like this?
Please don't answer with a railscast :)
Thanks in advance
Yes, that will work, though you missed an end script tag on line two:
<%= form_for :order do |f| %>
<% #fields.each do |field| %>
<%= f.label field.name %>
<%= f.text_field field.name %>
<% end %>
<%= f.submit %>
<% end %>
If you need something more complex than just a label/text field pair - then you can use a partial-template and use the collection keyword:
<!-- in 'order.html.erb' -->
<%= form_for :order do |f| %>
<!-- note: each 'field' is auto-populated from the collection/partial-name, but you need to pass the form in as a local -->
<%= render :partial => 'field', :collection => #fields, :locals => {:f => f} %>
<%= f.submit %>
<% end %>
and
<!-- in '_field.html.erb' -->
<%= f.label field.name %>
<%= f.text_field field.name %>
<!-- and whatever else you want to do... -->
more on partial rendering here: http://api.rubyonrails.org/classes/ActionView/Partials.html

Rails Nested Attributes Doesn't Insert ID Correctly

I'm attempting to edit a model's nested attributes, much as outline here, replicated here:
<%= form_for #person do |person_form| %>
<%= person_form.text_field :name %>
<% for address in #person.addresses %>
<%= person_form.fields_for address, :index => address do |address_form|%>
<%= address_form.text_field :city %>
<% end %>
<% end %>
<% end %>
In my code, I have the following:
<%= form_for(#meal) do |f| %>
<!-- some other stuff that's irrelevant... -->
<% for subitem in #meal.meal_line_items %>
<!-- # Edit 2: I need to display information here about the subitem
Which I can't find a way to pass it to the partial, or work in
this manner for existing items
-->
<%= subitem.food.name %>
<%= subitem.food.calories %>
<%= f.fields_for subitem, :index => subitem do |line_item_form| %>
<%= line_item_form.label :servings %><br/>
<%= line_item_form.text_field :servings %><br/>
<%= line_item_form.label :food_id %><br/>
<%= line_item_form.text_field :food_id %><br/>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
This works great, except, when I look at the HTML, it's creating the inputs that look like the following, failing to input the correct id and instead placing the memory representation(?) of the model. As a result, an update fails:
<input type="text" value="2" size="30" name="meal[meal_line_item][#<MealLineItem:0x00000005c5d618>][servings]" id="meal_meal_line_item_#<MealLineItem:0x00000005c5d618>_servings">
EDIT:
The reason I'm attempting to do it in this method is that I need to gather some information on associations for existing meal_line_items. For example, in the area where I took out code, I have some code to the effect of:
<%= subitem.food.name %>
<%= subitem.food.calories %>
Getting this information won't work if I am using a form builder with partials, at least, not in my trials.
Edit 2:*
See the edit in the code. Here's my MealLineItem
class MealLineItem < ActiveRecord::Base
# Associations ---------------------
belongs_to :food
belongs_to :meal
end
And meal accepts_nested_attributes for the model. As you can see it belongs to both food and meal model. For the existing meal_line_item I need to do something like:
meal_line_item.food.name
Is there f. missing from <%= fields_for?
--edit
Have you tried:
<%= f.fields_for 'meal[meal_line_item][]', subitem do |line_item_form| %>
--edit
Docs say that it should work without loop too:
<%= form_for(#meal) do |f| %>
<!-- some other stuff that's irrelevant... -->
<%= f.fields_for :meal_line_items do |line_item_form| %>
<%= line_item_form.label :servings %><br/>
<%= line_item_form.text_field :servings %><br/>
<%= line_item_form.label :food_id %><br/>
<%= line_item_form.text_field :food_id %><br/>
<% end %>
<%= f.submit %>
<% end %>
Have to test this but maybe this approach?
_form
<%= form.fields_for :meal_line_items do |meal_line_item_form| %>
<% #meal.meal_line_items.each do |meal_line_item| %>
<%= render :partial => "meal_line_items/meal_line_item", :locals => { :meal_line_item_form => meal_line_item_form, :meal_line_item => meal_line_item } %>
<% end %>
<% end %>
meal_line_items/_meal_line_item.erb
<%= meal_line_item_form.label :servings %><br/>
<%= meal_line_item_form.text_field :servings %><br/>
<%= meal_line_item_form.label :food_id %><br/>
<%= meal_line_item_form.text_field :food_id %><br/>
EDIT
here's a link to an example for setting the formbuilder iterator directly (Rails 2.3.8 though). The associations between Outbreak -> Incidents -> Location should be similiar to the ones for Meal -> Meal_line_items -> Food.
AJAX update of accepts_nested_attributes_for partials
After searching high and low, I found the error. Although I was modifying the partial and was receiving a NameError it's because I was calling the partial from a helper method - exactly the same problem as stated in the following question:
rails fields_for render partial with multiple locals producing undefined variable

Adding validations without knowing the fields

My example form
<% form_for #ad do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :ad_type_id %><br />
<%= f.collection_select(:ad_type_id, AdType.all, :id, :name) %>
</p>
<p>
<% #ad.ad_properties.each do |property| %>
<%= property.name %>:
<% f.fields_for :ad_values do |value_field| %>
<%= value_field.text_field :ad_id, :value => #ad.id %>
<%= value_field.text_field :ad_property_id, :value => property.id %>
<%= value_field.text_field :value %>
<% end %><br /><br />
<% end %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description %>
</p>
<p><%= f.submit %></p>
<% end %>
Explanation:
Ad has many properties. I can add new properties at any time (it's a normal model).
Lets say the Ad is of the type 'hotel'. Then I would add properties like 'stars' and 'breakfast_included'
Then I store each of these properties' values in a separate model.
And all this works fine with my form above.
My problem:
These fields are not validated because I can't know what their names are.
I need to add validations dynamically somehow.
My thought:
#Before the normal validations kick in
def add_validations
self.properties.each do |property|
property.add_validation :whatever #somehow :)
end
end
How could I do this?
Have you tried with polymorphic associations ? That's maybe a cleaner approach.
http://railscasts.com/episodes/154-polymorphic-association
Disclaimer: I've never done this before, so I'm not 100% sure it will work.
But as long as you can get the type of the object you are working with, you can use the Rails constantize method to get the model it references (I'm assuming that if ad can be of type Hotel, then you have a Hotel model). At that point you should probably have the appropriate validations on your Hotel model.

In Rails, how do I generate form labels without symbols that still create correct "for" attributes?

In Rails, how do I generate form labels without symbols that still create correct "for" attributes?
If I take this form:
<% form_for(#thing) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
And alter it to improve the clarity of what's expected in the field:
<% form_for(#thing) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label "What would you like to call your thing?" %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
The for attribute on the label tag would read "thing_What would you like to call your thing?", which obviously destroys its relationship with the intended partner field.
So how do I alter the label text while preserving that relationship?
<%= f.label :name, "What would you like to call your thing?" %>
See label’s documentation (and on APIdock).

Resources