Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow proc default values that depend on other values #2195

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions lib/sequel/plugins/defaults_setter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
12 changes: 9 additions & 3 deletions spec/extensions/defaults_setter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
Loading