Permalink
Browse files

use virtus class_options

This is the implementation of virtus with a combined getter and setter.
  • Loading branch information...
1 parent 9f429ac commit 90eccbb34e0129a514f0da2b87557bf961b07564 @Gibheer committed Jan 28, 2013
Showing with 137 additions and 17 deletions.
  1. +97 −13 lib/class_options/options.rb
  2. +40 −4 spec/unit/class_options/options/options_spec.rb
@@ -1,24 +1,108 @@
module ClassOptions
module Options
- def options(*names)
- names.each do |option|
- create_option(option)
+ # Returns default options hash for a given attribute class
+ #
+ # @example
+ # Virtus::Attribute::String.options
+ # # => {:primitive => String}
+ #
+ # @return [Hash]
+ # a hash of default option values
+ #
+ # @api public
+ def options
+ accepted_options.each_with_object({}) do |option_name, options|
+ option_value = send(option_name)
+ options[option_name] = option_value unless option_value.nil?
end
end
- protected
+ # Returns an array of valid options
+ #
+ # @example
+ # Virtus::Attribute::String.accepted_options
+ # # => [:primitive, :accessor, :reader, :writer]
+ #
+ # @return [Array]
+ # the array of valid option names
+ #
+ # @api public
+ def accepted_options
+ @accepted_options ||= []
+ end
+
+ # Defines which options are valid for a given attribute class
+ #
+ # @example
+ # class MyAttribute < Virtus::Attribute::Object
+ # accept_options :foo, :bar
+ # end
+ #
+ # @return [self]
+ #
+ # @api public
+ def accept_options(*new_options)
+ add_accepted_options(new_options)
+ new_options.each { |option| define_option_method(option) }
+# descendants.each { |descendant| descendant.add_accepted_options(new_options) }
+ self
+ end
- def create_option(option)
+ protected
+
+ # Adds a reader/writer method for the give option name
+ #
+ # @return [undefined]
+ #
+ # @api private
+ def define_option_method(option)
class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def self.#{option}=(value = ClassOptions::Undefined)
- @#{option} = value
- self
- end
-
- def self.#{option}
- @#{option} ||= ClassOptions::Undefined
- end
+ def self.#{option}(value = Undefined) # def self.primitive(value = Undefined)
+ return @#{option} || Undefined if value.equal?(Undefined) # return @primitive if value.equal?(Undefined)
+ @#{option} = value # @primitive = value
+ self # self
+ end # end
RUBY
end
+
+ # Sets default options
+ #
+ # @param [#each] new_options
+ # options to be set
+ #
+ # @return [self]
+ #
+ # @api private
+ def set_options(new_options)
+ new_options.each { |pair| send(*pair) }
+ self
+ end
+
+ # Adds new options that an attribute class can accept
+ #
+ # @param [#to_ary] new_options
+ # new options to be added
+ #
+ # @return [self]
+ #
+ # @api private
+ def add_accepted_options(new_options)
+ accepted_options.concat(new_options)
+ self
+ end
+
+ private
+
+ # Adds descendant to descendants array and inherits default options
+ #
+ # @param [Class] descendant
+ #
+ # @return [undefined]
+ #
+ # @api private
+ def inherited(descendant)
+ super
+ descendant.add_accepted_options(accepted_options).set_options(options)
+ end
end
end
@@ -7,10 +7,9 @@
shared_examples_for 'an option' do
it { should respond_to(function) } # check getter
- it { should respond_to(function + '=') } # check setter
it 'saves the option' do
- subject.send(function + '=', value)
+ subject.send(function, value)
expect(subject.send(function)).to be(value)
end
@@ -23,7 +22,7 @@
let(:testclass) do
Class.new do
extend ClassOptions::Options
- options :bar
+ accept_options :bar
end
end
@@ -34,10 +33,47 @@
let(:testclass) do
Class.new do
extend ClassOptions::Options
- options :foo, :bar
+ accept_options :foo, :bar
end
end
it_behaves_like 'an option'
end
+
+ context 'with instances' do
+ let(:testclass) do
+ Class.new do
+ extend ClassOptions::Options
+ accept_options :foo
+
+ def initialize
+ @foo = self.class.foo
+ end
+ attr_reader :foo
+ end
+ end
+
+ it "gets the value from the class" do
+ testclass.foo(23)
+ t = testclass.new
+ expect(t.foo).to be(23)
+ end
+ end
+
+ context 'with inheritance' do
+ let(:primclass) do
+ Class.new do
+ extend ClassOptions::Options
+ accept_options :foo
+ end
+ end
+ let(:testclass) do
+ Class.new(primclass) do
+ end
+ end
+ it "gets the value from the inherited class" do
+ primclass.foo(23)
+ expect(testclass.foo).to be(23)
+ end
+ end
end

0 comments on commit 90eccbb

Please sign in to comment.