Question

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
Was it helpful?

Solution

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]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top