Skip to content

Commit

Permalink
Add a way to build new objects
Browse files Browse the repository at this point in the history
Concept: allow formal_wearing objects to set up new objects as targets for saving data.
  • Loading branch information
wideopenspaces committed Jul 11, 2013
1 parent 6b5936a commit 8390385
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 1 deletion.
9 changes: 9 additions & 0 deletions lib/formal_wear/class_methods.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
module FormalWear
module ClassMethods
def build(name, block)
create_accessors([name])
define_build_method(name, block)
end

def create_accessors(keys)
keys.each { |k| self.send(:attr_accessor, k) unless method_defined?(k) }
end

def define_build_method(name, block)
define_method(:"build_#{name}") { block.call }
end

def validate_attrs!(attrs)
attrs.each do |a, opts|
opts.assert_valid_keys(*ALLOWED_KEYS)
Expand Down
7 changes: 6 additions & 1 deletion lib/formal_wear/instance_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module InstanceMethods
def initialize(options = {})
set_sources(options)
update_sources
build_objects
end

def required_attributes
Expand Down Expand Up @@ -80,6 +81,10 @@ def saving(&block)
after_save
end

def build_objects
self.methods.select { |m| m.match(/build_/) }.each { |m| self.send(:"#{m.to_s.sub(/\Abuild_/, '')}=", self.send(m)) }
end

def sanitize_and_fill_attributes(fields)
fields.deep_dup.each do |field, options|
fill_attributes!(field, options)
Expand Down Expand Up @@ -155,7 +160,7 @@ def set_source_reader(alt, obj)
def update_sources
required_fields.each do |field, options|
send(:"#{field}=", options[:source].call(self)) if options[:source] rescue nil
end
end if required_fields
end
end
end
37 changes: 37 additions & 0 deletions spec/bare_object_spec.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,49 @@
require 'spec_helper'
require_relative './support/bare_object'
require_relative './support/new_object'
require 'pry'

describe BareObject do
let(:obj) { BareObject }

context 'including FormalWear' do
before { obj.send(:include, FormalWear) }

context 'when build is invoked' do
before do
obj.class_eval do
build :new_obj, -> { NewObject.new }
end
end

it 'creates a reader called new_obj' do
obj.method_defined?(:new_obj).should be_true
end

it 'creates a method called build_new_obj' do
obj.method_defined?(:build_new_obj).should be_true
end

context 'and BareObject is instantiated' do
let!(:new_object) { NewObject.new }
subject { BareObject.new(ExternalObjectOne.new('Formal', 'Wear')) }

it 'invokes build_new_obj' do
BareObject.any_instance.expects(:build_new_obj).returns(true)
subject
end

it 'creates a NewObj' do
NewObject.expects(:new).returns(new_object)
subject
end

it 'stores NewObj in @new_obj' do
subject.new_obj.should be_a(NewObject)
end
end
end

context 'when required_attr is invoked' do
before do
obj.class_eval do
Expand Down
2 changes: 2 additions & 0 deletions spec/support/new_object.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class NewObject
end

0 comments on commit 8390385

Please sign in to comment.