Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Support for passing arguments to a constructor

- Fix allowing callbacks to be overridden for a local schematic
  • Loading branch information...
commit 564944c58b664210a0f18ea02d03acfaa343d528 1 parent 6ca6903
Les Hill and Sandro Turriate authored Paul Elliott committed
View
7 Changelog.markdown
@@ -1,3 +1,10 @@
+### 0.9.0 (master) ###
+
+* Bugfix: callbacks are copied to the local override (leshill and sandro)
+* Support for classes with required arguments in their constructor (leshill
+and sandro)
+
+
### 0.8.3 (09/30/2010) ###
* Bugfix: Non-association virtual attributes were being generated lazily
View
8 README.markdown
@@ -63,6 +63,14 @@ Breaking down the above, we are defining a "company" fabricator, which will gene
* After the object is built but before it is saved, it will update the name to "Another Fun Factory".
* After the object is created, it will update the "ceo" association with a new "drone" record.
+
+For a class with required arguments in its constructor, use the `on_init` method:
+
+ Fabricator(:location) do
+ on_init { init_with(30.284167, -81.396111) }
+ end
+
+
### Inheritance ###
So you already have a company fabricator, but you need one that specifically generates an LLC. No problem!
View
7 lib/fabrication/generator/base.rb
@@ -3,7 +3,12 @@ class Fabrication::Generator::Base
def self.supports?(klass); true end
def generate(options={:save => true}, attributes=[], callbacks={})
- self.instance = klass.new
+ if callbacks[:on_init]
+ self.instance = klass.new(*callbacks[:on_init].call)
+ else
+ self.instance = klass.new
+ end
+
process_attributes(attributes)
callbacks[:after_build].each { |callback| callback.call(instance) } if callbacks[:after_build]
View
20 lib/fabrication/schematic.rb
@@ -38,11 +38,13 @@ def callbacks
end
def generate(options={}, overrides={}, &block)
- attributes = merge(overrides, &block).attributes
- if options[:attributes]
- to_hash(attributes, overrides)
- else
- generator.new(klass).generate(options, attributes, callbacks)
+ new_schematic = merge(overrides, &block)
+ new_schematic.instance_eval do
+ if options[:attributes]
+ to_hash(attributes, overrides)
+ else
+ generator.new(klass).generate(options, attributes, callbacks)
+ end
end
end
@@ -57,6 +59,10 @@ def initialize_copy(original)
end
end
+ def init_with(*args)
+ args
+ end
+
def merge(overrides={}, &block)
clone.tap do |schematic|
schematic.instance_eval(&block) if block_given?
@@ -87,6 +93,10 @@ def method_missing(method_name, *args, &block)
end
end
+ def on_init(&block)
+ callbacks[:on_init] = block
+ end
+
def parse_method_name(method_name, args)
if method_name.to_s.end_with?("!")
method_name = method_name.to_s.chomp("!").to_sym
View
33 spec/fabrication/generator/base_spec.rb
@@ -36,6 +36,39 @@
person.instance_variable_get(:@first_name).should == 'Guy'
end
+ context "with on_init block" do
+ subject { schematic.generate }
+
+ let(:klass) { Struct.new :arg1, :arg2 }
+
+ context "using init_with" do
+ let(:schematic) do
+ Fabrication::Schematic.new(klass) do
+ on_init { init_with(:a, :b) }
+ end
+ end
+
+ it "sends the return value of the block to the klass' initialize method" do
+ subject.arg1.should == :a
+ subject.arg2.should == :b
+ end
+ end
+
+ context "not using init_with" do
+ let(:schematic) do
+ Fabrication::Schematic.new(klass) do
+ on_init { [ :a, :b ] }
+ end
+ end
+
+ it "sends the return value of the block to the klass' initialize method" do
+ subject.arg1.should == :a
+ subject.arg2.should == :b
+ end
+
+ end
+ end
+
end
end
View
27 spec/fabrication/schematic_spec.rb
@@ -135,4 +135,31 @@
end
+ describe "#on_init" do
+ let(:init_block) { lambda {} }
+ let(:init_schematic) do
+ block = init_block
+ Fabrication::Schematic.new(OpenStruct) do
+ on_init &block
+ end
+ end
+
+ it "stores the on_init callback" do
+ init_schematic.callbacks[:on_init].should == init_block
+ end
+
+ context "with inheritance" do
+ let(:child_block) { lambda {} }
+ let(:child_schematic) do
+ block = child_block
+ init_schematic.merge do
+ on_init &block
+ end
+ end
+
+ it "overwrites the on_init callback" do
+ child_schematic.callbacks[:on_init].should == child_block
+ end
+ end
+ end
end
View
11 spec/fabrication_spec.rb
@@ -56,6 +56,17 @@
end
+ context 'when the class requires a constructor' do
+ subject do
+ Fabricate(:city) do
+ on_init { init_with('Jacksonville Beach', 'FL') }
+ end
+ end
+
+ its(:city) { should == 'Jacksonville Beach' }
+ its(:state) { should == 'FL' }
+ end
+
context "when referring to other fabricators" do
let(:person) { Fabricate(:person) }
View
4 spec/fabricators.rb
@@ -29,6 +29,10 @@
after_build { |senior| senior.age *= 7 }
end
+Fabricator(:city) do
+ on_init { init_with('Boulder', 'CO') }
+end
+
# ActiveRecord Objects
Fabricator(:division) do
name "Division Name"
View
9 spec/support/helper_objects.rb
@@ -9,3 +9,12 @@ class Location
class Person
attr_accessor :age, :first_name, :last_name, :shoes, :location
end
+
+class City
+ attr_accessor :city, :state
+
+ def initialize(city, state)
+ self.city = city
+ self.state = state
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.