Has many :through association: Can't mass-assign protected attributes: model_id? - ruby-on-rails

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.

Related

ActiveAdmin not saving has_many nested object

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

Active admin nested form creates duplicate record

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

Problems with HABTM and ActiveAdmin

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.

validates_uniqueness_of fails when saving directly on the join model

I have three models, Team, Player and TeamMembership. TeamMembership defines the many-to-many relationship between Team and Player. When creating a new Team, the user gets 11 dropdown menus, each containing all the available players. However, a Player can only have a single membership with a Team, which is what I want to validate.
class Player < ActiveRecord::Base
has_many :team_memberships
has_many :teams, :through => :team_memberships
end
class Team < ActiveRecord::Base
has_many :team_memberships
has_many :players, :through => :team_memberships
accepts_nested_attributes_for :players, :team_memberships
validates_associated :team_memberships
end
class TeamMembership < ActiveRecord::Base
belongs_to :team
belongs_to :player
validates_uniqueness_of :player_id, scope: :team_id
end
# GET /teams/new
def new
#team = Team.new
11.times { #team.team_memberships.build }
end
<%= f.fields_for :team_memberships do |team_memberships_form| %>
<%= team_memberships_form.label :player_id %>
<%= team_memberships_form.select(:player_id, options_from_collection_for_select(#Player.available, :id, :name)) %>
<br />
<% end %>
When trying to create a new team, the following appears in the dev log. (Edited down to only 3 players for brevity)
Started POST "/teams" for 127.0.0.1 at 2014-02-06 10:48:40 +0100
Processing by FantasyTeamsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"OwP+nfksvaD0WTQdGjqF5p/shzkiaAodigbFTC6PDD0=", "team"=>{"name"=>"asd", "tournament_id"=>"1", "team_memberships_attributes"=>{"0"=>{"player_id"=>"12"}, "1"=>{"player_id"=>"12"}, "2"=>{"player_id"=>"12"}, "3"=>{"player_id"=>"12"}}}, "commit"=>"Create Fantasy team"}
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
Role Exists (0.3ms) SELECT 1 AS one FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND "roles"."name" = 'admin' LIMIT 1 [["user_id", 1]](0.3ms) BEGIN
FantasyTeamMembership Exists (0.5ms) SELECT 1 AS one FROM "team_memberships" WHERE ("team_memberships"."player_id" = 12 AND "team_memberships"."team_id" IS NULL) LIMIT 1
CACHE (0.0ms) SELECT 1 AS one FROM "team_memberships" WHERE ("team_memberships"."player_id" = 12 AND "team_memberships"."team_id" IS NULL) LIMIT 1
CACHE (0.0ms) SELECT 1 AS one FROM "team_memberships" WHERE ("team_memberships"."player_id" = 12 AND "team_memberships"."team_id" IS NULL) LIMIT 1
CACHE (0.0ms) SELECT 1 AS one FROM "team_memberships" WHERE ("team_memberships"."player_id" = 12 AND "team_memberships"."team_id" IS NULL) LIMIT 1
SQL (0.5ms) INSERT INTO "teams" ("created_at", "name", "tournament_id", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Thu, 06 Feb 2014 09:48:40 UTC +00:00], ["name", "asd"], ["tournament_id", 1], ["updated_at", Thu, 06 Feb 2014 09:48:40 UTC +00:00], ["user_id", 1]]
SQL (0.4ms) INSERT INTO "team_memberships" ("team_id", "player_id") VALUES ($1, $2) RETURNING "id" [["team_id", 8], ["player_id", 12]]
SQL (0.3ms) INSERT INTO "team_memberships" ("team_id", "player_id") VALUES ($1, $2) RETURNING "id" [["team_id", 8], ["player_id", 12]]
SQL (0.3ms) INSERT INTO "team_memberships" ("team_id", "player_id") VALUES ($1, $2) RETURNING "id" [["team_id", 8], ["player_id", 12]]
(14.7ms) COMMIT
Redirected to http://lolhost:3000/teams/8
Completed 302 Found in 111ms (ActiveRecord: 34.3ms)
As can be seen, because of the way I save the records through accepts_nested_attributes_for, validation does not reflect the actual SQL which will run.
How do I get the behaviour that I want?
Worked around this by adding a custom validation method to the Team model.
validate :unique_players
def unique_players
player_ids = team_memberships.map { |ft| ft.player_id }
if player_ids != player_ids.uniq
errors.add(:team_memberships, "must have unique players.")
end
end

Losing an Attribute When Saving Through an Association w/ Scope (Rails 4.0.0)

The Code (Rails 4.0.0)
class Track < ActiveRecord::Base
has_many :artist_tracks
has_many :owning_artists,
-> { where(:artist_tracks => { :artistic_role_id => 1 }) },
:through => :artist_tracks,
:source => :artist
end
class ArtistTrack < ActiveRecord::Base
belongs_to :artist
belongs_to :track
belongs_to :artistic_role
end
class Artist < ActiveRecord::Base
has_many :artist_tracks
has_many :tracks, :through => :artist_tracks
end
Finding Works
# artist_tracks.artistic_role_id is properly set to "1"
2.0.0p195 :003 > Track.last.owning_artists
Track Load (1.1ms) SELECT "tracks".* FROM "tracks" ORDER BY "tracks"."id" DESC LIMIT 1
Artist Load (0.8ms) SELECT "artists".* FROM "artists" INNER JOIN "artist_tracks" ON "artists"."id" = "artist_tracks"."artist_id" WHERE "artist_tracks"."artistic_role_id" = 1 AND "artist_tracks"."track_id" = $1 [["track_id", 10]]
Create Does Not Work
# artist_tracks.artistic_role_id is totally missing from the INSERT
2.0.0p195 :005 > Track.create!(name: "test_name", lyrics: "test_lyrics", owning_artist_ids: [1])
Artist Load (1.3ms) SELECT "artists".* FROM "artists" WHERE "artists"."id" = $1 LIMIT 1 [["id", 1]]
(0.5ms) BEGIN
Artist Exists (0.7ms) SELECT 1 AS one FROM "artists" WHERE ("artists"."name" = 'TestArtist1' AND "artists"."id" != 1) LIMIT 1
SQL (0.7ms) INSERT INTO "tracks" ("created_at", "lyrics", "name", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Thu, 13 Jun 2013 22:20:14 UTC +00:00], ["lyrics", "test_lyrics"], ["name", "test_name"], ["updated_at", Thu, 13 Jun 2013 22:20:14 UTC +00:00]]
#
# Y U NO have artist_tracks.artistic_role_id?
#
SQL (0.7ms) INSERT INTO "artist_tracks" ("artist_id", "created_at", "track_id", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["artist_id", 1], ["created_at", Thu, 13 Jun 2013 22:20:14 UTC +00:00], ["track_id", 12], ["updated_at", Thu, 13 Jun 2013 22:20:14 UTC +00:00]]
(1.0ms) COMMIT
According to the Rails Guide for Active Record Associations (4.3.3.1 where), I believe my usage of the scope and expectation are valid:
If you use a hash-style where option, then record creation via this
association will be automatically scoped using the hash.
Why is the artist_tracks.artistic_role_id attribute being lost? If my expectations are wrong, I'd like to understand why and how to implement an alternative solution.
I have also listed this as an issue on the Rails repo. Any insight is appreciated! Thank you
I believe that what is happening is that the associated model actually being created here is the join model, artist_tracks, and not the association with the actual conditions on it. You could probably fix this by declaring an alternate join association with conditions on it, and then attaching owning_artists through that instead. Like this:
class Track < ActiveRecord::Base
has_many :artist_tracks
has_many :owning_artist_tracks,
-> { where(:artistic_role_id => 1) },
:class_name => "ArtistTrack"
has_many :owning_artists,
:through => :owning_artist_tracks,
:source => :artist
end

Resources