Skip to content

Commit

Permalink
New syntax type, much cleaner interface.
Browse files Browse the repository at this point in the history
  • Loading branch information
cmeiklejohn committed Aug 21, 2011
1 parent 8c2a99a commit c51a04f
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 10 deletions.
8 changes: 8 additions & 0 deletions README.rdoc
Expand Up @@ -19,6 +19,14 @@ objects are meant for integration tests where persistence is required.

=== Learn profiles

==== Implicit profiles

Specify a dependency hash of profile name to objects. The watchmaker
will either yield another watchmaker or a factory when resolving those
dependencies.

Watchmaker.learn :lots_of_things => [:car, :garage, :boat]

==== Lambda-based profiles

When called, will call the lambda.
Expand Down
2 changes: 1 addition & 1 deletion lib/watchmaker.rb
Expand Up @@ -5,7 +5,7 @@
require "watchmaker/learner"
require "watchmaker/constructor"

module Watchmaker
module Watchmaker # :nodoc:
include Learner
include Constructor
end
10 changes: 7 additions & 3 deletions lib/watchmaker/configuration.rb
@@ -1,6 +1,6 @@
# encoding: UTF-8

module Watchmaker
module Watchmaker # :nodoc:

# Singleton configuration class to hold all configured information.
#
Expand All @@ -26,14 +26,18 @@ def self.learned(name)
instance.learned(name)
end

def learn(name, dependencies, &block)
def self.learned?(name)
!!learned(name)
end

def learn(name, dependencies, &block) # :nodoc:
@profiles[name] = {
:dependencies => dependencies,
:block => block
}
end

def learned(name)
def learned(name) # :nodoc:
@profiles[name]
end

Expand Down
30 changes: 27 additions & 3 deletions lib/watchmaker/constructor.rb
Expand Up @@ -6,8 +6,20 @@ module Constructor

module ClassMethods

# Contruct a profile.
# Construct from a factory.
#
def construct_from_factory(factory)
Factory.create(factory.to_sym)
end

# Construct from another watchmaker.
#
def construct_from_watchmaker(watchmaker)
construct(watchmaker.to_sym)
end

# Contruct a profile.
#
def construct(profile)

# Store created objects.
Expand All @@ -20,19 +32,31 @@ def construct(profile)

if dependencies = selected_profile[:dependencies]

# For any abstract dependencies, infer how to create them.
#
if abstracts = dependencies[:abstract]
abstracts.each do |abstract|
if Configuration.learned?(abstract)
objects << construct_from_watchmaker(abstract)
else
objects << construct_from_factory(abstract)
end
end
end

# For any supplied factories, create them.
#
if factories = dependencies[:factories]
factories.each do |factory|
objects << Factory.create(factory.to_sym)
objects << construct_from_factory(factory)
end
end

# For any supplied watchmakers, create them.
#
if watchmakers = dependencies[:watchmakers]
watchmakers.each do |watchmaker|
objects << construct(watchmaker.to_sym)
objects << construct_from_watchmaker(watchmaker)
end
end

Expand Down
23 changes: 23 additions & 0 deletions lib/watchmaker/learner.rb
Expand Up @@ -9,9 +9,32 @@ module ClassMethods
# Learn a profile by taking explicit dependencies.
#
def learn(name, dependencies = {}, &block)

if name.is_a?(Hash)

# Convert the hash into a profile name and a list of
# dependencies that's either a hash of nested classes or
# array.
#
name, dependencies =
name_and_dependencies_from_dependency_hash(name)

# Specifically store these as abstract dependencies.
#
dependencies = { :abstract => dependencies }

end

Configuration.learn(name, dependencies, &block)
end

# Get the profile name out of a dependency hash.
#
def name_and_dependencies_from_dependency_hash(dependencies)
name = dependencies.keys.first
[name, dependencies[name]]
end

end
end
end
2 changes: 1 addition & 1 deletion lib/watchmaker/version.rb
@@ -1,5 +1,5 @@
# encoding: UTF-8

module Watchmaker # :nodoc:
VERSION = "0.0.1"
VERSION = "0.1.0"
end
9 changes: 8 additions & 1 deletion spec/models/garage_spec.rb
Expand Up @@ -33,8 +33,15 @@
end

it "should create a car from the watchmaker based watchmaker" do
Watchmaker.construct(:car).first.should be_a_kind_of Car
Watchmaker.construct(:car_with_garage).first.should be_a_kind_of Car
Car.all.count.should == 1
Garage.all.count.should == 1
end

it "should be able to use the new syntax to build based on factories or watchmakers" do
Watchmaker.construct(:two_cars_and_two_garages)
Garage.all.count.should == 2
Car.all.count.should == 2
Garage.last.cars.count.should == 2
end
end
11 changes: 10 additions & 1 deletion spec/support/watchmakers.rb
Expand Up @@ -14,8 +14,17 @@

Watchmaker.learn :garage, :factories => [:garage]

Watchmaker.learn :car, :factories => [:car], :watchmakers => [:garage]
Watchmaker.learn :car_with_garage, :factories => [:car], :watchmakers => [:garage]

Watchmaker.learn :car_in_garage, :factories => [:garage, :car] do |garage, car|
garage.cars << car
end

Watchmaker.learn :two_garages, :factories => [:garage, :garage]

Watchmaker.learn :two_cars_and_two_garages => [:two_garages, :car, :car] do |garages, car1, car2|
garages.each do |garage|
garage.cars << car1
garage.cars << car2
end
end

0 comments on commit c51a04f

Please sign in to comment.