Permalink
Browse files

Replace AttributesAccessor with AttributeSet.

This way the methods for accessing a set of
Attributes are together with those Attributes.
  • Loading branch information...
1 parent 167e3ee commit d606d65aa37c27ce9ee4d28bcb7fe2e3fff41698 @emmanuel emmanuel committed Jul 1, 2012
View
@@ -56,7 +56,6 @@ def self.extended(object)
require 'virtus/class_inclusions'
require 'virtus/module_extensions'
-require 'virtus/attributes_accessor'
require 'virtus/class_methods'
require 'virtus/instance_methods'
@@ -1,7 +1,7 @@
module Virtus
# A set of Attribute objects
- class AttributeSet
+ class AttributeSet < Module
include Enumerable
# Initialize an AttributeSet
@@ -66,6 +66,7 @@ def merge(attributes)
# @api public
def <<(attribute)
self[attribute.name] = attribute
+ attribute.define_accessor_methods(self)
self
end
@@ -110,6 +111,36 @@ def reset
self
end
+ # Defines an attribute reader method
+ #
+ # @param [Attribute] attribute
+ # @param [Symbol] method_name
+ # @param [Symbol] visibility
+ #
+ # @return [self]
+ #
+ # @api private
+ def define_reader_method(attribute, method_name, visibility)
+ define_method(method_name) { attribute.get(self) }
+ send(visibility, method_name)
+ self
+ end
+
+ # Defines an attribute writer method
+ #
+ # @param [Attribute] attribute
+ # @param [Symbol] method_name
+ # @param [Symbol] visibility
+ #
+ # @return [self]
+ #
+ # @api private
+ def define_writer_method(attribute, method_name, visibility)
+ define_method(method_name) { |value| attribute.set(self, value) }
+ send(visibility, method_name)
+ self
+ end
+
private
# Merge the attributes into the index
@@ -1,68 +0,0 @@
-module Virtus
-
- # Host attribute accessor methods
- class AttributesAccessor < Module
-
- # Initialize a module for hosting Attribute access methods
- #
- # @param [Symbol, String] name
- #
- # @api private
- def initialize(name)
- super()
- @name = name
- end
-
- # Defines an attribute reader method
- #
- # @param [Attribute] attribute
- # @param [Symbol] method_name
- # @param [Symbol] visibility
- #
- # @return [self]
- #
- # @api private
- def define_reader_method(attribute, method_name, visibility)
- define_method(method_name) { attribute.get(self) }
- send(visibility, method_name)
- self
- end
-
- # Defines an attribute writer method
- #
- # @param [Attribute] attribute
- # @param [Symbol] method_name
- # @param [Symbol] visibility
- #
- # @return [self]
- #
- # @api private
- def define_writer_method(attribute, method_name, visibility)
- define_method(method_name) { |value| attribute.set(self, value) }
- send(visibility, method_name)
- self
- end
-
- # The inspect value of this Module
- #
- # This provides meaningful output when inspecting the ancestors
- # of a class/module that includes this module
- #
- # @example
- #
- # class ClassWithAttributes
- # include Virtus
- # end
- #
- # mod = ClassWithAttributes.send(:virtus_setup_attributes_accessor_module)
- # mod.inspect
- #
- # @return [String]
- #
- # @api public
- def inspect
- "#{@name}::AttributesAccessor"
- end
-
- end
-end
@@ -15,7 +15,7 @@ def self.extended(descendant)
super
descendant.module_eval do
extend DescendantsTracker
- virtus_setup_attributes_accessor_module
+ include attribute_set
end
end
@@ -56,18 +56,6 @@ def attributes
attribute_set
end
- protected
-
- # Set up the anonymous module which will host Attribute accessor methods
- #
- # @return [self]
- #
- # @api private
- def virtus_setup_attributes_accessor_module
- @virtus_attributes_accessor_module = AttributesAccessor.new(inspect)
- include @virtus_attributes_accessor_module
- end
-
private
# Setup descendants' own Attribute-accessor-method-hosting modules
@@ -85,7 +73,7 @@ def virtus_setup_attributes_accessor_module
# @api private
def inherited(descendant)
super
- descendant.virtus_setup_attributes_accessor_module
+ descendant.module_eval { include attribute_set }
end
# Hooks into const missing process to determine types of attributes
View
@@ -14,10 +14,9 @@ module Extensions
# @api private
def self.extended(object)
super
- object.extend(InstanceMethods)
object.instance_eval do
- @virtus_attributes_accessor_module = AttributesAccessor.new(object.class.inspect)
- extend @virtus_attributes_accessor_module
+ extend InstanceMethods
+ extend attribute_set
end
end
private_class_method :extended
@@ -51,7 +50,6 @@ def self.extended(object)
# @api public
def attribute(*args)
attribute = Attribute.build(*args)
- attribute.define_accessor_methods(@virtus_attributes_accessor_module)
virtus_add_attribute(attribute)
self
end
@@ -8,6 +8,8 @@
let(:object) { described_class.new(parent, attributes) }
let(:name) { :name }
+ before { attribute.stub(:define_accessor_methods) }
+
context 'with a new attribute' do
let(:attribute) { mock('Attribute', :name => name) }
@@ -1,7 +1,7 @@
require 'spec_helper'
-describe Virtus::AttributesAccessor, '#define_reader_method' do
- subject { described_class.new('Test') }
+describe Virtus::AttributeSet, '#define_reader_method' do
+ subject { described_class.new }
let(:attribute) { mock('attribute') }
@@ -1,7 +1,7 @@
require 'spec_helper'
-describe Virtus::AttributesAccessor, '#define_writer_method' do
- subject { described_class.new('Test') }
+describe Virtus::AttributeSet, '#define_writer_method' do
+ subject { described_class.new }
let(:attribute) { mock('attribute') }
@@ -1,9 +1,9 @@
require 'spec_helper'
-describe Virtus::AttributesAccessor, '#inspect' do
+describe Virtus::AttributeSet, '#inspect' do
subject { object.inspect }
let(:object) { described_class.new('Test') }
- it { should eql('Test::AttributesAccessor') }
+ it { pending; should eql('Test::AttributeSet') }
end
@@ -9,6 +9,8 @@
let(:name) { :name }
let(:other) { [ attribute ] }
+ before { attribute.stub(:define_accessor_methods) }
+
context 'with a new attribute' do
let(:attribute) { mock('Attribute', :name => name) }
@@ -8,6 +8,8 @@
let(:attributes) { [ attribute ] }
let(:object) { described_class.new(parent, attributes) }
+ before { attribute.stub(:define_accessor_methods) }
+
context 'when the parent has no attributes' do
let(:parent) { described_class.new }
@@ -39,6 +41,8 @@
let(:parent) { described_class.new([ parent_attribute ]) }
let(:new_attribute) { mock('New Attribute', :name => :parent_name) }
+ before { new_attribute.stub(:define_accessor_methods) }
+
it { should equal(object) }
it 'includes changes from the parent' do
@@ -13,6 +13,7 @@ def assert_attribute_added(klass, name, attribute_class)
attributes[name].should be_nil
subject
attribute = attributes[name]
+ attribute.should_not be_nil
attribute.name.should be(name)
attribute.class.should be(attribute_class)
end
@@ -5,15 +5,15 @@
let(:object) { Class.new { extend Virtus::ClassMethods } }
- it 'includes an AttributesAccessor module' do
+ it 'includes an AttributeSet module' do
descendant = subject
# return the descendant's attribute accessor modules (superclass + own)
- modules = descendant.ancestors.grep(Virtus::AttributesAccessor)
+ modules = descendant.ancestors.grep(Virtus::AttributeSet)
modules.size.should be(2)
# remove the superclass' attribute accessor module
- modules -= object.ancestors.grep(Virtus::AttributesAccessor)
+ modules -= object.ancestors.grep(Virtus::AttributeSet)
# the descendant should have it's own attribute accessor module
modules.size.should be(1)

0 comments on commit d606d65

Please sign in to comment.