From c2d9af2ce93d1f639ad60a768b88e490d98104f7 Mon Sep 17 00:00:00 2001 From: Dan Kubb Date: Tue, 17 Aug 2010 13:15:20 -0700 Subject: [PATCH] Refactored Property option methods * Instead of asking the parent class for an option value when it is unknown, copy the values when the descendant inherits from the parent class. Also, when an option value changes in a parent class copy the value to all the descendants. This has the same effect as the previous code, except that it should be more efficient in the general case. * Replace Property.primitive with a method created using accept_options. --- lib/dm-core/property.rb | 82 +++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 49 deletions(-) diff --git a/lib/dm-core/property.rb b/lib/dm-core/property.rb index 8fc4d366..83f5470a 100644 --- a/lib/dm-core/property.rb +++ b/lib/dm-core/property.rb @@ -396,17 +396,20 @@ def descendants end # @api private - def inherited(subclass) - add_descendant(subclass) + def inherited(descendant) + add_descendant(descendant) - subclass.primitive primitive - subclass.accept_options(*accepted_options) + descendant.primitive primitive + descendant.accept_options(*accepted_options) + + # inherit the options from the parent class + options.each { |key, value| descendant.send(key, value) } end # @api private - def add_descendant(subclass) - descendants << subclass - superclass.add_descendant(subclass) if superclass.respond_to?(:add_descendant) + def add_descendant(descendant) + descendants << descendant + superclass.add_descendant(descendant) if superclass.respond_to?(:add_descendant) end # @api public @@ -421,21 +424,24 @@ def accept_options(*args) # Load Property options accepted_options.each do |property_option| class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def self.#{property_option}(*args) # def unique(*args) - if args.any? # if args.any? - @#{property_option} = args.first # @unique = args.first - elsif instance_variable_defined?(:@#{property_option}) # elsif instance_variable_defined?(:@unique) - @#{property_option} # @unique - elsif superclass.respond_to?(:#{property_option}) # elsif superclass.respond_to?(:unique) - superclass.#{property_option} # superclass.unique - else # else - nil # nil - end # end - end # end + def self.#{property_option}(value = Undefined) # def self.unique(value = Undefined) + return @#{property_option} if value.equal?(Undefined) # return @unique if value.equal?(Undefined) + descendants.each do |descendant| # descendants.each do |descendant| + descendant.#{property_option}(value) # descendant.unique(value) + end # end + @#{property_option} = value # @unique = value + end # end RUBY end - descendants.each {|descendant| descendant.accept_options(*args)} + descendants.each { |descendant| descendant.accept_options(*args) } + end + + # @api private + def nullable(*args) + # :required is preferable to :allow_nil, but :nullable maps precisely to :allow_nil + warn "#nullable is deprecated, use #required instead (#{caller[0]})" + allow_nil(*args) end # Gives all the options set on this type @@ -446,36 +452,14 @@ def self.#{property_option}(*args) # def unique(*args) def options options = {} accepted_options.each do |method| - next if !respond_to?(method) || (value = send(method)).nil? - options[method] = value + value = send(method) + options[method] = send(method) unless value.nil? end options end - - # Ruby primitive type to use as basis for this type. See - # Property::PRIMITIVES for list of types. - # - # @param primitive [Class, nil] - # The class for the primitive. If nil is passed in, it returns the - # current primitive - # - # @return [Class] if the param is nil, return the current primitive. - # - # @api public - def primitive(primitive = nil) - return @primitive if primitive.nil? - @primitive = primitive - end - - # @api private - def nullable(value) - # :required is preferable to :allow_nil, but :nullable maps precisely to :allow_nil - warn "#nullable is deprecated, use #required instead (#{caller[0]})" - allow_nil(value) - end end - accept_options *Property::OPTIONS + accept_options :primitive, *Property::OPTIONS # A hook to allow types to extend or modify property it's bound to. # Implementations are not supposed to modify the state of the type class, and @@ -489,11 +473,11 @@ def bind # @return [String] name of field in data-store # # @api semipublic - def field(repository_name = nil) + def field(repository_name = Undefined) self_repository_name = self.repository_name klass = self.class - if repository_name + unless repository_name.equal?(Undefined) warn "Passing in +repository_name+ to #{klass}#field is deprecated (#{caller[0]})" if repository_name != self_repository_name @@ -902,10 +886,10 @@ def assert_valid_options(options) # # @api private def determine_visibility - default_accessor = @options[:accessor] || :public + default_accessor = @options.fetch(:accessor, :public) - @reader_visibility = @options[:reader] || default_accessor - @writer_visibility = @options[:writer] || default_accessor + @reader_visibility = @options.fetch(:reader, default_accessor) + @writer_visibility = @options.fetch(:writer, default_accessor) end end # class Property end