module Sequel::Plugins
Empty namespace that plugins should use to store themselves, so they can be loaded via Model.plugin.
Plugins should be modules with one of the following conditions:
-
A singleton method named apply, which takes a model, additional arguments, and an optional block. This is called the first time the plugin is loaded for this model (unless it was already loaded by an ancestor class), before including/extending any modules, with the arguments and block provided to the call to Model.plugin.
-
A module inside the plugin module named ClassMethods, which will extend the model class.
-
A module inside the plugin module named InstanceMethods, which will be included in the model class.
-
A module inside the plugin module named DatasetMethods, which will extend the model’s dataset.
-
A singleton method named configure, which takes a model, additional arguments, and an optional block. This is called every time the Model.plugin method is called, after including/extending any modules.
Constants
- SEQUEL_METHOD_NAME
-
Return a unique method name symbol for the given suffix.
Public Class Methods
Source
# File lib/sequel/model/plugins.rb 61 def self.after_set_dataset(mod, meth) 62 mod.send(:define_method, :set_dataset) do |*a| 63 r = super(*a) 64 # Allow calling private class methods as methods this specifies are usually private 65 send(meth) 66 r 67 end 68 end
Add method to mod that overrides set_dataset to call the method afterward.
Source
# File lib/sequel/model/plugins.rb 31 def self.def_dataset_methods(mod, meths) 32 Array(meths).each do |meth| 33 mod.class_eval("def #{meth}(*args, &block); dataset.#{meth}(*args, &block) end", __FILE__, __LINE__) 34 # :nocov: 35 mod.send(:ruby2_keywords, meth) if respond_to?(:ruby2_keywords, true) 36 # :nocov: 37 end 38 end
In the given module mod, define methods that are call the same method on the dataset. This is designed for plugins to define dataset methods inside ClassMethods that call the implementations in DatasetMethods.
This should not be called with untrusted input or method names that can’t be used literally, since it uses class_eval.
Source
# File lib/sequel/model/plugins.rb 92 def self.def_sequel_method(model, meth, expected_arity, &block) 93 if meth.is_a?(String) 94 meth = SEQUEL_METHOD_NAME.call(meth) 95 end 96 call_meth = meth 97 98 unless block.lambda? 99 required_args, optional_args, rest, keyword = _define_sequel_method_arg_numbers(block) 100 101 if keyword == :required 102 raise Error, "cannot use block with required keyword arguments when calling define_sequel_method with expected arity #{expected_arity}" 103 end 104 105 case expected_arity 106 when 0 107 unless required_args == 0 108 # SEQUEL6: remove 109 Sequel::Deprecation.deprecate("Arity mismatch in block passed to define_sequel_method. Expected Arity 0, but arguments required for #{block.inspect}. Support for this will be removed in Sequel 6.") 110 b = block 111 block = lambda{instance_exec(&b)} # Fallback 112 end 113 when 1 114 if required_args == 0 && optional_args == 0 && !rest 115 # SEQUEL6: remove 116 Sequel::Deprecation.deprecate("Arity mismatch in block passed to define_sequel_method. Expected Arity 1, but no arguments accepted for #{block.inspect}. Support for this will be removed in Sequel 6.") 117 temp_method = SEQUEL_METHOD_NAME.call("temp") 118 model.class_eval("def #{temp_method}(_) #{meth =~ /\A\w+\z/ ? "#{meth}_arity" : "send(:\"#{meth}_arity\")"} end", __FILE__, __LINE__) 119 model.send(:alias_method, meth, temp_method) 120 model.send(:undef_method, temp_method) 121 model.send(:private, meth) 122 meth = :"#{meth}_arity" 123 elsif required_args > 1 124 # SEQUEL6: remove 125 Sequel::Deprecation.deprecate("Arity mismatch in block passed to define_sequel_method. Expected Arity 1, but more arguments required for #{block.inspect}. Support for this will be removed in Sequel 6.") 126 b = block 127 block = lambda{|r| instance_exec(r, &b)} # Fallback 128 end 129 else 130 raise Error, "unexpected arity passed to define_sequel_method: #{expected_arity.inspect}" 131 end 132 end 133 134 model.send(:define_method, meth, &block) 135 model.send(:private, meth) 136 model.send(:alias_method, meth, meth) 137 call_meth 138 end
Define a private instance method using the block with the provided name and expected arity. If the name is given as a Symbol, it is used directly. If the name is given as a String, a unique name will be generated using that string. The expected_arity should be either 0 (no arguments) or 1 (single argument).
If a block with an arity that does not match the expected arity is used, a deprecation warning will be issued. The method defined should still work, though it will be slower than a method with the expected arity.
Sequel only checks arity for regular blocks, not lambdas. Lambdas were already strict in regards to arity, so there is no need to try to fix arity to keep backwards compatibility for lambdas.
Blocks with required keyword arguments are not supported by this method.
Source
# File lib/sequel/model/plugins.rb 43 def self.inherited_instance_variables(mod, hash) 44 mod.send(:define_method, :inherited_instance_variables) do || 45 super().merge!(hash) 46 end 47 mod.send(:private, :inherited_instance_variables) 48 end
Add method to mod that overrides inherited_instance_variables to include the values in this hash. These affects how class instance variables will be treated during subclassing.
Source
# File lib/sequel/model/plugins.rb 52 def self.model_instance_variables(mod, *ivs) 53 mod.send(:define_method, :each_model_instance_variable) do |&block| 54 super(&block) 55 ivs.each(&block) 56 end 57 mod.send(:private, :each_model_instance_variable) 58 end
Sets the model instance variables used by the plugin. These instance variables will be initialized to nil for created model objects.
Private Class Methods
Source
# File lib/sequel/model/plugins.rb 144 def self._define_sequel_method_arg_numbers(callable) 145 optional_args = 0 146 rest = false 147 keyword = false 148 callable.parameters.map(&:first).each do |arg_type, _| 149 case arg_type 150 when :opt 151 optional_args += 1 152 when :rest 153 rest = true 154 when :keyreq 155 keyword = :required 156 when :key, :keyrest 157 keyword ||= true 158 else 159 raise Error, "invalid arg_type passed to _define_sequel_method_arg_numbers: #{arg_type}" 160 end 161 end 162 arity = callable.arity 163 if arity < 0 164 arity = arity.abs - 1 165 end 166 required_args = arity 167 arity -= 1 if keyword == :required 168 169 # callable currently is always a non-lambda Proc 170 optional_args -= arity 171 172 [required_args, optional_args, rest, keyword] 173 end
Return the number of required argument, optional arguments, whether the callable accepts any additional arguments, and whether the callable accepts keyword arguments (true, false or :required).