delegate意为代理,ActiveRecord中的delegate方法暴露其中包含的对象的公开方法作为当前类的方法。
提供了如下选项
- :to - 指定目标对象
- :prefix - 用目标对象的名字或者自定义的前缀来作为代理方法的前缀
- :allow_nil - 如果设置为true, 可以阻止抛出NoMethodError异常, 调用将返回nil
例如:
class Greeter < ActiveRecord::Base
def hello
'hello'
end
def goodbye
'goodbye'
end
end
class Foo < ActiveRecord::Base
belongs_to :greeter
delegate :hello, to: :greeter
end
Foo.new.hello # => "hello"
Foo.new.goodbye # => NoMethodError: undefined method `goodbye' for #<Foo:0x1af30c>
同时定义多个代理方法
class Foo < ActiveRecord::Base
belongs_to :greeter
delegate :hello, :goodbye, to: :greeter
end
Foo.new.goodbye # => "goodbye"
代理方法到实例变量、类变量、或者常量
class Foo
CONSTANT_ARRAY = [0,1,2,3]
@@class_array = [4,5,6,7]
def initialize
@instance_array = [8,9,10,11]
end
delegate :sum, to: :CONSTANT_ARRAY
delegate :min, to: :@@class_array
delegate :max, to: :@instance_array
end
Foo.new.sum # => 6
Foo.new.min # => 4
Foo.new.max # => 11
代理方法到类方法
class Foo
def self.hello
"world"
end
delegate :hello, to: :class
end
Foo.new.hello # => "world"
可以通过:prefix
选项把代理对象名作为代理前缀,如果:prefix
选项设置为true
erson = Struct.new(:name, :address)
class Invoice < Struct.new(:client)
delegate :name, :address, to: :client, prefix: true
end
john_doe = Person.new('John Doe', 'Vimmersvej 13')
invoice = Invoice.new(john_doe)
invoice.client_name # => "John Doe"
invoice.client_address # => "Vimmersvej 13"
自定义前缀
class Invoice < Struct.new(:client)
delegate :name, :address, to: :client, prefix: :customer
end
invoice = Invoice.new(john_doe)
invoice.customer_name # => 'John Doe'
invoice.customer_address # => 'Vimmersvej 13'