6

私はまだ Rails にまったく慣れていないので、これがばかげた質問ではないことを願っています。

User と Chore の 2 つのモデルがあります。ユーザー has_one chore であり、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 をビューに渡し、.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 の name 属性にアクセスできません。次のエラーが表示されます。

nil:NilClass の未定義のメソッド `name'

.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]]
 => #<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 関連付けがどのように機能するかを理解したいだけです。

どんな助けでも大歓迎です!

4

4 に答える 4

5

これは、すべてのユーザーが雑用を関連付けているわけではないためです。

これに対処する方法はいくつかあります。私はArray()、コレクションを強制するために使用する反復パターンに部分的です。あなたはあなたの見解でこれを行うことができます:

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

Array()がnilの場合、空の配列をインスタンス化しますchore。つまり、反復しようとしても何も起こりません。雑用が存在する場合、それは繰り返し[chore]ます。

このパターンの利点は、Tell donotaskに違反しないことです。オブジェクトにそれが可能かどうかを尋ねることnil?も可能ですが、それはRubyの強力なオブジェクト指向機能を利用しない手続き型の手法です。

編集

Deefourが指摘しているように、これにより、列が一致しないテーブルが作成されます。この場合、おそらく彼の解決策を使用する必要があります。

于 2012-11-05T02:01:48.993 に答える
5

Rails の Delegate モジュールを使用する別のオプションを次に示します。

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

これにより、呼び出しが雑用に<%= user.chore_name %>渡され、何もない場合は返されます。namenil

于 2012-11-05T05:24:31.817 に答える
3

nil:NilClassの未定義のメソッド `name'

name()これは、のインスタンスで何らかのメソッドを呼び出そうとしていることを示していますNil。あなたのコードの文脈の中で、それはchoreこの行にnil

<td><%= user.chore.name %></td>

簡単に言うと、のUserインスタンスの1つには@userが関連付けられていませんChore。ビューでこれに対応する簡単な方法の1つは、user.chore存在するかどうかを確認することです。

<td><%= user.chore.nil? ?  "some default name" : user.chore.name %></td>
于 2012-11-05T02:01:39.120 に答える
0

別のオプション:

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

nilがない場合、これが返されuser.choreます。

于 2016-12-31T17:12:01.870 に答える