Ruby on Rails Madness - 在同一个对象上调用相同的方法,不同的结果..为什么?

pen*_*ere 2 ruby ruby-on-rails

这怎么可能?我在控制台中所做的就是创建这些对象并关联它们.这对我来说毫无意义.p.jobs.first和j是一回事.为什么title方法适用于j而不适用于p.jobs.first?

ruby-1.9.2-p136 :031 > p
 => #<Person id: 14, type: "Person", desc: nil, created_at: "2011-01-24 23:53:13", updated_at: "2011-01-24 23:53:13"> 
ruby-1.9.2-p136 :032 > p.jobs.first
 => #<Job id: 18, type: "Job", created_at: "2011-01-24 23:53:36", updated_at: "2011-01-24 23:53:36", entity_id: nil, person_id: 14, company_id: 15> 
ruby-1.9.2-p136 :033 > p.jobs.first.title
 => nil 
ruby-1.9.2-p136 :034 > p.title
 => nil 
ruby-1.9.2-p136 :035 > j
 => #<Job id: 18, type: "Job", created_at: "2011-01-24 23:53:36", updated_at: "2011-01-24 23:53:36", entity_id: nil, person_id: 14, company_id: 15> 
ruby-1.9.2-p136 :036 > j.title
 => "dfkjld" 
Run Code Online (Sandbox Code Playgroud)

注意:名称类是抽象的并与Job相关联.这两个类都包含一个辅助模块.

  def title
    if class_name == "Job" 
      name.value
    elsif class_name == "Person"
      if jobs.empty? then "Unemployed" else jobs.first.title end
    else
      nil
    end      
  end

ruby-1.9.2-p136 :015 > j.name
 => #<Name id: 16, kind: nil, value: "dfklj", name_id: nil, event_id: 19, instrument_id: nil, transaction_id: nil> 
ruby-1.9.2-p136 :016 > j.name.value
 => "dfklj"
Run Code Online (Sandbox Code Playgroud)

kik*_*ito 6

这可能是一个懒惰的加载问题.p.jobs.first不是从您的系统中提取"真实"数据,而是使用它的memoized/cached版本.并且该缓存版本不包含标题.

它可以通过强制p"重新加载其依赖关系" 来解决.如果p是ActiveRecord对象,则有一个reload方法:

p.reload
p.jobs.first
Run Code Online (Sandbox Code Playgroud)

另一种可能性是j有本地修改,但这些没有被提交 - 例如,在ActiveRecord中,如果标题最初是nil并且你在j上设置它而没有保存/重新加载,它将不会出现在p.jobs.first:

> p.jobs.first.title
nil
> j = Jobs.find(1) # same job as p.jobs.first.title
...
> j.title = 'blah'
'blah'
> j.title
'blah'
> p.jobs.first.title
nil
Run Code Online (Sandbox Code Playgroud)

为了使其工作,您必须保存到数据库并重新加载p:

> j.save
true
> p.reload
p.jobs.first.title
> 'blah'
Run Code Online (Sandbox Code Playgroud)