I have two controllers categories and products. Products belongs to categories but I'm having trouble setting up the relationship.
In category.rb
has_many :products
In product.rb
belongs_to :category
validates :category_id, :presence => true
validates :name, :presence => true, :uniqueness => true
When I try to create a new product, the record does not save because category_id is blank. My product form looks like so:
<%= form_for @product, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.hidden_field('category_id', :value => params[:category_id]) %>
<div class="control-group">
<%= f.label :name, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :name, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :category, :class => 'control-label' %>
<div class="controls">
<% @cat = Category.all %>
<%= select_tag 'category', options_from_collection_for_select(@cat, 'id', 'name') %>
</div>
</div>
<div class="control-group">
<%= f.label :price, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :price, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :description, :class => 'control-label' %>
<div class="controls">
<%= f.text_area :description, :class => "tinymce", :rows => 10, :cols => 120 %>
<%= tinymce %>
</div>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
products_path, :class => 'btn' %>
</div>
<% end %>
and in the products controller I have:
def new
@product = Product.new
@category = @product.category
end
I've tried looking through other questions on SO but haven't had any luck finding the correct way to pass the category id to products. I hope I've been clear enough and I'm happy to provide any extra information that may be needed.
EDIT
I've made the following changes to the products controller as suggested by I not get the error: Cannot find Category without an ID
before_filter :set_category, only: [:create]
def set_category
@category = Category.find(params[:category_id])
end
def create
@product = @category.products.new(product_params)
#....
end
I'm using nested routes like so:
resources :categories do
resources :products
end
You should set product's category in create
action:
def create
@product = @category.products.new(product_params)
# ...
end
in new
action, you should just have
def create
@product = Product.new
end
Of course, you need to set @category
(@category = Category.find(params[:category_id])
) instance variable before (in before_filter
, for example).
You should also remove this hidden field from view and remove category_id
from allowed params if you don't want users to set category_id
manually and set form_for
arguments properly, since you're using nested resources:
form_for [@category, @product]