Accessing a has_one associations' attributes

后端 未结 4 499
暗喜
暗喜 2021-01-06 00:26

I\'m still quite new to Rails so hopefully this isn\'t a silly question.

I have two models: User and Chore. User has_one chore, and Chore belongs to User

<         


        
相关标签:
4条回答
  • 2021-01-06 00:49

    Another option:

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

    This will return nil if there is no user.chore.

    0 讨论(0)
  • 2021-01-06 01:02

    It's because not every user has a chore associated with it.

    There are a few ways you can deal with this; I'm partial to the iteration pattern using Array() to coerce a collection. You can do this in your view:

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

    Array() will instantiate an empty array if chore is nil, meaning nothing happens when you try to iterate over it. If a chore is present, it will iterate over [chore].

    The benefit of this pattern is that it doesn't violate Tell don't ask. Asking an object if it is nil? is also possible, but it's more of a procedural technique that doesn't take advantage of Ruby's strong object-oriented features.

    Edit

    As Deefour points out, this will result in a table with mismatched columns. You should probably use his solution for this case.

    0 讨论(0)
  • 2021-01-06 01:04

    undefined method `name' for nil:NilClass

    This says that you are trying to call some method name() on an an instance of Nil. Within your code's context, that says that chore on this line is nil

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

    Simply put, one of the User instances in @user has no associated Chore. One simple way to accomodate this in your view is by checking if user.chore exists.

    <td><%= user.chore.nil? ?  "some default name" : user.chore.name %></td>
    
    0 讨论(0)
  • 2021-01-06 01:08

    Here's another option that uses Rails' Delegate module:

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

    This will allow you to call <%= user.chore_name %>, which will pass the name call onto chore, returning nil if there is none.

    0 讨论(0)
提交回复
热议问题