Reputation: 427
I'm new to rails and working on a rails app and I'm stuck pondering this issue.
I have three models
class Product < ActiveRecord::Base
attr_accessible :name, :issn, :category, :user_products_attributes
validates_presence_of :name, :issn, :category
validates_numericality_of :issn, :message => "has to be a number"
has_many :user_products
has_many :users, :through => :user_products
accepts_nested_attributes_for :user_products
end
class UserProduct < ActiveRecord::Base
attr_accessible :price, :category
validates_presence_of :price, :category
validates_numericality_of :price, :message => "has to be a number"
belongs_to :user
belongs_to :product
end
class user < ActiveRecord::Base
# devise authentication here
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
has_many :user_products, :dependent => :destroy
has_many :products, :through => :user_products
end
Product controller
def new
@product = product.new
@product.user_products.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: @product }
end
end
So the question is this: I want the user to enter the info for the product in the form but it also involves putting in the price of the product which exists in a different model/table (user_product) that is associated with product. How can I do this? You can see that my form_for uses @product.
Any help will be appreciated.
<div class="span8">
<div id="listBoxWrapper">
<fieldset>
<%= form_for(@product, :html => { :class => "form-inline" }, :style => "margin-bottom: 60px" ) do |f| %>
<div class="control-group">
<label class="control-label" for="Category">Category</label>
<div class="controls">
<%= f.text_field :category, :class => 'input-xlarge', :id => "Category" %>
</div>
</div>
<div class="control-group" style="display: inline-table;">
<label class="control-label" for="First Name">Price($/Month)</label>
<div class="controls">
<%= product.fields_for :user_products do |p| %>
<%= p.text_field :price, :class => 'input-xlarge input-name' %>
<% end %>
</div>
</div>
Upvotes: 1
Views: 2498
Reputation: 5317
It should be kind of following
<%= form_for(@product) do |product| %>
<%= product.text_field :name, :class => 'input-xlarge input-name' %>
<%= product.fields_for :user_products do |user_product| %>
<%= user_product.text_field :price, :class => 'input-xlarge input-name' %>
and you need to build your user_products
for the @product
in your controller. Like
@product.user_products.build
and your Product
model should have the following
accepts_nested_attributes_for :user_products
This will make it realized that user_products
values might come while saving a product entity.
Edit:
Just explaining the skeleton of nested form
form_for(@object) do |object_form_builder|
# call any field generator helper function by object_form_builder like
object_form_builder.text_field
object_form_builder.check_box
# so on...
#Now for nested forms get the nested objects from the builder like
object_form_builder.fields_for :nested_objects do |nested_object_builder|
#generate the fields for this with nested_object_builder. Like
nested_object_builder.text_field
# so on...
end
end
yes its always convenient to use short names for object builders like you usually use f
for form_builder
.
Upvotes: 2