6

I'm using rails to create a new product and want to add a category to every product.

I have three tables: product, category, and categorizations (which stores the relationship between products and categories). I'm trying to use nested attributes to manage the creation of the categorizations, but unsure how my controller and view/form should be updated so that new products also update the categorizations table.

Here are my models:

class Product < ActiveRecord::Base
 belongs_to :users
 has_many :categorizations
 has_many :categories, :through => :categorizations
 has_attached_file :photo
 accepts_nested_attributes_for :categorizations, allow_destroy: true

 attr_accessible :description, :name, :price, :photo

 validates :user_id, presence: true

end


class Category < ActiveRecord::Base
 attr_accessible :description, :name, :parent_id
 acts_as_tree
 has_many :categorizations, dependent: :destroy
 has_many :products, :through => :categorizations

end


class Categorization < ActiveRecord::Base
  belongs_to :category
  belongs_to :product
  attr_accessible :category_id, :created_at, :position, :product_id

end

Here is my new product controller:

def new
    @product = Product.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @product }
    end
  end

And here is my view form:

<%= form_for @product, :html => { :multipart => true } do |f| %>
  <% if @product.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h2>

      <ul>
      <% @product.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :description %><br />
    <%= f.text_field :description %>
  </div>
  <div class="field">
    <%= f.label :price %><br />
    <%= f.number_field :price %>
  </div>
<div class="field">
<%= f.file_field :photo %>
</div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

How should I update my controller so that both the product and the categorization tables are updated when a new product is added? How do I update my view file so that the categories appear in a drop down menu?

william tell
  • 4,352
  • 6
  • 23
  • 27
  • *but unsure how my ... view/form should be updated* -- we also have no idea as you didn't expose them. – jdoe May 14 '12 at 07:30
  • Hi @jdoe - I added the view file here. Just the standard one created by the rails generate command. – william tell May 14 '12 at 15:10

4 Answers4

4

I see that product has_many categories. It's naturally to allow the user to specify them at product creation/edition. One approach is described here (via checkboxes to assign categories to your product). Another way: create product as usually and allow adding/removing categories on its edit page, like:

 cat_1 [+]
 cat_2 [-]
 cat_3 [+]

Also take a look at Railcasts, like this one for doing it on a more beautiful way.

jdoe
  • 15,665
  • 2
  • 46
  • 48
0

First of all to show categories in view file use something like following to show category in dropdown

<%= select_tag("category_id[]", options_for_select(Category.find(:all).collect { |cat| [cat.category_name, cat.id] }, @product.category.collect { |cat| cat.id}))%>

Then in create method of product controller do something like following

@product = Product.create(params[:category])
@product.category = Category.find(params[:category_id]) if params[:category_id]

I hope this would help you.
Thanks.

urjit on rails
  • 1,763
  • 4
  • 19
  • 36
0

Tutorial for Nested Model Form from RailsCasts Maybe help you, or maybe It will help someone else.

quatermain
  • 1,442
  • 2
  • 18
  • 33
0

Here is what I addded to my Product view file, in _form.html - this created multiple check boxes that I could use to select multiple categories per product:

</div class="field">
<% Category.all.each do |category| %>
<%= check_box_tag "product[category_ids][]", category.id %>
<%= label_tag dom_id(category), category.name %><br>
<% end %>
william tell
  • 4,352
  • 6
  • 23
  • 27