Question

I'm actually creating a taxonomy system into my application. Here is my tables schema :

Taxonomies

class CreateTaxonomies < ActiveRecord::Migration
  def change
    create_table :taxonomies do |t|
      t.references :taxonomable, polymorphic: true
      t.integer :term_id
    end
  end
end

Terms

class CreateTerms < ActiveRecord::Migration
  def change
    create_table :terms do |t|
      t.string :name
      t.string :type
      t.integer :parent_id, default: 0
    end
  end
end

and here are my associations :

class Taxonomy < ActiveRecord::Base
  belongs_to :taxonomable, polymorphic: true
end

class Term < ActiveRecord::Base
  self.inheritance_column = :_type_disabled // because I use type as table field
  has_many :taxonomies, as: :taxonomable
end

To make it more generic, I create a concern :

module Taxonomable
  extend ActiveSupport::Concern

  included do
    has_many :taxonomies, as: :taxonomable
  end

  def get_associate_terms
    terms  = self.taxonomies.map { |t| t.term_id }
    taxonomies = Term.find terms
  end
end

and I'm including it into my model :

class Post < ActiveRecord::Base
    include Taxonomable
end

It works fine and I can retreive the associated data using get_associate_terms. My problem is located within my controller and my form. I'm actually saving it like that :

# posts/_form.html.haml
= f.select :taxonomy_ids, @categories.map { |c| [c.name, c.id] }, {}, class: 'form-control'

# PostsController
def create
  @post = current_user.posts.new( post_params )
  if @post.save
    @post.taxonomies.create( term_id: params[:post][:taxonomy_ids] )
    redirect_to posts_path
  else
    render :new
  end
end

This create method is saving the data correctly but if you take a look at the params attribute, you will see that the object taxonomies is waiting for a term_id but I can only use taxonomy_ids in my form. It feels kind of dirty and I wanted to have your point of view to avoid hacking around like that.

Also, and I think this problem is linked with the one above, when editing my item, the select box is not checked the actual matching category associate to the current post.

Any thoughts are welcome.

Thanks a lot

EDIT :
Here is my form

= form_for @post, url: posts_path, html: { multipart: true } do |f|
  = f.select :taxonomy_ids, @categories.map { |c| [c.name, c.id] }, {}, class: 'form-control'

EDIT 2 :
I added the accepts_nested_attributes_for to my concern as it :

module Taxonomable
  include do
    has_many :taxonomies, as: :taxonomable, dependent: :destroy
    accepts_nested_attributes_for :taxonomies
  end
end

and then used fields_for in my form :

= f.fields_for :taxonomies_attributes do |taxo|
  = taxo.label :term_id, 'Categories'
  = taxo.select :term_id, @categories.map { |c| [c.name, c.id] }, {}, class: 'form-control'

When submitting the form, I receive it :

"post"=>{"type"=>"blog", "taxonomies_attributes"=>{"term_id"=>"2"}, "reference"=>"TGKHLKJ-567TYGJGK", "name"=>"My super post"

However, when the post has been saved with success, the associations are not. Any ideas???

EDIT 3 :
In my controller, I added this :

def post_params
  params.require(:post).permit(
    taxonomies_attributes: [:term_id]
  )
end

When submitting the form, I've got the following error :

no implicit conversion of Symbol into Integer

According to that post Rails 4 nested form - no implicit conversion of Symbol into Integer, it's because I'm using taxonomies_attributes in my fields_for as:

= f.fields_for :taxonomies_attributes do |taxo|

However, if I remove it to :

= f.fields_for :taxonomies do |taxo|

The block is displaying nothing except the div wrapping it :

<div class="form-group">
  <!-- Should be display here but nothing -->
</div>

EDIT 4 :
Finally make it works. The fact that the select box was not showing came from the fact that when creating a new resource, my @post has no taxonomies. Doing the following fix that :

def new
  @product    = current_user.products.new
  category    = @product.taxonomies.build
end

thanks to everyone

Was it helpful?

Solution

I am not sure if I completely understand your question, but one thing I noticed is that you don't really need to save in two steps.

Just add the following line to your Taxonomable module (Rails 3)

attr_accessible :taxonomies_attributes
accepts_nested_attributes_for :taxonomies

If you are using Rails 4, add only the accepts_nested_attributes_for to your Taxonomable module and each of the Controllers, make sure to allow taxonomies attributes. For example, in your PostsController, add the following to your

 def post_params
   params.require(:post).permit(:name, taxonomies_attributes: [:name])
 end

Your create will change to:

def create
  @post = current_user.posts.new( post_params )
  if @post.save
    redirect_to posts_path
  else
    render :new
  end
end

This is assuming that your form uses the proper nesting via fields_for - I am not sure about that since you didn't post the form code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top