Rails ActiveAdmin form for many-to-many relationship via junction table does not work
In my Rails application BlogPosts and BlogCategories, I use the BlogPostCategorization table to combine them. So,
class BlogCategory < ActiveRecord::Base
attr_accessible :name, :created_at, :updated_at, :blog_post_id
validates :name, presence: true, uniqueness: true
has_many :blog_post_categorizations
has_many :blog_posts, :through => :blog_post_categorizations
accepts_nested_attributes_for :blog_posts, allow_destroy: true
end
class BlogPost < ActiveRecord::Base
attr_accessible :body, :created_at, :updated_at, :image_url, :title
validates :body, :image_url, :title, presence: true
validates :title, uniqueness: true
has_many :blog_post_categorizations
has_many :blog_categories, :through => :blog_post_categorizations
accepts_nested_attributes_for :blog_categories, allow_destroy: true
end
class BlogPostCategorization < ActiveRecord::Base
belongs_to :blog_post
belongs_to :blog_category
end
Now through ActiveAdmin, I want to be able to create a new blog post and create categories for that blog post. I have
form do |f|
f.semantic_errors *f.object.errors.keys
f.inputs "Blog Post" do
f.input :title
f.input :body, as: :html_editor
f.input :image_url
end
f.inputs "Blog Categories" do
f.has_many :blog_post_categorizations do |s|
s.input :blog_category
end
end
f.actions
end
But when I try to access the active admin page for a new blog post, I get a rails error saying "undefined method` new_record?" for nil: NilClass "on the line where
f.has_many: blog_post_categorizations do | s |
What am I doing wrong / missing?
Also, below is the blog_category data that is sent in the params hash of the POST request
"blog_categories_attributes"=>{"1408936652467"=>{"name"=>"cooking"}, "1408936656066"=>{"name"=>"eat"}}
source to share
I think this part:
f.inputs "Blog Categories" do
f.has_many :blog_post_categorizations do |s|
s.input :blog_category
end
end
it should be:
f.inputs "Blog Categories" do
f.has_many :blog_categorys do |s|
s.input :name
end
end
EDIT
Considering your other question on this matter, I would recommend (hopefully) a good workaround. Since strong_parameters are used by default in Rails 4 and up, and you are on Rails 3.2.17, let's make your application use it. So there are steps:
-
install
gem 'strong_parameters'
; -
set to false
config.active_record.whitelist_attributes
inconfig/application.rb
; -
include ActiveModel::ForbiddenAttributesProtection
in modelsBlogPost
andBlogCategory
; - get rid of all calls
attr_accessible
.
After doing all this, you can whitelist all parameters in the private method, for example:
private
def blog_post_params
params.require(:blog_post).permit(#all the params here)
end
And in #create action use BlogPost.new(blog_post_params)
(same in other models where you use the included module). Now you can take advantage of strong parameters.
In ActiveAdmin BlogPost
select the whitelist of all allowed options as:
permit_params :body, :created_at, :updated_at, :image_url, :title, blog_categories_attributes: [:id, :name, :_destroy, :blog_post_id]
and in the controller
controller do
def permitted_params
params.permit blog_posts: [:body, :created_at, :updated_at, :image_url, :title, blog_categories_attributes: [:id, :name, :_destroy, :blog_post_id]]
end
end
A more accurate look at the use of strong_pairs in the documentation. And also double check for typos / wrong names / underscores (because I was assuming some stuff).
Good luck!
source to share