Module | Sequel::Plugins::AssociationProxies |
In: |
lib/sequel/plugins/association_proxies.rb
|
Sequel by default does not use proxies for associations. The association method for *_to_many associations returns an array, and the association_dataset method returns a dataset. This plugin makes the association method return a proxy that will load the association and call a method on the association array if sent an array method, and otherwise send the method to the association‘s dataset.
You can override which methods to forward to the dataset by passing a block to the plugin:
plugin :association_proxies do |opts| [:find, :where, :create].include?(opts[:method]) end
If the block returns false or nil, the method is sent to the array of associated objects. Otherwise, the method is sent to the association dataset. Here are the entries in the hash passed to the block:
:method : | The name of the method |
:arguments : | The arguments to the method |
:block : | The block given to the method |
:instance : | The model instance related to the call |
:reflection : | The reflection for the association related to the call |
:proxy_argument : | The argument given to the association method call |
:proxy_block : | The block given to the association method call |
For example, in a call like:
artist.albums(1){|ds| ds}.foo(2){|x| 3}
The opts passed to the block would be:
{ :method => :foo, :arguments => [2], :block => {|x| 3}, :instance => artist, :reflection => AssociationReflection instance, :proxy_argument => 1, :proxy_block => {|ds| ds} }
Usage:
# Use association proxies in all model subclasses (called before loading subclasses) Sequel::Model.plugin :association_proxies # Use association proxies in a specific model subclass Album.plugin :association_proxies
# File lib/sequel/plugins/association_proxies.rb, line 53 53: def self.configure(model, &block) 54: model.instance_exec do 55: @association_proxy_to_dataset = block if block 56: @association_proxy_to_dataset ||= AssociationProxy::DEFAULT_PROXY_TO_DATASET 57: end 58: end
Set the association reflection to use, and whether the association should be reloaded if an array method is called.
# File lib/sequel/plugins/association_proxies.rb, line 84 84: def initialize(instance, reflection, proxy_argument, &proxy_block) 85: @instance = instance 86: @reflection = reflection 87: @proxy_argument = proxy_argument 88: @proxy_block = proxy_block 89: end
Call the method given on the array of associated objects if the method is an array method, otherwise call the method on the association‘s dataset.
# File lib/sequel/plugins/association_proxies.rb, line 93 93: def method_missing(meth, *args, &block) 94: v = if @instance.model.association_proxy_to_dataset.call(:method=>meth, :arguments=>args, :block=>block, :instance=>@instance, :reflection=>@reflection, :proxy_argument=>@proxy_argument, :proxy_block=>@proxy_block) 95: @instance.public_send(@reflection[:dataset_method]) 96: else 97: @instance.send(:load_associated_objects, @reflection, @proxy_argument, &@proxy_block) 98: end 99: v.public_send(meth, *args, &block) 100: end