Permalink
Browse files

Overrides, relation tests, API revisions.

I've revised the configuration API to allow more intuitive override
capability and provide a counter for generation of unique values. The
result ends up looking quite a bit like machinist.

 * README.txt
   - lots of API changes
 * lib/modelfactory.rb
   - new class InstanceBuilder handles instance initialization
 * test/fixtures/category.rb, test/fixtures/schema.rb
   - new fixture for testing factory-generated relations
 * test/relation_test.rb
   - tests for factory-created relations
 * test/named_test.rb
   - moved tests for named configurations to a separate file
 * test/counter_test.rb
   - moved tests for counter functionality to a separate file
  • Loading branch information...
1 parent 937ec0b commit 519834f9bd11116a87ad892f7bd7ebf6de678f73 Zack Hobson committed May 26, 2009
View
@@ -18,9 +18,9 @@ opaque ActiveRecord objects whose contents are unimportant.
require 'modelfactory'
ModelFactory.configuration do
- default(User) do |m|
- m.name = "Factory User"
- m.email = "user@factory.ws"
+ default(User) do
+ name { "Factory User" }
+ email { "user@factory.ws" }
end
end
@@ -50,7 +50,7 @@ raised.
end
ModelFactory.configure do
- default(Widget) {|w| w.name = 'widget' }
+ default(Widget) { name { 'widget' } }
end
# Raises an error because no desc was provided:
@@ -61,7 +61,10 @@ raised.
# Doesn't raise, required values are defined in the default factory:
ModelFactory.configure do
- default(Widget) {|w| w.name = 'widget'; w.desc = 'widget desc' }
+ default(Widget) do
+ name { 'widget' }
+ desc { 'widget desc' }
+ end
end
Widget.factory.create
@@ -71,9 +74,9 @@ created. This counter is passed to model initialization blocks to make it
easier to generate unique values:
ModelFactory.configuration do
- default(User) do |m, i|
- m.name = "Factory User #{i}"
- m.email = "user#{i}@factory.ws"
+ default(User) do
+ name {|i| "Factory User #{i}" }
+ email {|i| "user#{i}@factory.ws" }
end
end
@@ -83,9 +86,9 @@ easier to generate unique values:
It's possible to configure named factories:
ModelFactory.configuration do
- admin(User) do |m, i|
- m.name = "Admin User #{i}"
- m.admin = true
+ admin(User) do
+ name {|i| "Admin User #{i}" }
+ admin { true }
end
end
View
@@ -17,7 +17,7 @@ Hoe.new('ModelFactory', ModelFactory::VERSION::STRING) do |p|
p.test_globs = ["test/**/*_test.rb"]
p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
p.extra_dev_deps = %w[
- active_record mocha thoughtbot-shoulda sqlite3-ruby mislav-hanna
+ activerecord mocha thoughtbot-shoulda sqlite3-ruby mislav-hanna
]
end
View
@@ -1,7 +1,7 @@
require 'rubygems'
require 'active_record'
-require 'modelfactory/factory'
-require 'modelfactory/legacy'
+require File.dirname(__FILE__) + '/modelfactory/factory'
+require File.dirname(__FILE__) + '/modelfactory/legacy'
ActiveRecord::Base.class_eval do
def self.factory ; ModelFactory[self] ; end
@@ -34,16 +34,7 @@ def next_counter
def new_named(name, opt = {}, &block)
instance = @class.new
- if @options[name]
- case @options[name].arity
- when 2
- @options[name].call(instance, next_counter) if @options[name]
- else
- @options[name].call(instance) if @options[name]
- end
- end
- opt.each {|k,v| instance.send("#{k}=", v) }
- yield instance if block_given?
+ InstanceBuilder.new(instance, opt, next_counter, &@options[name])
instance
end
@@ -56,4 +47,21 @@ def create_named(name, opt = {}, &block)
end
+ class InstanceBuilder # :nodoc:
+ def initialize(instance, params, counter, &block)
+ @instance = instance
+ @params = params
+ @counter = counter
+ @params.each { |attr, value| @instance.send "#{attr}=", value }
+ instance_eval(&block) if block_given?
+ end
+
+ def method_missing(method, &block)
+ if block_given? && !@params.key?(method.to_sym)
+ @instance.send "#{method}=",
+ (block.arity == 1) ? block.call(@counter) : block.call
+ end
+ end
+ end
+
end
View
@@ -0,0 +1,25 @@
+require File.dirname(__FILE__) + '/test_helper'
+require File.dirname(__FILE__) + '/../lib/modelfactory'
+
+class ModelFactoryTest < Test::Unit::TestCase
+ context "with a specified default that uses automatic numbering" do
+ setup do
+ ModelFactory.configure do
+ default(Widget) { price {|i| i } }
+ end
+ end
+
+ should "start counting at 1 after configuration" do
+ assert_equal 1.0, Widget.factory.create.price
+ end
+
+ should "generate a unique sequence" do
+ w = []
+ 3.times { w << Widget.factory.create.price }
+ assert_equal w.uniq, w
+ end
+
+ end
+end
+
+
@@ -0,0 +1,4 @@
+class Category < ActiveRecord::Base
+ has_many :widgets
+end
+
View
@@ -3,6 +3,11 @@
t.string "name"
t.decimal "price"
t.string "type"
+ t.integer "category_id"
+ end
+
+ create_table "categories", :force => true do |t|
+ t.string "name"
end
end
View
@@ -1,4 +1,4 @@
-
class Widget < ActiveRecord::Base
+ belongs_to :category
end
File renamed without changes.
View
@@ -1,86 +0,0 @@
-require File.dirname(__FILE__) + '/test_helper'
-require File.dirname(__FILE__) + '/../lib/modelfactory'
-
-class ModelFactoryTest < Test::Unit::TestCase
-
- should "not instantiate when using new" do
- assert Widget.factory.new.new_record?
- end
-
- should "instantiate when using create" do
- assert !Widget.factory.create.new_record?
- end
-
- should "raise on creation of invalid records" do
- assert_raises(ActiveRecord::RecordInvalid) { StrictWidget.factory.create }
- end
-
- context "with a specified default that uses automatic numbering" do
- setup do
- ModelFactory.configure do
- default(Widget) {|w, i| w.price = i }
- end
- end
-
- should "start counting at 1 after configuration" do
- assert_equal 1.0, Widget.factory.create.price
- end
-
- should "generate a unique sequence" do
- w = []
- 3.times { w << Widget.factory.create.price }
- assert_equal w.uniq, w
- end
- end
-
- context "with a specified default" do
- setup do
- ModelFactory.configure do
- default(Widget) {|w| w.name = 'foobaz' }
- end
- end
-
- should "initialize defaults with no arguments" do
- assert_equal 'foobaz', Widget.factory.create.name
- end
-
- should "initialize defaults with an unspecified argument" do
- assert_equal 'foobaz', Widget.factory.create(:price => 4.0).name
- end
-
- should "initialize with an unspecified argument" do
- assert_equal 4, Widget.factory.create(:price => 4.0).price
- end
- end
-
- context "with a named factory" do
- setup do
- ModelFactory.configure do
- default(Widget) {|w| w.name = 'wubbo' }
- favorite(Widget) {|w| w.name = 'foobaz' }
- end
- end
-
- should "not apply named config to default" do
- assert_equal 'wubbo', Widget.factory.create.name
- end
-
- should "not apply any config to unrecognized name" do
- assert_equal nil, Widget.factory.create_emptyfoo.name
- end
-
- should "initialize defaults with no arguments" do
- assert_equal 'foobaz', Widget.factory.create_favorite.name
- end
-
- should "initialize defaults with an unspecified argument" do
- assert_equal 'foobaz', Widget.factory.create_favorite(:price => 4.0).name
- end
-
- should "initialize with an unspecified argument" do
- assert_equal 4, Widget.factory.create_favorite(:price => 4.0).price
- end
- end
-end
-
-
View
@@ -0,0 +1,40 @@
+require File.dirname(__FILE__) + '/test_helper'
+require File.dirname(__FILE__) + '/../lib/modelfactory'
+
+class ModelFactoryTest < Test::Unit::TestCase
+
+ should "not instantiate when using new" do
+ assert Widget.factory.new.new_record?
+ end
+
+ should "instantiate when using create" do
+ assert !Widget.factory.create.new_record?
+ end
+
+ should "raise on creation of invalid records" do
+ assert_raises(ActiveRecord::RecordInvalid) { StrictWidget.factory.create }
+ end
+
+ context "with a specified default" do
+ setup do
+ ModelFactory.configure do
+ default(Widget) { name {'foobaz' } }
+ end
+ end
+
+ should "initialize defaults with no arguments" do
+ assert_equal 'foobaz', Widget.factory.create.name
+ end
+
+ should "initialize defaults with an unspecified argument" do
+ assert_equal 'foobaz', Widget.factory.create(:price => 4.0).name
+ end
+
+ should "initialize with an unspecified argument" do
+ assert_equal 4, Widget.factory.create(:price => 4.0).price
+ end
+ end
+
+end
+
+
View
@@ -0,0 +1,35 @@
+require File.dirname(__FILE__) + '/test_helper'
+require File.dirname(__FILE__) + '/../lib/modelfactory'
+
+class ModelFactoryTest < Test::Unit::TestCase
+ context "with a named factory" do
+ setup do
+ ModelFactory.configure do
+ default(Widget) { name { 'wubbo' } }
+ favorite(Widget) { name { 'foobaz' } }
+ end
+ end
+
+ should "not apply named config to default" do
+ assert_equal 'wubbo', Widget.factory.create.name
+ end
+
+ should "not apply any config to unrecognized name" do
+ assert_equal nil, Widget.factory.create_emptyfoo.name
+ end
+
+ should "initialize defaults with no arguments" do
+ assert_equal 'foobaz', Widget.factory.create_favorite.name
+ end
+
+ should "initialize defaults with an unspecified argument" do
+ assert_equal 'foobaz', Widget.factory.create_favorite(:price => 4.0).name
+ end
+
+ should "initialize with an unspecified argument" do
+ assert_equal 4, Widget.factory.create_favorite(:price => 4.0).price
+ end
+ end
+end
+
+
View
@@ -0,0 +1,34 @@
+require File.dirname(__FILE__) + '/test_helper'
+require File.dirname(__FILE__) + '/../lib/modelfactory'
+
+class ModelFactoryTest < Test::Unit::TestCase
+ context "initializing a belongs_to relation" do
+ setup do
+ ModelFactory.configure do
+ default(Category) do
+ name { "Factory Category" }
+ end
+ default(Widget) do
+ category { Category.factory.create }
+ end
+ end
+ end
+
+ should "automatically create parent instance" do
+ old_count = Category.count
+ assert !Widget.factory.create.category.nil?
+ assert_equal old_count + 1, Category.count
+ end
+
+ should "do not create a parent when one is passed in" do
+ old_count = Category.count
+ Widget.factory.create(:category => nil)
+ assert_equal old_count, Category.count
+ end
+
+ should "do not assign a parent when nil is passed in" do
+ assert Widget.factory.create(:category => nil).category.nil?
+ end
+ end
+end
+

0 comments on commit 519834f

Please sign in to comment.