在has_many:through关系的连接模型中使用attr_accessible

时间:2011-06-22 03:00:14

标签: ruby-on-rails-3 join has-many-through attr-accessible

我有一个创建公司的USER,并在此过程中成为一名雇员。 employees表格有:user_id:company_id

class User
has_many :employees
has_many :companies, :through => :employees

class Employee
belongs_to :user
belongs_to :company
attr_accessible :active

class Company
has_many :employees
has_many :users, :through => employees

非常基本。但事实上,资源EMPLOYEE具有除外键之外的其他属性,例如布尔值:active。我想使用attr_accessible,但这会导致一些问题。属性:user_id设置正确,但:company_id为零。

@user.companies << Company.new(...)
Employee id:1 user_id:1 company_id:nil

所以我的问题是:如果:user_id设置正确,尽管它不是attr_accessible,为什么:company_id设置不正确?它不应该是attr_accessible

我正在使用Rails 3.0.8,并且还使用3.0.7进行了测试。

2 个答案:

答案 0 :(得分:2)

这里有很多比特在一起工作。

您肯定希望在所有型号上使用attr_accessible。 (Google“hack rails mass assignment”并阅读Rails Guide on mass assignment。)

将attr_accessible添加到模型后,将禁用散列(质量分配)中的所有分配,但明确允许的除外。但是,您仍然可以直接分配值,一次一个。

外键似乎是从质量分配中排除的好东西,所以不要在attr_accessible中列出它们。

.create和.build方法没有使用质量赋值,因此可以设置一个外键关联的值。如果有多个关联,我可以告诉你,你必须分别设置除第一个以外的所有关联。

最后,外键的实际ID是由数据库创建的,而不是由ActiveRecord创建的。因此,您必须同时创建父记录和子记录,或者您必须先保存子项,然后才能在父项中分配外键。否则,没有可用于分配的ID。

从您的示例中我不清楚Employee是如何实例化的。但由于员工属于用户和公司,我认为这样的事情可能有用,假设@user已经存在:

company  = @user.companies.create(..) # fills in company.user_id and saves to DB
employee = @user.employees.build(..)  # fills in employee.user_id but does NOT save yet
employee.company = company            # fills in employee.company_id
employee.save                         # now save to DB

答案 1 :(得分:0)

company_id仅仅是因为公司尚未保存到数据库中 - 公司.new只是在内存中创建对象而不保存它。

如果你这样做:

@user.companies << Company.create(..)

@user.companies << Company.first

他们都应该工作。甚至还有一种更短的方法我认为也应该起作用:

@user.companies.create(..)

这一切都取决于你想要保存关联的点。在某些情况下,最好不要立即保存员工和公司模型,而是等待保存父模型(用户)。在这种情况下,您可以使用:

@user.companies.build(..) 

(类似于您示例中的代码)。

就Employee模型上的active布尔属性而言,如果这是数据库中的列,则不需要为其明确声明attr_accessible - 它可以通过默认值。