访问has_one关联的属性

我仍然是Rails的新手,所以希望这不是一个愚蠢的问题。

我有两个模型:用户和家务。 用户has_one杂事,Chore属于User

class User < ActiveRecord::Base attr_accessible :chore_done, :email, :name, :phone has_one :chore class Chore < ActiveRecord::Base attr_accessible :name, :user_id belongs_to :user 

在我的用户索引中,我正在尝试向所有用户显示并显示与他或她相关的杂项。 我这样做是通过将User.all传递给视图并使用.each来遍历每个用户:

          

不幸的是,我无法访问Chore的name属性。 我收到此错误:

nil的未定义方法`name’:NilClass

如果我删除.name属性,它只返回一个指向Chore对象的指针。

我有一种感觉,这与将User.all对象传递给视图然后迭代它有关。 只需在控制台中访问特定的User对象(例如User.find(1)),然后访问user.chore.name就可以了。

 1.9.3-p194 :045 > user = User.find(4) User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 4]] => # 1.9.3-p194 :046 > user.chore.name Chore Load (0.3ms) SELECT "chores".* FROM "chores" WHERE "chores"."user_id" = 4 LIMIT 1 => "Living room" 

我在APIDock中读了一些关于AssociationProxy的内容,但我认为我并不完全理解它,也不知道如何使用它。 根据我收集的内容,访问模型中的所有对象会返回一个对象数组,但是不会为其依赖项返回一组完整的属性? 因此,在这种情况下,我得到一个指向Chore对象的指针,但是不能访问它的任何属性。

我当然可以在我的用户表中添加Chore作为另一列,但我可能会在将来添加到该模型+我只是想弄清楚has_one关联如何工作。

任何帮助表示赞赏!

nil的未定义方法`name’:NilClass

这表示你试图在一个Nil实例上调用一些方法name() 。 在你的代码的上下文中,这就是说这行的chorenil

 <%= user.chore.name %> 

简而言之,@ User一个User实例没有关联的Chore 。 在视图中容纳此function的一种简单方法是检查user.chore存在。

 <%= user.chore.nil? ? "some default name" : user.chore.name %> 

这是因为不是每个用户都有与之相关的杂务。

有几种方法可以解决这个问题; 我偏爱使用Array()来强制集合的迭代模式。 您可以在视图中执行此操作:

 <% Array(user.chore).each do |chore| %> <%= chore.name %> <%= chore.done? %> <% end %> 

如果chore是nil, Array()将实例化一个空数组,这意味着当你尝试迭代时没有任何反应。 如果存在杂务,它将遍历[chore]

这种模式的好处是它不违反Tell不要求 。 问对象是否nil? 也是可能的,但它更多的是一种不利用Ruby强大的面向对象function的程序技术。

编辑

正如Deefour指出的那样,这将导致列中列不匹配。 您应该在这种情况下使用他的解决方案。

这是使用Rails的Delegate模块的另一个选项:

 class User < ActiveRecord::Base has_one :chore delegate :name, to: :chore, prefix: true, allow_nil: true end 

这将允许您调用<%= user.chore_name %> ,它将name调用传递给杂项,如果没有则返回nil

另外一个选项:

 <%= user.chore.try(:name) %> 

如果没有user.chore这将返回nil