Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3: method delegations with nil relationships

Given the following (vastly simplified) objects:

class Player < ActiveRecord::Base
  has_many :characters
end

class Character < ActiveRecord::Base
  belongs_to :player
  delegate :name, :to => :player, :prefix => :player
end

I need to display the player name in several views. But it's totally valid (and expected) that the Player might be nil.

I've currently handled this via a method as follows:

class Character < ActiveRecord::Base
  belongs_to :player

  def player_name
    player ? player.name : 'Unknown'
  end
end

I don't like this for several reasons. Is there a nicer way of doing this?

like image 657
Catharz Avatar asked May 11 '13 03:05

Catharz


1 Answers

If you're dealing with mostly view-related code, you might find using an "or" in conjunction with allow_nil: true on the delegate call feels natural:

Name: <%= @character.player_name || 'Unknown' %>

Another interesting pattern you may consider is the null object pattern; using this pattern, you describe "default" behavior using an object that represents a "null" or missing value for that object. For example, (pseudocode-ish):

class NullPlayer
  def name
    'Unknown'
  end
end

class Character < ActiveRecord::Base
  belongs_to :player

  delegate :name, to: :player, prefix: :player, allow_nil: true

  # overwrite default player accessor
  def player
    super || NullPlayer.new
  end
end

This pattern is a bit more heavy handed, but you may find it appropriate depending on your application.

Finally, the code for delegate isn't too complicated. You could write your own version of this method that takes a default argument to use in the case of nil:

delegate :name, to: :player, prefix: :player, default: 'Unknown'
like image 188
Michelle Tilley Avatar answered Jan 04 '23 06:01

Michelle Tilley