From 980c261f8e2413cd9ffdb600e03689f8b798526f Mon Sep 17 00:00:00 2001 From: Pedro Carmona Date: Thu, 25 Jul 2024 13:29:33 +0100 Subject: [PATCH] Allow proc default values that depend on other values --- lib/sequel/plugins/defaults_setter.rb | 14 ++++++++++---- spec/extensions/defaults_setter_spec.rb | 12 +++++++++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/sequel/plugins/defaults_setter.rb b/lib/sequel/plugins/defaults_setter.rb index 1d325d7e8..886f61475 100644 --- a/lib/sequel/plugins/defaults_setter.rb +++ b/lib/sequel/plugins/defaults_setter.rb @@ -43,13 +43,13 @@ module Plugins # album.values # => {} # album.a # album.values # => {:a => Date.today} - # + # # Usage: # # # Make all model subclass instances set defaults (called before loading subclasses) # Sequel::Model.plugin :defaults_setter # - # # Make the Album class set defaults + # # Make the Album class set defaults # Album.plugin :defaults_setter module DefaultsSetter # Set the default values based on the model schema. Options: @@ -76,7 +76,7 @@ module ClassMethods def cache_default_values? @cache_default_values end - + # Freeze default values when freezing model class def freeze @default_values.freeze @@ -133,7 +133,13 @@ module InstanceMethods def [](k) if new? && !values.has_key?(k) v = model.default_values.fetch(k){return} - v = v.call if v.respond_to?(:call) + if v.respond_to?(:call) + if v.arity == 1 + v = v.call(self) + else + v = v.call + end + end values[k] = v if model.cache_default_values? v else diff --git a/spec/extensions/defaults_setter_spec.rb b/spec/extensions/defaults_setter_spec.rb index 9420077a2..c43e30246 100644 --- a/spec/extensions/defaults_setter_spec.rb +++ b/spec/extensions/defaults_setter_spec.rb @@ -9,11 +9,11 @@ def db.supports_schema_parsing?() true end def db.schema(*) [] end db.singleton_class.send(:alias_method, :schema, :schema) @c = c = Class.new(Sequel::Model(db[:foo])) - @c.instance_variable_set(:@db_schema, {:a=>{}}) + @c.instance_variable_set(:@db_schema, {:a=>{}, :b=>{}}) @c.plugin :defaults_setter - @c.columns :a + @c.columns :a, :b @pr = proc do |x| - db.define_singleton_method(:schema){|*| [[:id, {:primary_key=>true}], [:a, {:ruby_default => x, :primary_key=>false}]]} + db.define_singleton_method(:schema){|*| [[:id, {:primary_key=>true}], [:a, {:ruby_default => x, :primary_key=>false}], [:b, {:primary_key=>false}]]} db.singleton_class.send(:alias_method, :schema, :schema) c.dataset = c.dataset; c end @@ -181,6 +181,12 @@ def db.schema(*) [] end c.new.a.must_equal 2 end + it "should allow proc default values that depend on other values" do + @pr.call(2) + @c.default_values[:a] = proc{ |instance| instance.b * 2 } + @c.new(b: 5).a.must_equal 10 + end + it "should set default value upon initialization when plugin loaded without dataset" do db = @db @c = c = Class.new(Sequel::Model)