在具有has_many:through关系的联接模型中使用attr_accessible

问题描述

|| 我有一个创建公司并在此过程中成为员工的用户。员工表有一个“ 0”和一个“ 1”。
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
,但这会引起一些问题。属性“ 0”设置为正确,而“ 1”设置为nil。
@user.companies << Company.new(...)
Employee id:1 user_id:1 company_id:nil
所以我的问题是:如果
:user_id
设置得正确,尽管不是is4ѭ,为什么why1ѭ设置不正确呢?它不应该是
attr_accessible
。 我正在使用Rails 3.0.8,并且也已在3.0.7中进行了测试。     

解决方法

        这里有很多共同的地方。 您肯定要在所有模型上使用attr_accessible。 (Google \“ hack rails大规模分配\”,并阅读有关大规模分配的Rails指南。) 将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.companies.build(..) 
(类似于您示例中的代码)。 就Employee模型上的
active
布尔属性而言,如果这是数据库中的一列,则无需为其显式声明
attr_accessible
-默认情况下将可以访问它。