I can't get the has_many :through Association to work. And do I need to set something extra in the create method from the post_controller, to save also the post_category? (Below the code, the errors and my tries)
I have a has_many :through Association with post, post_category and as join table categorization as follows:
The Post Model:
class Post < ApplicationRecord
has_many :categorizations
has_many :post_categories, :through => :categorizations
end
The Post::Category Model (Used namespacing for better project structure):
class Post::Category < ApplicationRecord
has_many :categorizations
has_many :posts, :through => :categorizations
end
The Categorization Model (Used class_name, cause of the namespacing of Post::Category):
class Categorization < ApplicationRecord
belongs_to :post
belongs_to :post_category, :class_name => 'Post::Category'
end
And then I have in the view a select where I create a post with a post_category:
<div class="form-group">
<%= f.label :post_categories, :class => 'control-label', :value => 'Category: ' %>
<%= f.select :post_categories, options_from_collection_for_select(all_post_categories, :id, :name), {}, {class: 'selectpicker', :'data-live-search' => 'true', required: 'false' } %>
</div>
In the posts_controller, I permitted the :post_categories
symbol:
def post_params
params.require(:post).permit(:post_categories)
end
Here is my migration file for the Association:
class CreateCategorizations < ActiveRecord::Migration[5.0]
def change
create_table :categorizations do |t|
t.integer :post_id
t.integer :post_category_id
t.timestamps
end
add_index :categorizations, :post_id
add_index :categorizations, :post_category_id
# multiple-key index enforces uniqueness on (post_id, post_category_id)
# pairs, so that a category can't have the same post twice
add_index :categorizations, [:post_id, :post_category_id], unique: true
end
end
When I try to submit the form, I get the following error in the logs:
NoMethodError (undefined method `each' for "3":String):
app/controllers/posts_controller.rb:32:in `create'
So I searched for some answers ok -> You can't assign string to association.
I tried another way to make the association going to work.
So I tried using the post_category_id, like recommended here
I set in the select of the view
<%= f.select :post_category_id, options_from_collection_for_select(all_post_categories, :id, :name), {}, {class: 'selectpicker', :'data-live-search' => 'true', required: 'false' } %>
then in the posts_controller permit the category_id:
def post_params
params.require(:post).permit(:post_category_id)
end
and in the Post model:
class Post < ApplicationRecord
has_many :categorizations
has_many :post_category_id, :through => :categorizations
end
This is the new error:
Could not find the source association(s) "post_category_id" or :post_category_id in model Categorization. Try 'has_many :post_category_id, :through => :categorizations, :source => <name>'. Is it one of post or post_category?
Ok makes sense, cause there is no post_category_id
association.
Update:
The post_params:
<ActionController::Parameters {"content"=>"content", "post_categories"=>"2"} permitted: true>
I figured out a right solution for me with this answer and this question.
First solution to just save one Post::Category with a Post
Regarding to this answer, I had to change my permit parameter in the posts_controller to this:
def post_params
params.require(:post).permit(:post_category_ids)
end
Then I need also to change the select in the view where I create a post with a post_category to this:
<div class="form-group">
<%= f.label :post_category_ids, :class => 'control-label', :value => 'Category: ' %>
<%= f.select :post_category_ids, options_from_collection_for_select(all_post_categories, :id, :name), {}, {class: 'selectpicker', :'data-live-search' => 'true', required: 'false' } %>
</div>
That's it. The rest of the code is still the same as I showed before my second try in my question.
Second solution to save multiple Post::Category with a Post
Regarding to this question, I need to change my permit parameter in the posts_controller to this:
def post_params
params.require(:post).permit(:post_category_ids => [])
end
And to select more than one Post::Category at the same time, I need to add multiple: 'true'
to the select in the view:
<div class="form-group">
<%= f.label :post_category_ids, :class => 'control-label', :value => 'Category: ' %>
<%= f.select :post_category_ids, options_from_collection_for_select(all_post_categories, :id, :name), {}, {class: 'selectpicker', :'data-live-search' => 'true', required: 'false', multiple: 'true' } %>
</div>