简体   繁体   中英

rails: has_and_belongs_to_many not saving associated objects (null in join table)

Rails 4. I got an Authentication model

class Authentication < ActiveRecord::Base
  ...
  has_and_belongs_to_many :posting_groups
  ...
end

and a PostingGroup model

class PostingGroup < ActiveRecord::Base
  ...
  has_and_belongs_to_many :authentications
  ...
end

The migration for the join table look like this:

def change
  create_table :authentications_posting_groups, id: false do |t|
    t.belongs_to :posting_group
    t.belongs_to :authentication
  end
end

Neither the Authentication nor the PostingGroup tables need references to each other or to the join table, so there's no relevant information in them. When updating the PostingGroups of an Authentication I do the following:

def update
  @authentication.update_attributes(authentication_params)
end
def authentication_params
    params.require(:other_unimportant_stuff, posting_groups: [])
end

During the execution of the update action, params is as follows:

{"authentication"=>{"posting_groups"=>["17", "18"]}, "stuff"=>"more stuff}

...where, 17 and 18 are the ids of the posting groups which should be saved. And, indeed, the @authentication variable in update contains the desired PostingGroups and update_attributes returns true. However, Authentication.find(id).posting_groups (ie what actually was stored in the db) returns an empty set. Additionally, checking the authentications_posting_groups table shows the following:

posting_group_id    authentication_id   
              17    NULL
              18    NULL

For some weird reason the authentication_id is never making it to the db, which is funny because the save was triggered on this object in the first place. It's not the first time I encounter this problem but rather the second, the first time we noticed that everything worked fine (that is, those NULL didn't pop up in the db) when creating what in this scenario is the Authentication , but the same happened on update . On that occasion a hack was implemented re-creating the object (on create everything is OK!!), but here that's not an option. I'd immensely appreciate any pointers because this is driving us mad. Thanks.

Edit - here's the form which is triggering the whole thing:

= form_for authentication, remote: true do |f|
  = f.select :posting_groups, options_for_select(@posting_groups.map {|pg| [ pg.name, pg.id ] }), {}, multiple: true, class: "form-control posting_groups_select"

You should permit posting_group_ids and pass posting_group_ids

Controller

def update
  @authentication.update_attributes(authentication_params)
end
def authentication_params
    params.require(:other_unimportant_stuff, posting_group_ids: [])
end

View

= form_for authentication, remote: true do |f|
  = f.select :posting_group_ids, options_for_select(@posting_groups.map {|pg| [ pg.name, pg.id ] }), {}, multiple: true, class: "form-control posting_groups_select"
params.require(:other_unimportant_stuff, posting_group_ids: [])

Notice the ids.

You're passing in posting_group_ids as per your params but your parameters are set to posting_groups so strong parameters will filter it out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM