Class: Module

Inherits:
Object show all
Defined in:
lib/support/delegate_method.rb

Instance Method Summary collapse

Instance Method Details

#delegate(*methods) ⇒ Object

Patching delegate to take default value as option, which means that instead of

returning nil in any situation it will return the default value. So if the
object you delegate to does not exist or the method on that object does not exist
or the method returns nil then the default value is returned.
Note that if you use a default value then the allow nil is automatically set to false,
since you will always return the default if there is nil value

class Invoice < Struct.new(:client)
  delegate :name, :to => :client, :default => 'Dano'
end

Example 1:
invoice = Invoice.new(nil) # no client
invoice.client_name    # => "Dano"

Example 2:
Client = Struct.new(:address) # client does not have attribute called name
john_doe = Client.new("1 park avenue")
invoice = Invoice.new(john_doe)
invoice.client_name    # => "Dano"

Example 3:
Client = Struct.new(:name, :address)
john_doe = Client.new(nil, "1 park avenue") # client name is nil
invoice = Invoice.new(john_doe)
invoice.client_name    # => "Dano"


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/support/delegate_method.rb', line 30

def delegate(*methods)
  options = methods.pop

  unless options.is_a?(Hash) && to = options[:to]
    raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)."
  end

  if options[:prefix] == true && options[:to].to_s =~ /^[^a-z_]/
    raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
  end

  prefix = options[:prefix] && "#{options[:prefix] == true ? to : options[:prefix]}_"

  default = options[:default]

  allow_nil = (options[:allow_nil] || default) && "#{to} && "

  methods.each do |method|

    writer(method, to, prefix) if options[:writer]

    module_eval(<<-EOS, "(__DELEGATION__)", 1)
        def #{prefix}#{method}(*args, &block)                                   # def customer_name(*args, &block)
          val = #{allow_nil}#{to}.__send__(#{method.inspect}, *args, &block)    #   val = client && client.__send__(:name, *args, &block)
          return "#{default}" if val.nil? and #{!default.blank?}                #   return default if val.nil? and !default.blank?
          val                                                                   #   val
        end                                                                     # end
    EOS
  end
end

#writer(setter_attribute, model, prefix) ⇒ Object

writer :tail_number, :aircraft

creates a method like this:

def tail_number=(tail_number)
  self.aircraft = Aircraft.find_by_tail_number(tail_number)
end

in this case the setter_attribute is the same as the attribute name
but in a case like this:

setter :pic_xojet_id, :pilot, :pic_pilot

you are saying set the attribue pic_pilot to a pilot


77
78
79
80
81
82
# File 'lib/support/delegate_method.rb', line 77

def writer(setter_attribute, model, prefix)
  define_method "#{prefix}#{setter_attribute.to_s}=" do |value|
    found_model = model.to_s.capitalize.constantize.find(:first, :conditions=> {setter_attribute => value})
    self.send("#{model.to_s}=", found_model)
  end
end