before_add回调,'为nil对象调用id'错误

时间:2013-03-23 17:42:24

标签: ruby-on-rails

我遇到了经典的'Called id for nil...错误,但我很难理解为什么我的对象为零。

尝试获取任务所属的代理的ID时,validate_assignee方法出错。

class Task < ActiveRecord::Base

belongs_to :user
has_one :agent, through: :users
has_and_belongs_to_many :assignees,
                      class_name: "User",
                      before_add: :validate_assignee
private
  def validate_assignee(assignee)
    #need to check that the :assignee belongs to the same :agent as the :user
    #grab agent_id from self
    current_agent_id = self.agent.id 
    #fails here on create of a Task through the @user.tasks.build association
    ...
  end
end

从控制台我通过

构建任务时得到预期的行为
> task = @user.tasks.build ...
> task.agent.id
=> 1

我在TasksController中的创建操作:

def create
  @task = current_user.tasks.build(params[:task])
  ...
end

当对象尚未保存时,在此上下文中使用self有什么奇怪之处吗?有没有更好的方法呢?我正处于我需要另一双眼睛的阶段,因为我正绕着圆圈走。感谢。

更新 为了从流程中消除current_user,我已经在create action中更改了task.build,以通过User关联显式构建任务,并且我知道的User属于代理。

@task = User.find(1).tasks.build(params[:task])

当我在validate_assignee方法中输出对象的表示时,如puts self.to_yaml,我发现任务没有设置user_id

总结 - 我正在通过我的创建操作中的用户关联构建一个新的Task对象,但是在由before_add关联回调调用的方法内的Task模型中,它已经失去与用户。

2 个答案:

答案 0 :(得分:2)

似乎,在保存记录之前,您无法访问该对象的关联属性。这就是this chap says。相反,我已经在我的Task模型中添加了一个after_save回调来调用我的验证方法,其中一切都按预期工作。

在验证方法中通过self.to_yaml输出任务时,我会按预期看到user_id值。在我验证它之前,我必须实际保存记录和habtm关联,这简直是一种耻辱。

答案 1 :(得分:1)

我认为您的agent没有current_user。如果agent没有user

   current_user.agent  #=> nil 

因此,在id上调用nil时会抛出错误。

   current_user.agent.id #=> Throws error

如果您agent没有user,则可以使用try来避免错误:

   current_agent_id = self.agent.try(:id)