Permalink
Browse files

Added support for Fixjour's like attribute overrides

  • Loading branch information...
1 parent 49393d8 commit b4cdaefd347aae51af3fd1ec065f1848080433eb @eeng committed Oct 3, 2012
Showing with 107 additions and 10 deletions.
  1. +1 −0 lib/machinist.rb
  2. +6 −2 lib/machinist/blueprint.rb
  3. +11 −7 lib/machinist/lathe.rb
  4. +44 −0 lib/machinist/overrides.rb
  5. +0 −1 spec/machinable_spec.rb
  6. +45 −0 spec/overrides_spec.rb
View
@@ -2,4 +2,5 @@
require 'machinist/exceptions'
require 'machinist/lathe'
require 'machinist/machinable'
+require 'machinist/overrides'
@@ -21,10 +21,14 @@ def initialize(klass, options = {}, &block)
#
# Pass in attributes to override values defined in the blueprint.
def make(attributes = {})
- lathe = lathe_class.new(@klass, new_serial_number, attributes)
+ # Collect overrides from the hierarchy
+ overrided_attributes = OverridedAttributes.get_from &@block
+ each_ancestor { |blueprint| overrided_attributes += OverridedAttributes.get_from(&blueprint.block) }
+
+ lathe = lathe_class.new(@klass, new_serial_number, attributes, overrided_attributes)
lathe.instance_eval(&@block)
- each_ancestor {|blueprint| lathe.instance_eval(&blueprint.block) }
+ each_ancestor { |blueprint| lathe.instance_eval(&blueprint.block) }
lathe.object
end
View
@@ -7,13 +7,14 @@ module Machinist
# including method_missing to let the blueprint define attributes.
class Lathe
- def initialize(klass, serial_number, attributes = {})
- @klass = klass
- @serial_number = serial_number
- @assigned_attributes = {}
+ def initialize(klass, serial_number, attributes = {}, overrided_attributes = {})
+ @klass = klass
+ @serial_number = serial_number
+ @assigned_attributes = {}
- @object = @klass.new
- attributes.each {|key, value| assign_attribute(key, value) }
+ @object = @klass.new
+ @overrides = Overrides.new(self, attributes)
+ attributes.reject { |key, _| overrided_attributes.include?(key) }.each {|key, value| assign_attribute(key, value) }
end
# Returns a unique serial number for the object under construction.
@@ -35,8 +36,11 @@ def method_missing(attribute, *args, &block) #:nodoc:
undef_method :id if respond_to?(:id)
undef_method :type if respond_to?(:type)
- protected
+ def overrides &block
+ @overrides.instance_eval(&block)
+ end
+ protected
def make_attribute(attribute, args, &block) #:nodoc:
count = args.shift if args.first.is_a?(Fixnum)
if count
View
@@ -0,0 +1,44 @@
+module Machinist
+ class Overrides
+ def initialize lathe, attributes
+ @lathe = lathe
+ @attributes = attributes
+ end
+
+ def method_missing(attribute, *args, &block) #:nodoc:
+ return unless @attributes.has_key?(attribute)
+ @lathe.instance_exec @attributes[attribute], &block
+ end
+ end
+
+ class OverridedAttributes
+ def initialize
+ @accumulator = Accumulator.new
+ end
+
+ def self.get_from &block
+ new.tap { |oa| oa.instance_eval(&block) }.attributes
+ end
+
+ def method_missing(attribute, *args, &block) #:nodoc:
+ return unless attribute.to_sym == :overrides
+ @accumulator.instance_eval(&block)
+ end
+
+ def attributes
+ @accumulator.attributes
+ end
+
+ class Accumulator
+ attr_reader :attributes
+
+ def initialize
+ @attributes = []
+ end
+
+ def method_missing(attribute, *args, &block) #:nodoc:
+ @attributes << attribute
+ end
+ end
+ end
+end
View
@@ -97,5 +97,4 @@ class Comment
exception.blueprint.klass.should == MachinableSpecs::Post
end
end
-
end
View
@@ -0,0 +1,45 @@
+require File.dirname(__FILE__) + '/spec_helper'
+require 'ostruct'
+
+module OverridesSpecs
+ class Post
+ extend Machinist::Machinable
+ attr_accessor :title, :body, :comments
+ end
+
+ class Subpost < Post
+ end
+end
+
+describe Machinist::Blueprint do
+ before(:each) do
+ OverridesSpecs::Post.clear_blueprints!
+
+ OverridesSpecs::Post.blueprint do
+ title { "First Post" }
+ overrides do
+ title_and_body { |tb| object.title, object.body = tb.split(' - ') }
+ body_and_title { |tb| object.body, object.title = tb.split(' | ') }
+ end
+ end
+ end
+
+ it "supports overriding attributes that are not defined in the object" do
+ post = OverridesSpecs::Post.make :title_and_body => "Title - Body"
+ post.title.should == "Title"
+ post.body.should == "Body"
+
+ post = OverridesSpecs::Post.make :body_and_title => "Body | Title"
+ post.title.should == "Title"
+ post.body.should == "Body"
+ end
+
+ it "works with inheritance" do
+ OverridesSpecs::Subpost.blueprint do
+ end
+
+ post = OverridesSpecs::Subpost.make :title_and_body => "Title - Body"
+ post.title.should == "Title"
+ post.body.should == "Body"
+ end
+end

0 comments on commit b4cdaef

Please sign in to comment.