我对 Rails 还是很陌生,所以希望这不是一个愚蠢的问题。
我有两个模型:User 和 Chore。用户有_一件家务,家务属于用户
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 传递给 View 并使用 .each 遍历每个用户来执行此操作:
<% @users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.chore.name %></td>
<td><%= user.chore_done? %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
不幸的是,我无法访问 Chore 的名称属性。我收到此错误:
undefined method `name' for nil:NilClass
如果我删除 .name 属性,它只会返回一个指向 Chore 对象的指针。
我觉得这与将 User.all 对象传递给 View 然后对其进行迭代有关。只需在控制台中访问特定的用户对象(例如 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]]
=> #<User id: 4, name: "Example User", email: "example@dot.com", phone: 8675309, chore_done: false, created_at: "2012-11-05 01:53:33", updated_at: "2012-11-05 01:53:33">
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 关联是如何工作的。
感谢任何帮助!
最佳答案
这是因为并非每个用户都有与之相关的琐事。
有几种方法可以解决这个问题;我偏爱使用 Array()
强制集合的迭代模式。您可以在您的 View 中执行此操作:
<% Array(user.chore).each do |chore| %>
<td><%= chore.name %></td>
<td><%= chore.done? %></td>
<% end %>
如果 chore
为 nil,Array()
将实例化一个空数组,这意味着当您尝试迭代它时没有任何反应。如果存在琐事,它将遍历 [chore]
。
这种模式的好处是它不违反 Tell don't ask .询问对象是否为 nil?
也是可能的,但它更像是一种过程技术,没有利用 Ruby 强大的面向对象的特性。
编辑
正如 Deefour 指出的那样,这将导致表格中的列不匹配。对于这种情况,您可能应该使用他的解决方案。
关于ruby-on-rails - 访问 has_one 关联的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13225002/