используя has_many: through и build - PullRequest
       0

используя has_many: through и build

9 голосов
/ 19 февраля 2012

У меня есть три модели, все для has_many: через отношения.Они выглядят так:

class Company < ActiveRecord::Base

  has_many :company_users, dependent: :destroy
  has_many :users, through: :company_users

  accepts_nested_attributes_for :company_users, :users

end

class CompanyUser < ActiveRecord::Base
  self.table_name = :companies_users #this is because this was originally a habtm relationship
  belongs_to :company
  belongs_to :user
end

class User < ActiveRecord::Base
  # this is a devise model, if that matters

  has_many :company_users, dependent: :destroy
  has_many :companies, through: :company_users

  accepts_nested_attributes_for :company_users, :companies

end

это нормально загружается, и соединения создаются для запросов.Однако всякий раз, когда я делаю что-то вроде

@company = Company.last
@user = @company.users.build(params[:user])

@user.save    #=> true
@company.save #=> true

, создаются и записи User, и записи CompanyUser, но поле company_id в записи CompanyUser устанавливается на NULL

INSERT INTO `companies_users` (`company_id`, `created_at`,`updated_at`, `user_id`) 
VALUES (NULL, '2012-02-19 02:09:04', '2012-02-19 02:09:04', 18)

он делает то же самое, когда вы @company.users << @user

Я уверен, что я делаю что-то глупое, я просто не знаю, что.

Ответы [ 3 ]

14 голосов
/ 19 февраля 2012

Вы не можете использовать has_many: через , как это, вы должны сделать это так:

@company = Company.last
@user    = User.create( params[:user] ) 
@company.company_users.create( :user_id => @user.id )

Тогда ассоциация будет определена правильно.

обновление

В случае комментария ниже, поскольку у вас уже есть accepts_nested_attributes_for , ваши параметры должны быть такими:

{ :company => 
    { :company_users_attributes => 
        [ 
          { :company_id => 1, :user_id => 1 } ,
          { :company_id => 1, :user_id => 2 },
          { :company_id => 1, :user_id => 3 } 
        ]
    } 
}

И пользователи будут автоматически добавляться в компании.

5 голосов
/ 19 февраля 2012

Я подозреваю ваш параметр params[:user], иначе ваш код кажется чистым.We can use build method with 1..n and n..n associations too, см. здесь .

Я предлагаю вам сначала убедиться, что ваши ассоциации моделей работают нормально, для этого откройте console и попробуйте следующее,

> company = Company.last
=> #<Tcompany id: 1....>
> company.users
=> []
> company.users.build(:name => "Jake")
=> > #<User id: nil, name: "Jake">
> company.save
=> true

Теперь, если записи сохраняются нормально, отладьте параметры, которые вы передаете методу сборки.

Счастливая отладка:)

2 голосов
/ 05 февраля 2019

Если у вас есть ассоциация has_many :through и вы хотите сохранить ассоциацию, используя build, вы можете сделать это, используя опцию :inverse_of в ассоциации own_to в модели соединения

Вот модифицированный примериз документа rails, в котором теги имеют has_many: посредством ассоциации с публикациями, и разработчик пытается сохранить теги через модель соединения (PostTag), используя метод build:

@post = Post.first
@tag = @post.tags.build name: "ruby"
@tag.save

Общее ожидание заключается в том, чтопоследняя строка должна сохранить сквозную запись в таблице соединений (post_tags).Тем не менее, это не будет работать по умолчанию. Это будет работать только в том случае, если установлено: inverse_of :

class PostTag < ActiveRecord::Base
  belongs_to :post
  belongs_to :tag, inverse_of: :post_tags # add inverse_of option
end

class Post < ActiveRecord::Base
  has_many :post_tags
  has_many :tags, through: :post_tags 
end

class Tag < ActiveRecord::Base
  has_many :post_tags
  has_many :posts, through: :post_tags  
end

Так что для вышеуказанного вопроса установите параметр: inverse_of в ассоциации belongs_to :user в модели соединения (CompanyUser)например:

class CompanyUser < ActiveRecord::Base
  belongs_to :company
  belongs_to :user, inverse_of: :company_users
end

приведет к тому, что следующий код правильно создаст запись в объединяемой таблице (company_users)

company = Company.first
company.users.build(name: "James")
company.save

Источник: здесь & здесь

...