我有一个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。
这里有很多位在一起工作。
您肯定希望在所有模型上都使用attr_accessible。(谷歌"破解铁轨批量分配"并阅读关于批量分配的铁轨指南。)
将attr_accessible添加到模型后,将禁用哈希中的所有赋值(批量赋值),除非您明确允许。但是,您仍然可以直接指定值,每次指定一个值。
外键似乎是从批量分配中排除的一件好事,所以不要在attr_accessible中列出它们。
.create和.build方法不使用批量赋值,因此它们可以设置一个外键关联的值。如果有几个关联,据我所知,除了第一个之外,你必须分别设置所有关联。
最后,外键的实际ID是由数据库创建的,而不是由ActiveRecord创建的。因此,您要么必须同时创建父记录和子记录,要么必须先保存子记录,然后才能在父记录中分配外键。否则,没有可用于分配的ID。
从您的示例中,我不清楚Employee是如何实例化的。但由于Employee同时属于User和Company,我认为这样的事情可能会奏效,假设@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
company_id为nil只是因为company还没有保存到数据库中-company.new只是在内存中创建对象而没有保存它。
如果你这样做:
@user.companies << Company.create(..)
或
@user.companies << Company.first
它们都应该起作用。甚至还有一种更短的方法,我认为也应该有效:
@user.companies.create(..)
这完全取决于您希望在哪一点保存关联。在某些情况下,最好不要立即保存员工和公司模型,而是等待父模型(User)保存。在这种情况下,您可以使用:
@user.companies.build(..)
(这与您的示例中的代码类似)。
就Employee模型上的active
布尔属性而言,如果这是数据库中的一列,则不需要为其显式声明attr_accessible
——默认情况下可以访问它。