factory_loader 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,5 @@
1
+ === 0.1.0 / 2008-03-17
2
+
3
+ * Initial release
4
+
5
+
data/Manifest.txt ADDED
@@ -0,0 +1,17 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/factory_loader.rb
6
+ spec/factory_loader_spec.rb
7
+ spec/sample_project
8
+ spec/sample_project/lib
9
+ spec/sample_project/lib/cat.rb
10
+ spec/sample_project/lib/dog.rb
11
+ spec/sample_project/lib/factories
12
+ spec/sample_project/lib/factories/fish
13
+ spec/sample_project/lib/factories/fish/dolphin_factory.rb
14
+ spec/sample_project/lib/fish
15
+ spec/sample_project/lib/fish/dolphin.rb
16
+ spec/sample_project/lib/fish/guppy.rb
17
+ spec/spec_helper.rb
data/README.txt ADDED
@@ -0,0 +1,48 @@
1
+ = FactoryLoader
2
+
3
+ * http://www.continuousthinking.com/factory_loader (url)
4
+
5
+ == DESCRIPTION:
6
+
7
+ FactoryLoader is intended to help scale object creation with less pain and less refactoring.
8
+
9
+ Public git repository: git://github.com/zdennis/factory_loader.git
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ == SYNOPSIS:
14
+
15
+ See RDOC
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * active_support
20
+
21
+ == INSTALL:
22
+
23
+ * gem install factory_loader
24
+
25
+ == LICENSE:
26
+
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2008 Zach Dennis, Mutually Human Software
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining
32
+ a copy of this software and associated documentation files (the
33
+ 'Software'), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rake/rdoctask'
2
+
3
+ task :default => :spec
4
+
5
+ task :spec do
6
+ system "spec spec --pattern '**/*_spec.rb'"
7
+ end
8
+
9
+ desc "Generate RDoc documentation"
10
+ Rake::RDocTask.new do |rdoc|
11
+ rdoc.rdoc_dir = 'rdoc'
12
+ rdoc.title = "FactoryLoader: intended to help scaling complex object creation with less pain and less refactoring."
13
+ rdoc.rdoc_files.include('lib/**/*.rb', 'README','CHANGES','MIT-LICENSE')
14
+ end
15
+
16
+ require 'rubygems'
17
+ require 'hoe'
18
+ require './lib/factory_loader.rb'
19
+
20
+ Hoe.new('factory_loader', FactoryLoader::VERSION) do |p|
21
+ p.developer('Zach Dennis', 'zach.dennis@gmail.com')
22
+ end
@@ -0,0 +1,97 @@
1
+ require 'find'
2
+
3
+ # FactoryLoader is intended to help scale object creation with less pain and less
4
+ # refactoring.
5
+ #
6
+ # In the early stages of a project object creation is simple and object
7
+ # dependencies are kept to a minimum. As the project grows so does the
8
+ # complexity of object dependencies and object creation. It doesn't make
9
+ # sense to create custom factory classes upfront to deal with complex
10
+ # object construction that may not exist yet. But when those custom
11
+ # factories are needed it is usually painful and time consuming to update
12
+ # the code base to use them. It's also easy for developers to give-in
13
+ # due to time constraints and start making bad decisions.
14
+ #
15
+ # This is where FactoryLoader comes into play. It automaticaly creates a Factory
16
+ # class for your objects and provides a Factory#create method which passes any arguments
17
+ # along to your object's constructor.
18
+ #
19
+ # When you need to have custom factory behavior you can implement the factory
20
+ # without having to update other code references (assuming you've used them
21
+ # in the rest of your application rather then direct class references).
22
+ #
23
+ # For example given a directory structure like the below:
24
+ #
25
+ # init.rb
26
+ # lib/
27
+ # |--things/
28
+ # |-- foo.rb
29
+ # |-- bar.rb
30
+ # |--factories/
31
+ # |-- bar_factory.rb
32
+ #
33
+ # Given this project directory structure you could have the following code
34
+ # in init.rb:
35
+ # factory_loader = FactoryLoader.new("lib/factories")
36
+ # factory_loader.load("lib/things")
37
+ #
38
+ # The first call constructs a factory loader telling it which directory is used
39
+ # to store custom factories.
40
+ #
41
+ # The second call will create a factory for each *.rb file in the lib/things/
42
+ # directory. So for the foo.rb file a FooFactory class will be created
43
+ # which can be used to wrap creation of Foo objects. The generated factory
44
+ # will provide a #create method which will pass along all arguments to
45
+ # the constructor of the object it wraps. So...
46
+ # FooFactory.new.create :a => :b
47
+ # is the same as:
48
+ # Foo.new :a => :b
49
+ #
50
+ # A FooFactory will be created, but a BarFactory will not. This is because
51
+ # we told the FactoryLoader that custom factories are storied in lib/factories/
52
+ # and a bar_factory.rb exists there, so FactoryLoader assumes you want to use
53
+ # a custom factory.
54
+ #
55
+ # Author: Zach Dennis, zdennis at mutuallyhuman dot com
56
+ class FactoryLoader
57
+ VERSION = "0.1.0"
58
+
59
+ def initialize(*factory_paths)
60
+ @factory_paths = factory_paths.map{ |f| File.expand_path(f) }
61
+ end
62
+
63
+ def load(directory) # :nodoc:
64
+ Dir[directory + "/**/*.rb"].each do |file|
65
+ object_filename = File.basename(file, ".rb")
66
+ factory_filepath = "#{object_filename}_factory.rb"
67
+ unless custom_factory_exists?(factory_filepath)
68
+ load_object_factory object_filename.classify
69
+ end
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def custom_factory_exists?(factory_filepath)
76
+ found = false
77
+ @factory_paths.find do |path|
78
+ found = Dir["#{path}/**/#{factory_filepath}"].any?
79
+ end
80
+ found
81
+ end
82
+
83
+ def load_object_factory(object_name)
84
+ factory_name = "#{object_name}Factory"
85
+ unless Object.const_defined?(factory_name)
86
+ eval <<-CODE
87
+ class ::#{factory_name}
88
+ def create(options={})
89
+ #{object_name}.new options
90
+ end
91
+ end
92
+ CODE
93
+ end
94
+ end
95
+ end
96
+
97
+
@@ -0,0 +1,70 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'fileutils'
3
+
4
+ describe FactoryLoader, "#load" do
5
+ def load
6
+ FactoryLoader.new(CUSTOM_FACTORIES_DIR).load(SAMPLE_LIB_DIR)
7
+ end
8
+
9
+ it "creates a factory for each .rb file in the loaded directory" do
10
+ load
11
+ Object.const_defined?("CatFactory").should be_true
12
+ Object.const_defined?("DogFactory").should be_true
13
+ end
14
+
15
+ it "creates a factory for each .rb object in sub-directories of the loaded directory" do
16
+ load
17
+ Object.const_defined?("GuppyFactory").should be_true
18
+ end
19
+
20
+ it "does not create a factory for .rb files in any custom factory directory" do
21
+ load
22
+ Object.const_defined?("AnimalFactory").should be_false
23
+ end
24
+
25
+ it "does not create a factory for .rb files in a sub-directory of any custom factory directory" do
26
+ load
27
+ Object.const_defined?("DolphinFactory").should be_false
28
+ end
29
+
30
+ describe "when a set of custom factory paths are given" do
31
+ before(:all) do
32
+ FileUtils.touch(SAMPLE_LIB_DIR + "/animal.rb")
33
+ FileUtils.touch(CUSTOM_FACTORIES_DIR + "/animal_factory.rb")
34
+ end
35
+
36
+ after(:all) do
37
+ FileUtils.rm(SAMPLE_LIB_DIR + "/animal.rb")
38
+ FileUtils.rm(CUSTOM_FACTORIES_DIR + "/animal_factory.rb")
39
+ end
40
+
41
+ it "does not create a factory for the presenter" do
42
+ load
43
+ Object.const_defined?("AnimalFactory").should be_false
44
+ end
45
+ end
46
+
47
+ describe "a created factory" do
48
+ before(:all) do
49
+ ::Person = stub("Person model")
50
+ Dir["#{SAMPLE_LIB_DIR}/*.rb"].each{ |f| require f }
51
+ load
52
+ end
53
+
54
+ describe '#create' do
55
+ before do
56
+ @object = mock "some new object"
57
+ ::Dog.stub!(:new).and_return(@object)
58
+ end
59
+
60
+ it "creates a presenter passing along any options" do
61
+ ::Dog.should_receive(:new).with(:foo => :bar)
62
+ ::DogFactory.new.create(:foo => :bar)
63
+ end
64
+
65
+ it "returns the newly created presenter" do
66
+ ::DogFactory.new.create.should == @object
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ class Cat
2
+
3
+ end
@@ -0,0 +1,2 @@
1
+ class Dog
2
+ end
File without changes
@@ -0,0 +1,2 @@
1
+ class Guppy
2
+ end
@@ -0,0 +1,18 @@
1
+ require 'fileutils'
2
+
3
+ spec_helper = File.dirname(__FILE__) + '/../../../../spec/spec_helper.rb'
4
+ if File.exists?(spec_helper)
5
+ puts "Running specs inside of rails project. Letting the Rails project load rspec."
6
+ require spec_helper
7
+ else
8
+ puts "Running specs outside of rails project. Using active_support and rspec gems."
9
+ require 'rubygems'
10
+ require 'active_support'
11
+ require 'spec'
12
+ end
13
+
14
+ SAMPLE_PROJECT_DIR = File.dirname(__FILE__) + '/sample_project'
15
+ CUSTOM_FACTORIES_DIR = SAMPLE_PROJECT_DIR + "/lib/factories"
16
+ SAMPLE_LIB_DIR = SAMPLE_PROJECT_DIR + "/lib"
17
+ FileUtils.mkdir_p(CUSTOM_FACTORIES_DIR)
18
+ require File.dirname(__FILE__) + '/../lib/factory_loader'
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: factory_loader
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Zach Dennis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-03-17 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.5.1
23
+ version:
24
+ description: "FactoryLoader is intended to help scale object creation with less pain and less refactoring. Public git repository: \tgit://github.com/zdennis/factory_loader.git"
25
+ email:
26
+ - zach.dennis@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - History.txt
33
+ - Manifest.txt
34
+ - README.txt
35
+ files:
36
+ - History.txt
37
+ - Manifest.txt
38
+ - README.txt
39
+ - Rakefile
40
+ - lib/factory_loader.rb
41
+ - spec/factory_loader_spec.rb
42
+ - spec/sample_project
43
+ - spec/sample_project/lib
44
+ - spec/sample_project/lib/cat.rb
45
+ - spec/sample_project/lib/dog.rb
46
+ - spec/sample_project/lib/factories
47
+ - spec/sample_project/lib/factories/fish
48
+ - spec/sample_project/lib/factories/fish/dolphin_factory.rb
49
+ - spec/sample_project/lib/fish
50
+ - spec/sample_project/lib/fish/dolphin.rb
51
+ - spec/sample_project/lib/fish/guppy.rb
52
+ - spec/spec_helper.rb
53
+ has_rdoc: true
54
+ homepage: http://www.continuousthinking.com/factory_loader (url)
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --main
58
+ - README.txt
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project: factory_loader
76
+ rubygems_version: 1.0.1
77
+ signing_key:
78
+ specification_version: 2
79
+ summary: FactoryLoader is intended to help scale object creation with less pain and less refactoring
80
+ test_files: []
81
+