使用的has_many:通过和构建

问题描述 投票:9回答:3

我有三个型号,全部为一的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同样的事情

我敢肯定,我在做一些愚蠢的事在这里,我只是不知道是什么。

ruby-on-rails ruby has-many-through
3个回答
14
投票

你不能使用的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
投票

我怀疑你的params[:user]参数,否则你的代码看起来干净。 We can use build method with 1..n and n..n associations too,见here

我建议你首先要确保你的模型协会工作正常,为打开console和尝试以下,

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

现在,如果记录被保存的很好,调试参数传递给构建方法。

快乐调试:)


2
投票

如果你有一个has_many :through协会并要使用保存关联build你可以做到这一点使用上的连接模型的belongs_to的关联:inverse_of选项

下面是从轨道文档,其中标签具有的has_many变形例:通过关联与职位,开发商正试图通过使用build方法联接模型(PostTag)保存标签:

@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这样就在加入模型(CompanyUser)的belongs_to :user关联选项:

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

来源:herehere

© www.soinside.com 2019 - 2024. All rights reserved.