Rails:如何在setter方法中提供父属性

时间:2016-02-18 23:12:35

标签: ruby-on-rails nested-attributes getter-setter virtual-attribute

上下文

我有一个company模型,其中有许多projects,有很多taskscompany也有很多employees,而后者又有很多tasks

架构:

Railscast #102

问题:

我正在构建一个表单来创建一个项目,用户可以在其中添加多个tasks。提交后,表单应创建一条project条记录,一条或多条带有taskhours属性的employee_id条记录,并且(!)会检查employee名称已经存在于数据库中或创建一个新的。

我通过在表单中​​添加jquery autocomplete并在我的任务模型中使用gettersetter方法定义虚拟属性来实现此目的。与{{3}}类似。

这会成功设置employee_id中的tasks并创建一个新的employee记录,其中包含员工nametask_id

目前的问题是模型没有保存company_id

我的代码:

class Task < ActiveRecord::Base
    belongs_to :project
    belongs_to :employee

    def employee_name
      employee.try(:name)
    end

    def employee_name=(name)
      self.employee = Employee.find_or_create_by(name: name) if name.present?
    end
end

问题:

如何使父模型的company_id属性可用于Task模型的setter方法?像这样:

def shareholder_name=(name)
    self.shareholder = Shareholder.find_or_create_by(name: name, company_id: company_id) if name.present?
end

目前会产生错误:

undefined local variable or method "company_id" for #<Task:0x98438b8>

修改

或者,如果我尝试project.company_id,这告诉我project是一个NilClass:

undefined method company_id for nil:NilClass

更新

尚未解决。这里有project nil为什么的任何想法?

1 个答案:

答案 0 :(得分:1)

class Task < ActiveRecord::Base
  belongs_to :project
  belongs_to :employee

  def shareholder_name=(name)
    self.shareholder = Shareholder.find_or_create_by(name: name, company_id: project.company_id) if name.present?
  end
end 

另外,所以使用rails的典型模式,例如你有belongs_to :project的模式,会将project的实例方法添加到Task,然后可以使用该实例方法获取与任务相关联的项目,以及随后可能感兴趣的相关company_id项目