class User < ActiveRecord::Base
belongs_to :person, :dependent => :destroy
accepts_nested_attributes_for :person, :allow_destroy => true
attr_accessible :person_attributes
end
class Person < ActiveRecord::Base
has_many :phone_numbers, :as => :phoneable, :dependent => :destroy
has_one :user
accepts_nested_attributes_for :phone_numbers
end
class PhoneNumber < ActiveRecord::Base
belongs_to :phoneable, :polymorphic => true
end
<%= form_for #user do |user_form| %>
<%= user_form.fields_for :person do |person_form| %>
<%= person_form.fields_for :phone_numbers do |phone_number_form| %>
<%= phone_number_form.text_field :number %>
<% end %>
<% end %>
<% end %>
This works. It does what I expect, but I want more than one phone number in my form. How can I accomplish that?
user[person_attributes][phone_numbers_attributes][0][number]
Why does fields_for add [0] ?
If I want multiple phone numbers, would the second look like this?
user[person_attributes][phone_numbers_attributes][1][number]
If so, how?
If I can get multiple phone numbers in the database, my next question will be how to include other phone number attributes along with each number? e.g.: description
user[person_attributes][phone_numbers_attributes][0][number]
user[person_attributes][phone_numbers_attributes][0][description]
fields_for adds "[0]" because its a many relationship and it needs to make an array, with an index for each relation member [0], [1] ...
So yes, the second would have [1], rails adds that by itself via the helpers.
To include other phone number attributes:
<%= form_for #user do |user_form| %>
<%= user_form.fields_for :person do |person_form| %>
<%= person_form.fields_for :phone_numbers do |phone_number_form| %>
<%= phone_number_form.text_field :number %>
<%= phone_number_form.text_field :description %>
<% end %>
<% end %>
<% end %>
Related
I'm new to rails and just cant get that problem solved.
i have 3 models. Orders, Products and LineItems.
I want to have a order form with checkboxes for each product. User selects appropriate products and submits the order.
I cannot get the form to create the correct hash.
class Order < ActiveRecord::Base
attr_accessible :account_id, :user_id
has_many :line_items, :dependent => :destroy
end
class LineItem < ActiveRecord::Base
attr_accessible :account_id, :product_id, :order_id
belongs_to :orders
belongs_to :product
end
Here the view:
<%= form_for 'line_items[]' do |f| %>
<%= f.select :account_id, options_from_collection_for_select( Account.all,
:id, :name ), :prompt => 'Select Account' %>
<% Product.all.each do |product| %>
<div>
<%= check_box_tag 'line_items[product_ids][]', product.id %>
</div>
<% end -%>
<div>
<%= f.submit 'save' %>
</div>
thanks!
You would need to use accepts_nested_attributes_for in your model to enable nested atributes from associated models. You may also want to check out this railscast and adapt to your needs.
For example in the orders model:
class Order < ActiveRecord::Base
attr_accessible :account_id, :user_id
has_many :products #This makes the association to products
has_many :line_items, :dependent => :destroy
accepts_nested_attributes_for :products #This allows the attributes from products accessible
end
Then the form could be:
<%= form_for #order do |f| %>
<%= f.select :account_id, options_from_collection_for_select( Account.all,
:id, :name ), :prompt => 'Select Account' %>
<%= f.fields_for :product do |product_form| %>
<%= product_form.check_box :id %>
<% end %>
<%= f.submit %>
<% end %>
I have a habtm model like:
class Recurrence < ActiveRecord::Base
has_many :participations, :include => :user
has_many :users, :through => :participations
accepts_nested_attributes_for :participations
attr_accessible :scheduled_to, :user_id, :user_ids
end
class Participation < ActiveRecord::Base
belongs_to :recurrence
belongs_to :user
attr_accessible :recurrence_id, :user_id
end
class User < ActiveRecord::Base
has_many :participations, :dependent => :delete_all
has_many :recurrences, :through => :participations
accepts_nested_attributes_for :participations
attr_accessible :name, :email, :phone, :recurrence_ids
end
with standard actions for the recurrences_controller (index, show, new, edit, create, update, destroy).
In the view of a single recurrence (/recurrences/10 -> show-action), I try to create/update the participation of user. When I do in the mentioned view something like:
<%= form_for #recurrence do |f| %>
<div class="checkbox">
<% for user in User.find(:all) %>
<div>
<%= check_box_tag "recurrence[user_ids][]", user.id, #recurrence.users.include?(user) %>
<%= user.name %>
</div>
<% end %>
</div>
<div class="actions">
<%= f.submit "Update", :class => 'btn btn-mini btn-primary' %>
</div>
<% end %>
erverything is working fine, I can add or remove the participation for one or more users.
BUT I like to do it - for just a single user, namely the current_user! I tried with the following source:
<%= form_for(#recurrence) do %>
<%= check_box_tag "recurrence[user_id]", current_user.id,
#recurrence.users.include?(current_user) %>
<%= current_user.name %>
<%= submit_tag "Update" %>
<% end %>
which is not working, more detailed
Updating the not changed status: not particpating, doesn't do anything: correct!
Changing status: from not participating - to participating, works for current_user, BUT will also delete the status of a other users: wrong!
Changing status: from participating - to not participating, won't change anything: wrong!
Any help is welcome!
Finaly I want to reduce the Check-Box to Confirm-/Refuse-Buttons with hidden-fields for the recurrence, but proabably there is easier rails-way?
I have recipe and ingredient in a many to many relation.
I have defined the following commands in my presentation.
<div>
<%= render :partial => 'ingredients/form',
:locals => {:form => recipe_form} %>
</div>
the partial begins with
<%= form_for(#ingredient) do |ingredient_form| %>
but received #ingredient nill.
Then I tried
<%= recipe_form.fields_for :ingredients do |builder| %>
<%= render 'ingredient_fields', f: builder %>
<% end %>
where my render was
<p class="fields">
<%= f.text_field :name %>
<%= f.hidden_field :_destroy %>
</p>
but nothing was printed.
then I tried
<% #recipe.ingredients.each do |ingredient| %>
<%= ingredient.name %>
<% end %>
and only then all of the ingredients were printed.
What was I doing wrong in the previous tries ?
Thank you.
my ingredient recipe relation defined as follows
class Ingredient < ActiveRecord::Base
has_many :ingredient_recipes
has_many :recipes, :through => :ingredient_recipes
...
class Recipe < ActiveRecord::Base
has_many :ingredient_recipes
has_many :ingredients, :through => :ingredient_recipes
...
accepts_nested_attributes_for :ingredient_recipes ,:reject_if => lambda { |a| a[:content].blank?}
class IngredientRecipe < ActiveRecord::Base
attr_accessible :created_at, :ingredient_id, :order, :recipe_id
belongs_to :recipe
belongs_to :ingredient
end
You don't exactly specify what you are trying to do, so I am presuming you have a page that shows a recipe, with many ingredients that can be edited and added to. In your controller you have something like:
class RecipeController < ApplicationController
def edit
#recipe = Recipe.find(params[:id]
end
end
I am also presuming that you are looking to have a form that post backs to the create action. I therefore think you want a form like this:
<%= form_for #recipe do |form| %>
<%= label_for :name %>
<%= text_field :name %>
<%= form.fields_for :ingredients do |ingredients_fields| %>
<div class="ingredient">
<%= f.text_field :name %>
<%= f.hidden_field :_destroy %>
</div>
<% end %>
<% end %>
Also, change your recipe to accept nested attributes for ingredients, not ingredient_recipes:
class Recipe < ActiveRecord::Base
has_many :ingredient_recipes
has_many :ingredients, :through => :ingredient_recipes
...
accepts_nested_attributes_for :ingredients, :reject_if => lambda { |a| a[:content].blank?}
And finally, add attr_accessible for your content:
class Ingredient < ActiveRecord::Base
attr_accessible :content
...
Does that work for you?
I am having some issues with nested models in a form, using Rails 3.1rc4.
I presently have models that look like this:
class Sale < ActiveRecord::Base
attr_accessible :customer_id, :vehicle_id, :sale_date
belongs_to :customer
accepts_nested_attributes_for :customer
end
and
class Customer < ActiveRecord::Base
attr_accessible :dealership_id, :first_name, :last_name, :address1, :email
belongs_to :dealership
has_many :sales
has_many :vehicles, :through => :sales
end
I've obviously truncated these slightly, but all the important info is there.
I am attempting to set up a sale form that will also allow me to create a new customer, hence the accepts_nested_attributes_for :customer line in the sale model.
My form view looks like (again truncated, only the important part):
<%= form_for #sale, :html => {:class => 'fullform'} do |f| %>
<%= f.error_messages %>
<%= field_set_tag 'Customer Details' do %>
<% f.fields_for :customer do |builder| %>
<%= builder.label :first_name %><br>
<%= builder.text_field :first_name %>
<% end %>
<% end %>
<% end %>
The problem I am having is that neither the text field nor the label for :first_name are showing up when the form is rendered - there is no error message, it just doesn't appear.
I should mention that I have tried both with and without #sale.customer.build in the new method of my controller, but it seems to have had no effect.
Thanks!
Can anyone suggest what I am doing wrong?
EDIT: For the avoidance of doubt, my sales controller's new method looks like:
def new
#sale = Sale.new
#sale.customer.build
end
Add customer_attributes to your attr_accessible in the Sale model.
Another mistake; Replace:
<% f.fields_for :customer do |builder| %>
With:
<%= f.fields_for :customer do |builder| %>
I have a model Journey which has many Users (drivers). I want to be able with help of accepts_nested_attributes_for to add and remove drivers from a journey. When I add a driver I want to show the user a <select> where she can select one of the users to be one of the drivers belonging to that particular journey. I have come that long:
# Models
class Journey < ActiveRecord::Base
has_many :drivers
accepts_nested_attributes_for :drivers, :allow_destroy => true
has_many :users, :through => :drivers
accepts_nested_attributes_for :users
end
class Driver < ActiveRecord::Base
belongs_to :journey
belongs_to :user
end
class User < ActiveRecord::Base
has_many :drivers
has_many :journeys, :through => :drivers
end
# View _form.html.erb
<% form_for(#journey) do |f| %>
<%= f.error_messages %>
<% f.fields_for :drivers do |d| %>
<%= render :partial => 'driver', :locals => { :f => d } %>
<% end %>
<p><%= f.submit 'Submit' %></p>
<% end %>
# View _driver.html.erb
<p><%= f.collection_select(:id, User.all, :id, :name)%></p>
The error says:
ActiveRecord::AssociationTypeMismatch in JourneysController#create
Driver(#2185315860) expected, got Array(#2151950220)
I suspect that my _driver.html.erb is wrong, but I have no idea how to fix it. Could you please help me out with some hints here?
Your _driver.html.erb should look like this:
<%= f.collection_select(:user_id, User.all, :id, :name) %>
But I'm not sure if this causes the error.
Also when I use accepts_nested_attributes_for for nested models, I do it this way:
# Models
class Journey < ActiveRecord::Base
has_many :drivers
accepts_nested_attributes_for :drivers, :allow_destroy => true
has_many :users, :through => :drivers
end
class Driver < ActiveRecord::Base
belongs_to :journey
belongs_to :user
accepts_nested_attributes_for :users
end
So you can have forms like this:
<% form_for #journey do |f| %>
<% fields_for :drivers do |d| %>
<% fields_for :user do |u| %>
<%= u.text_field :name %>
...
<% end %>
<% end %>
<% end %>