Using activeadmin in application, and added nested form which creates record twice on create action, update action is woking fine.
Using Course and Image model.
Gemfile
gem 'rails', '~> 5.0.0'
gem 'activeadmin', github: 'activeadmin'
Course.rb
class Course < ApplicationRecord
has_many :images, dependent: :destroy
validates_presence_of :title
accepts_nested_attributes_for :images, allow_destroy: true
end
Image.rb
class Image < ApplicationRecord
belongs_to :course
mount_uploader :image, ImageUploader
validates_presence_of :image
end
active_admin/course.rb
ActiveAdmin.register Course do
permit_params :title, :description, :publish, images_attributes: [:id, :image, :_destroy]
index do
column :title
column (:description) { |c| raw(c.description) }
column :publish
actions
end
show do
attributes_table do
row :title
row (:description) { |c| raw(c.description) }
row :publish
row "Images" do |c|
ul do
c.images.each do |img|
li do
image_tag(img.image.url(:small))
end
end
end
end
end
end
form do |f|
f.inputs "Course Details" do
f.input :title, :placeholder => "eg. General English"
f.input :description
f.input :publish
end
f.inputs "Images" do
f.has_many :images, heading: false, allow_destroy: true, new_record: true, html: {multipart: true} do |i|
i.input :image, :as => :file, :hint => image_tag(i.object.image)
end
end
f.actions
end
end
console log
Processing by Admin::CoursesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"mK74DdPZ37i3YnMjwq2bej2j/+F0BvAXVJbn5KZamoyGq3A1xeBXPLVCfrPdS4mY9RPYvaC2ZMrZdp36RO3DRw==", "course"=>{"course_type_id"=>"2", "title"=>"General Englisj", "description"=>"this is the description of the course", "publish"=>"1", "images_attributes"=>{"0"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0xd585c98 #tempfile=#<Tempfile:/tmp/RackMultipart20160728-8817-5eo5a6.jpg>, #original_filename="pVxrlkgM3GDl.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"course[images_attributes][0][image]\"; filename=\"pVxrlkgM3GDl.jpg\"\r\nContent-Type: image/jpeg\r\n">}}}, "commit"=>"Create Course"}
AdminUser Load (1.3ms) SELECT "admin_users".* FROM "admin_users" WHERE "admin_users"."id" = $1 ORDER BY "admin_users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Location Load (0.9ms) SELECT "locations".* FROM "locations" WHERE 1=0
CACHE (0.0ms) SELECT "locations".* FROM "locations" WHERE 1=0
(0.4ms) BEGIN
SQL (14.3ms) INSERT INTO "courses" ("title", "description", "created_at", "updated_at", "course_type_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["title", "General Englisj"], ["description", "this is the description of the course"], ["created_at", 2016-07-28 08:29:24 UTC], ["updated_at", 2016-07-28 08:29:24 UTC], ["course_type_id", 2]]
SQL (58.6ms) INSERT INTO "images" ("image", "course_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["image", "pVxrlkgM3GDl.jpg"], ["course_id", 36], ["created_at", 2016-07-28 08:29:24 UTC], ["updated_at", 2016-07-28 08:29:24 UTC]]
SQL (0.7ms) INSERT INTO "images" ("image", "course_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["image", "pVxrlkgM3GDl.jpg"], ["course_id", 36], ["created_at", 2016-07-28 08:29:24 UTC], ["updated_at", 2016-07-28 08:29:24 UTC]]
(21.4ms) COMMIT
Redirected to http://localhost:3000/admin/courses/36
Completed 302 Found in 3578ms (ActiveRecord: 174.0ms)
so same image get generate twice in application
Finally installing gem locally in rails 5 application works for me.
instead of using github path
gem 'activeadmin', github: 'activeadmin'
i have used following activeadmin version.
gem 'activeadmin', '~> 1.0.0.pre4'
The best way to overcome this is for you to override the activeadmin create action, you can do something like this
controller do
def create
#course = Course.new(permitted_params[:course])
super
end
end
Related
I have two models.
Parent model Tag:
class Tag < ApplicationRecord
has_many :keywords, inverse_of: :tag, dependent: :destroy
accepts_nested_attributes_for :keywords
validates :keywords, presence: true
end
As you can see tag should have at least one keyword.
Child model Keyword:
class Keyword < ApplicationRecord
belongs_to :tag, inverse_of: :keywords
validates :tag, presence: true
end
Here is the code of FactoryGirl factories
tag factory:
FactoryGirl.define do
factory :tag do
sequence(:name) { |n| "Tag#{n}" }
after(:build) do |tag_object|
tag_object.keywords << build(:keyword, tag: tag_object)
end
end
end
keyword factory:
FactoryGirl.define do
factory :keyword do
tag
sequence(:name) { |n| "Keyword#{n}" }
end
end
When I create a new record in keywords table with keyword factory it creates one more record in keywords table which is associated with the same parent record in tags table.
How to omit creating one more record in keywords table and keep factories valid?
irb(main):023:0> FactoryGirl.create :keyword
(0.1ms) BEGIN
Keyword Exists (0.7ms) SELECT 1 AS one FROM "keywords" WHERE "keywords"."name" = $1 LIMIT $2 [["name", "Keyword1"], ["LIMIT", 1]]
Tag Exists (0.3ms) SELECT 1 AS one FROM "tags" WHERE "tags"."name" = $1 LIMIT $2 [["name", "Tag1"], ["LIMIT", 1]]
SQL (0.5ms) INSERT INTO "tags" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["name", "Tag1"], ["created_at", 2017-01-21 19:20:14 UTC], ["updated_at", 2017-01-21 19:20:14 UTC]]
SQL (0.6ms) INSERT INTO "keywords" ("tag_id", "name", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["tag_id", 36], ["name", "Keyword1"], ["created_at", 2017-01-21 19:20:14 UTC], ["updated_at", 2017-01-21 19:20:14 UTC]]
(10.4ms) COMMIT
(0.1ms) BEGIN
Keyword Exists (0.4ms) SELECT 1 AS one FROM "keywords" WHERE "keywords"."name" = $1 LIMIT $2 [["name", "Keyword2"], ["LIMIT", 1]]
SQL (0.4ms) INSERT INTO "keywords" ("tag_id", "name", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["tag_id", 36], ["name", "Keyword2"], ["created_at", 2017-01-21 19:20:14 UTC], ["updated_at", 2017-01-21 19:20:14 UTC]]
(4.4ms) COMMIT
=> #<Keyword id: 63, tag_id: 36, name: "Keyword2", created_at: "2017-01-21 19:20:14", updated_at: "2017-01-21 19:20:14">
irb(main):024:0>
You can see that it created a record in tags, a record in keywords table, and after that one more record in keywords table.
FactoryGirl creates all the stated associations for the model during the build process. Which means a FactoryGirl.build :keyword will do a FactoryGirl.create :tag so it will have an id for Keyword#tag_id to help pass validations on the Keyword model.
This is consistent with the database activity you are seeing.
irb(main):023:0> FactoryGirl.create :keyword
### keywordA = Keyword.new
### call create(:tag) because of association
### tag1 = Tag.new
### call build(:keyword) in after(:build)
###.keywordB.new(tag: tag1) # which prevents trying to make a new tag!
### tag1.save # which saves the keywordB
(0.1ms) BEGIN
Keyword Exists (0.7ms) SELECT 1 AS one FROM "keywords" WHERE "keywords"."name" = $1 LIMIT $2 [["name", "Keyword1"], ["LIMIT", 1]]
Tag Exists (0.3ms) SELECT 1 AS one FROM "tags" WHERE "tags"."name" = $1 LIMIT $2 [["name", "Tag1"], ["LIMIT", 1]]
SQL (0.5ms) INSERT INTO "tags" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["name", "Tag1"], ["created_at", 2017-01-21 19:20:14 UTC], ["updated_at", 2017-01-21 19:20:14 UTC]]
SQL (0.6ms) INSERT INTO "keywords" ("tag_id", "name", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["tag_id", 36], ["name", "Keyword1"], ["created_at", 2017-01-21 19:20:14 UTC], ["updated_at", 2017-01-21 19:20:14 UTC]]
(10.4ms) COMMIT
### keywordA.tag = tag1
### keywordA.save
(0.1ms) BEGIN
Keyword Exists (0.4ms) SELECT 1 AS one FROM "keywords" WHERE "keywords"."name" = $1 LIMIT $2 [["name", "Keyword2"], ["LIMIT", 1]]
SQL (0.4ms) INSERT INTO "keywords" ("tag_id", "name", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["tag_id", 36], ["name", "Keyword2"], ["created_at", 2017-01-21 19:20:14 UTC], ["updated_at", 2017-01-21 19:20:14 UTC]]
(4.4ms) COMMIT
### Since keywordA gets saved after keywordB,
### keywordB gets a 1 from the sequence and
### keywordA gets a 2 from the sequence
=> #<Keyword id: 63, tag_id: 36, name: "Keyword2", created_at: "2017-01-21 19:20:14", updated_at: "2017-01-21 19:20:14">
irb(main):024:0>
This is just the gist of what happens. Personally, I cannot imagine wanting a keyword without it's tag based on the database's schema so I would just call create(:tag) and get the first keyword as mentioned before. But the schema is simple enough so the following should hold up in 100% of the situations we would want to test:
FactoryGirl.define do
factory :tag do
sequence(:name) { |n| "Tag#{n}" }
after(:build) do |this|
this.keywords << build(:keyword) if this.keywords.empty?
end
end
end
FactoryGirl.define do
factory :keyword do
sequence(:name) { |n| "Keyword#{n}" }
after(:build) do |this|
this.tag ||= build(:tag)
end
end
end
build(:tag) # unsaved
build(:tag).keyword # also unsaved
create(:tag) # saved
create(:tag).keyword # also saved
build(:keyword) # unsaved
build(:keyword).tag # also unsaved
create(:keyword) # saved
create(:keyword).tag # also saved
# And it still lets you be specific
create(:tag, keywords: [create(:keyword, name: "More of a phrase")])
create(:keyword, tag: create(:tag, name: "Pop Me!"))
A few more options to consider:
# Fake the association
FactoryGirl.define do
factory :keyword do
sequence(:name) { |n| "Keyword#{n}" }
tag_id 1 # Danger!
# Will make it pass validation but you
# will forget and #tag will not be found
# or not what you expect
end
end
# use a trait
FactoryGirl.define do
factory :keyword do
sequence(:name) { |n| "Keyword#{n}" }
trait :with_tag do
tag
end
end
end
# make a new factory
FactoryGirl.define do
# do not need parent if inside the "factory :tag do"
factory :tag_with_keyword, parent: :tag do
sequence(:name) { |n| "Tag#{n}" }
keyword
end
end
# but now we are back to it creating the keyword on build(:tag)
FactoryGirl does give you enough options to solve many situations but the trick is understanding how it sets up the associations and try to stay away from setting up implicit circular ones.
Keywords and tags cannot exist independent of each other. Your tag factory creates a keyword every time it is called, so you should be calling the tag factory. Try this:
tag = FactoryGirl.create(:tag)
keyword = tag.keywords.first
I cannot seem to find out why my has_many record will not save. I've test with has_one in the models and it works fine but when I change it to has_many it doesn't work. I've check a few simular stackoverflow posts and I seem to have this correct but it doesn't work. Nested form in activeadmin not saving updates & ActiveAdmin Form not saving nested object
This is for Rails version 5.1.0.alpha and Activeadmin version 1.0.0.pre4
I do not get any errors nor do I see the nested object get created though I see the params when I create an object here is the output
Started POST "/admin/abq_districts" for ::1 at 2016-12-05 10:04:44 -0700
Processing by Admin::AbqDistrictsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"bHzfUG8xIMI66tTHNwSmL5FVnaa4nyuzJ3AM8tnLJSq69TLP1o8iUcLLeNnoS0FVgA8ju3x7Ioc+EV4xRv/T7Q==", "abq_districts_district"=>{"name"=>"test district", "title"=>"", "sub_title"=>"", "paragraph"=>"", "sections_attributes"=>{"0"=>{"text"=>"test section"}}}, "commit"=>"Create District"}
AdminUser Load (1.0ms) SELECT "admin_users".* FROM "admin_users" WHERE "admin_users"."id" = $1 ORDER BY "admin_users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.2ms) BEGIN
SQL (0.4ms) INSERT INTO "abq_districts_districts" ("name", "title", "sub_title", "paragraph", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["name", "test district"], ["title", ""], ["sub_title", ""], ["paragraph", ""], ["created_at", "2016-12-05 17:04:44.756215"], ["updated_at", "2016-12-05 17:04:44.756215"]]
(0.6ms) COMMIT
Redirected to http://localhost:3000/admin/abq_districts/41
Completed 302 Found in 34ms (ActiveRecord: 2.1ms)
here is my info
ActiveAdmin.register
ActiveAdmin.register AbqDistricts::District, as: 'ABQ Districts' do
permit_params :name, :title, :sub_title, :paragraph, sections_attributes: [ :text, :_destroy ]
index do
selectable_column
id_column
column :name
column :title
column :sub_title
column :paragraph
column :created_at
column :updated_at
actions
end
filter :name
filter :title
filter :updated_at
filter :created_at
form do |f|
f.inputs "Admin Details" do
f.input :name
f.input :title
f.input :sub_title
f.input :paragraph
f.inputs do
f.has_many :sections, heading: 'Sections', allow_destroy: true, new_record: true do |a|
a.input :text
end
end
end
f.actions
end
end
abq_districts.rb
module AbqDistricts
def self.table_name_prefix
'abq_districts_'
end
end
district.rb
class AbqDistricts::District < ApplicationRecord
has_many :sections, foreign_key: :abq_districts_district_id
accepts_nested_attributes_for :sections, allow_destroy: true
end
section.rb
class AbqDistricts::Section < ApplicationRecord
belongs_to :abq_districts_district
validates_presence_of :abq_districts_district
end
UPDATE
I just testing in the rails console and it worked fine (still does not work through ActiveAdmin browser
2.3.0 :001 > params = {"name"=>"test district", "title"=>"", "sub_title"=>"", "paragraph"=>"", "sections_attributes"=>{"0"=>{"text"=>"test section"}}}
=> {"name"=>"test district", "title"=>"", "sub_title"=>"", "paragraph"=>"", "sections_attributes"=>{"0"=>{"text"=>"test section"}}}
2.3.0 :002 > d = AbqDistricts::District.create(params)
(0.2ms) BEGIN
SQL (0.5ms) INSERT INTO "abq_districts_districts" ("name", "title", "sub_title", "paragraph", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["name", "test district"], ["title", ""], ["sub_title", ""], ["paragraph", ""], ["created_at", "2016-12-05 18:58:02.973482"], ["updated_at", "2016-12-05 18:58:02.973482"]]
SQL (2.2ms) INSERT INTO "abq_districts_sections" ("text", "abq_districts_district_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["text", "test section"], ["abq_districts_district_id", 63], ["created_at", "2016-12-05 18:58:02.979025"], ["updated_at", "2016-12-05 18:58:02.979025"]]
(0.4ms) COMMIT
=> #<AbqDistricts::District id: 63, name: "test district", title: "", sub_title: "", paragraph: "", created_at: "2016-12-05 18:58:02", updated_at: "2016-12-05 18:58:02">
I was able to patch by adding in ActiveAdmin.register
controller do
def create
#section = AbqDistricts::District.create!(permitted_params[:abq_district].as_json)
redirect_to admin_faq_sections_path, notice: "Section was successfully created!"
end
end
This is just a patch. Notice and the only way it worked is if I used .as_json
it would not work with to_json or just the params alone
I cannot seem to save my record with nested forms.
This is what pry says:
pry(#<VenuesController>)> #venue.save
(0.3ms) begin transaction
Tag Exists (0.2ms) SELECT 1 AS one FROM "tags" WHERE ("tags"."name" = 'All ' AND "tags"."id" != 2) LIMIT 1
Tag Exists (0.1ms) SELECT 1 AS one FROM "tags" WHERE "tags"."name" = '' LIMIT 1
(0.1ms) rollback transaction
=> false
I thought I followed everything correctly.
This is my nested form for tags
Tags:
<%= f.collection_check_boxes :tag_ids, Tag.all, :id, :name %><br>
Make a New Tag Here: <br>
<%= f.fields_for :tags, Tag.new do |tag_field| %>
<%= tag_field.label :name_tag %>
<%= tag_field.text_field :name %>
<% end %>
This is my venue model
class Venue < ActiveRecord::Base
has_many :venue_tags
has_many :tags, :through => :venue_tags
accepts_nested_attributes_for :tags, allow_destroy: true
end
And my tag model
class Tag < ActiveRecord::Base
has_many :venue_tags
has_many :venues, :through => :venue_tags
validates_uniqueness_of :name
end
However, when take off the 'validate uniqueness of name', I can save it, but new tags are added by itself.
And this is the pry log that tells it's true, but now I'm getting the correct tag added to the venue, but ALSO a new tag added to the venue (one I did not create myself). I am assuming this is happening because the New Tag Fields_for text was blank, which created a new tag by itself.
(0.2ms) begin transaction
SQL (0.6ms) INSERT INTO "venues" ("name", "address", "discount", "latitude", "longitude", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["name", "SPICEBOX"], ["address", "33 Pell St, New York, NY 10013, United States"], ["discount", "10% OFF with Student ID"], ["latitude", 40.714831], ["longitude", -73.998628], ["created_at", "2015-11-03 06:12:52.400643"], ["updated_at", "2015-11-03 06:12:52.400643"]]
SQL (0.2ms) INSERT INTO "venue_tags" ("tag_id", "venue_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["tag_id", 2], ["venue_id", 11], ["created_at", "2015-11-03 06:12:52.404715"], ["updated_at", "2015-11-03 06:12:52.404715"]]
SQL (0.2ms) INSERT INTO "tags" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", ""], ["created_at", "2015-11-03 06:12:52.408821"], ["updated_at", "2015-11-03 06:12:52.408821"]]
SQL (0.1ms) INSERT INTO "venue_tags" ("venue_id", "tag_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["venue_id", 11], ["tag_id", 9], ["created_at", "2015-11-03 06:12:52.411692"], ["updated_at", "2015-11-03 06:12:52.411692"]]
(1.4ms) commit transaction
=> true
You should probably add a validates :presence to tag name. You seem to have a tag in your db that has no name and when you add another with no name it is not unique and won't pass validations.
Take a look at the form or the strong parameters to see how that value is being cleared, if it is.
If it's blank because it was intentionally submitted that way, you can ignore it if blank.
accepts_nested_attributes_for :tags, allow_destroy: true, :reject_if => lambda { |a| a[:name].blank? }
However, when take off the 'validate uniqueness of name', I can save
it
Check the database for the name and see if it already exists.
Since you are able to save the record, you code is probably ok.
To see why the record doesn't want to save, you can ask out the errors of the object you are trying to save. You can do this in your pry console.
#venue.save
...
=> false
#venue.errors.messages
=> ...
It will probably tell you that you already have a record with the same name. If that it's the case, then it would make sense your record isn't saving.
I've looked for this exhaustively on StackOverflow and Google but found no answer to help me out, so I'm asking this though I know the subject has been hardly discussed here.
I have a HABTM relation between Contests and Subjects, my log shows de array of id's when posting a new contest or editing an existing one, but it simply doesn't record anything in my postgres DB.
I'm using ActiveAdmin 1.0 and Rails 4
Below follows my code:
class Contest < ActiveRecord::Base
attr_accessor :subjects_ids
has_and_belongs_to_many :subjects
belongs_to :examination_board
belongs_to :bureau
belongs_to :role
belongs_to :degree
belongs_to :career
end
class Subject < ActiveRecord::Base
attr_accessor :contests_ids
has_many :questions
has_and_belongs_to_many :contests
end
ActiveAdmin.register Contest do
permit_params :name,
:year,
:state,
:city,
:examination_board_id,
:role_id,
:degree_id,
:career_id,
:bureau_id,
subjects_ids: [:id]
# scope :states
index do
column "Nome", :name
column "Banca Examinadora", :examination_board
column "Matérias" do |subject|
div :class => 'subjects' do
subjects = ['yo','la','ho'].join(', ')
end
end
actions
end
form do |f|
f.semantic_errors
f.inputs
f.input :subjects, as: :check_boxes, collection: Subject.all
f.actions
end
end
My log:
Started POST "/admin/contests" for ::1 at 2015-02-27 21:20:05 -0300
Processing by Admin::ContestsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"JYF2JXwaY+6tz++H55QeECpKTjYR+bx0uGG50sIPGWS0AF06inUFPJQtPpp1TlqRPtQmdIZ5B/jAyxfxEgFCtQ==", "contest"=>{"examination_board_id"=>"1", "bureau_id"=>"1", "role_id"=>"1", "degree_id"=>"1", "career_id"=>"1", "name"=>"Concurso Teste 03", "year"=>"2015", "state"=>"São Paulo", "city"=>"São Paulo", "subject_ids"=>["", "1", "3"]}, "commit"=>"Create Contest"}
AdminUser Load (0.2ms) SELECT "admin_users".* FROM "admin_users" WHERE "admin_users"."id" = $1 ORDER BY "admin_users"."id" ASC LIMIT 1 [["id", 1]]
Unpermitted parameter: subject_ids
(0.2ms) BEGIN
SQL (0.3ms) INSERT INTO "contests" ("name", "year", "state", "city", "examination_board_id", "role_id", "degree_id", "career_id", "bureau_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING "id" [["name", "Concurso Teste 03"], ["year", 2015], ["state", "São Paulo"], ["city", "São Paulo"], ["examination_board_id", 1], ["role_id", 1], ["degree_id", 1], ["career_id", 1], ["bureau_id", 1], ["created_at", "2015-02-28 00:20:05.163771"], ["updated_at", "2015-02-28 00:20:05.163771"]]
(5.1ms) COMMIT
Redirected to http://localhost:3000/admin/contests/3
Completed 302 Found in 50ms (ActiveRecord: 5.8ms)
I appreciate any suggestion, thank you all!
Well, it turns out that I was not far from making it. My only problem was this line:
subjects_ids: [:id]
I shouldn't have put that ":id" plus the correct name is "subject_ids".
That's it, it works like a charm now.
I'm trying to create my Dog and add categories to it but I get the error:
WARNING: Can't mass-assign protected attributes: category_id
SQL (49.0ms) INSERT INTO "categorizations" ("dog_id", "category_id", "created_at", "cat_id", "mouse_id", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["dog_id", 7], ["category_id", 1], ["created_at", Sun, 29 Jul 2012 20:34:27 JST +09:00], ["cat_id", nil], ["mouse_id", nil], ["updated_at", Sun, 29 Jul 2012 20:34:27 JST +09:00]]
(105.0ms) COMMIT
Completed 500 Internal Server Error in 669ms
ArgumentError (too few arguments):
app/controllers/dogs_controller.rb:7:in `format'
app/controllers/dogs_controller.rb:7:in `create'
Don't know why this is true since I have in my model:
class Dog < ActiveRecord::Base
attr_accessible :name, :category_ids
belongs_to :user
has_many :categorizations
has_many :categories, :through => :categorizations
accepts_nested_attributes_for :categories
validates :name, :presence => true
validates :user_id, :presence => true
end
As you can see the join table is Categorizations:
class Categorization < ActiveRecord::Base
belongs_to :dog
belongs_to :category
belongs_to :cat
belongs_to :mouse
end
And I select the categories desired on the form. Here's the model:
class Category < ActiveRecord::Base
attr_accessible :name
belongs_to :user
has_many :categorizations
has_many :dogs, :through => :categorizations
has_many :cats, :through => :categorizations
has_many :mouses, :through => :categorizations
validates :name, :presence => true, :uniqueness => true
before_validation :downcase_name
private
def downcase_name
self.name = self.name.downcase if self.name.present?
end
end
For some strange reason it still assigns the categories when looking in the database but this may be causing other issues i'm having. What could be the problem?
UPDATE
Here is my Dog form:
<%= form_for(#dog, :remote => true) do |f| %>
<%= f.label :name, "Name" %>
<%= f.text_field :name %>
<%= f.label :category, "Categories" %>
<%= f.select :category_ids, Category.all.collect {|c| [c.name, c.id]}, {}, { :multiple => true, } %>
<% end %>
Still get the Mass-assignment error when I try:
attr_accessible :name, :category_ids
WARNING: Can't mass-assign protected attributes: category_id
attr_accessible :name, :category_id, :category_ids
# It says this for each category I want to put on the Dog.
WARNING: Can't mass-assign protected attributes: category_id
attr_accessible :name, :category_id
WARNING: Can't mass-assign protected attributes: category_ids
UPDATE 2
I was able to get rid of the ArgumentError though by adding the respond_to for the controller action:
def create
#dog = current_user.dogs.new(params[:dog])
respond_to do |format|
if #dog.save
format.js
else
format.js
end
end
end
If add 2 or more categories to the Dog ( in this case 3) . It adds them in the database and does mass assign them but server keeps saying this in the log:
Started POST "/dogs" for 127.0.0.1 at 2012-07-29 20:44:15 -0400
Processing by DogsController#create as JS
Parameters: {"utf8"=>"Γ£ô", "authenticity_token"=>"wuPqA6e8MqF/yW3VQ+sfLiyf0olOWgEpnVC2qawQE0I=", "dog"
Add Dog"}
User Load (2.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Category Load (0.0ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" IN (1, 2, 3)
(1.0ms) BEGIN
(0.0ms) COMMIT
(0.0ms) BEGIN
(1.0ms) SELECT 1 FROM "categories" WHERE ("categories"."name" = 'furry' AND "categories"."id" != 1) LI
(1.0ms) SELECT 1 FROM "categories" WHERE ("categories"."name" = 'house trained' AND "categories"."id" != 2) LIMIT
(0.0ms) SELECT 1 FROM "categories" WHERE ("categories"."name" = 'wild' AND "categories"."id" != 3) LIMIT
SQL (1.0ms) INSERT INTO "dogs" ("created_at", "name", "updated_at", "user_id") VALUES ($1, $2, $3, $4
"name", "Omni Dog"], ["updated_at", Mon, 30 Jul 2012 09:44:15 JST +09:00], ["user_id", 1]]
WARNING: Can't mass-assign protected attributes: category_id
[1m[35mSQL (1.0ms)[0m INSERT INTO "categorizations" ("dog_id", "category_id", "created_at", "cat_id", "mouse_id", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["dog_id", 31], ["category_id", 1], ["created_at", Mon, 30 Jul 2012 09:44:15 JST +09:00], ["cat__id", nil], ["mouse_id", nil], ["updated_at", Mon, 30 Jul 2012 09:44:15 JST +09:00]]
WARNING: Can't mass-assign protected attributes: category_id
[1m[36mSQL (1.0ms)[0m [1mINSERT INTO "categorizations" ("dog_id", "category_id", "created_at", "cat__id", "mouse_id", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"[0m [["dog_id", 31], ["category_id", 2], ["created_at", Mon, 30 Jul 2012 09:44:16 JST +09:00], ["cat__id", nil], ["mouse_id", nil], ["updated_at", Mon, 30 Jul 2012 09:44:16 JST +09:00]]
WARNING: Can't mass-assign protected attributes: category_id
[1m[35mSQL (1.0ms)[0m INSERT INTO "categorizations" ("dog_id", "category_id", "created_at", "cat__id", "mouse_id", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["dog_id", 31], ["category_id", 3], ["created_at", Mon, 30 Jul 2012 09:44:16 JST +09:00], ["cat__id", nil], ["mouse_id", nil], ["updated_at", Mon, 30 Jul 2012 09:44:16 JST +09:00]]
Rendered dogs/_dog.html.erb (1.0ms)
Rendered dogs/create.js.erb (3.0ms)
Completed 200 OK in 203ms (Views: 25.0ms | ActiveRecord: 52.0ms)
Is this a problem if it's technically working?
You have an extra s here:
class Dog < ActiveRecord::Base
attr_accessible :name, :category_ids
...
category_id is a column on the dogs table, So, just remove it:
class Dog < ActiveRecord::Base
attr_accessible :name, :category_id
I needed to change this:
#dog = current_user.dogs.new(params[:dog])
To this instad:
#dog = current_user.dogs.build(params[:dog])
And then it started to work for me.