32

Is it possible to use delegate in your Active Record model and use conditions like :if on it?

class User < ApplicationRecord
  delegate :company, :to => :master, :if => :has_master?

  belongs_to :master, :class_name => "User"

  def has_master?
    master.present?
  end
end
Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
Fousa
  • 535
  • 1
  • 7
  • 10

2 Answers2

43

No, you can't, but you can pass the :allow_nil => true option to return nil if the master is nil.

class User < ActiveRecord::Base
  delegate :company, :to => :master, :allow_nil => true

  # ...
end

user.master = nil
user.company 
# => nil

user.master = <#User ...>
user.company 
# => ...

Otherwise, you need to write your own custom method instead using the delegate macro for more complex options.

class User < ActiveRecord::Base
  # ...

  def company
    master.company if has_master?
  end

end
John Topley
  • 113,588
  • 46
  • 195
  • 237
Simone Carletti
  • 173,507
  • 49
  • 363
  • 364
  • He could use the new try syntax: master.try(:company) which will return nil if master is nil. – Ryan Bigg Nov 12 '09 at 11:21
  • try is only available in ruby 1.9 – Subba Rao Nov 12 '09 at 19:27
  • 1
    Try is available in any Ruby implementation via ActiveSupport but it requires ActiveSupport >= 2.3. Also, in this code I didn't see any real advantage of using try() so I went with the classic implementation. – Simone Carletti Nov 12 '09 at 19:43
3

I needed to delegate the same method to two models, preferring to use one model over the other. I used the :prefix option:

from individual.rb

delegate :referral_key, :email, :username, :first_name, :last_name, :gender, :approves_email, :approves_timeline, to: :user, allow_nil: true, prefix: true                                
delegate :email, :first_name, :last_name, to: :visitor, allow_nil: true, prefix: true

def first_name
  user.present? ? user_first_name : visitor_first_name
end
rthbound
  • 1,323
  • 1
  • 17
  • 24