rubyactiverecordnested-attributespadrinofields-for

Assign categories to a newly created post with Ruby and Padrino


I'm working on my ligthweight Padrino CMS which very much resembles the functionalities of Wordpress. When creating a new post I want to be able to assign them to many of the existing categories. Somehow I can not get my form work.

My models look like that:

Post model

 class Post < ActiveRecord::Base
   belongs_to :account
   has_many :categorizations
   has_many :categories, :through => :categorizations
   accepts_nested_attributes_for :categories
 end

Category model

 class Category < ActiveRecord::Base
  has_many :categorizations
  has_many :posts, :through => :categorizations
  belongs_to :category
 end

Categorization model

 class Categorization < ActiveRecord::Base
  belongs_to :post
  belongs_to :category
 end

I have also created a migration for the joint table

 class CreateCategorizations < ActiveRecord::Migration
  def self.up
   create_table :categorizations do |t|
     t.integer :category_id
     t.integer :post_id
     t.timestamps
   end
  end

  def self.down
   drop_table :categorizations
  end
 end

And here is the related part of the form

  <% fields_for :categories do |c| %>
    <fieldset class='control-group <%= error ? 'has-error' : ''%>'>
      <%= c.label 'Category title', :class => 'control-label' %>
      <div class='controls'>
        <%= c.select(:id, :collection => @categories, :fields => [:title, :id], :include_blank => true, :multiple => true, :class => 'form-control input-xlarge input-with-feedback') %>
       <span class='help-inline'><%= error ? c.error_message_on(:id) : "Select a category if there is a parent category" %></span>
     </div>
   </fieldset>
  <% end %>

I don't know what I'm missing but the association is not created. I do not mention categories in the controller during the creation but I do fill up the dropdown with the existing Categories. Somehow I would like to associate them to the new post.

I will greatly appreciate if someone can point me to the right direction with this. The error I get is this:

NoMethodError at /admin/posts/create undefined method `each' for nil:NilClass file: collection_association.rb location: replace line: 383

The forms POST data contains that:

POST

Variable authenticity_token

Value "c760c21a5d1f85bfc19e179b37d56f67"

category_active_record_relation {"id"=>["2", "3"]}

post {"post_name"=>"Test post", "post_type"=>"blogpost", "post_title"=>"Postie", "slug"=>"This is a custom set slug", "post_date"=>"2015-06-30", "post_content"=>"Lorem ipsum dolor sit amet consequtiv", "post_excerpt"=>"Lorem ipsum", "post_status"=>"published", "comment_status"=>"closed", "comment_count"=>"0"}

save_and_continue "Save and continue"


Solution

  • I have managed to answer my own question, the solution was fairly easy, however maybe there is a nicer one, with more magic. Anyway using the CollectionProxy API documentation it became clear that I can assign these categories in the controller.

    admin/controllers/posts.rb

    Just include before the if @post.save

     params[:category_active_record_relation]['id'].each do |category|
        category = Category.find(category)
        @post.categories << category
    end
    

    If I would create new categories than I could use the @post.categories.build(category) method.

    Hope it will help others as well.