Implicitly call FactoryGirl's syntax methods from dynamic attributes
This commit is contained in:
parent
4682ab0701
commit
29a5ab1a89
|
@ -28,6 +28,7 @@ require 'factory_girl/aliases'
|
|||
require 'factory_girl/definition'
|
||||
require 'factory_girl/definition_proxy'
|
||||
require 'factory_girl/syntax'
|
||||
require 'factory_girl/syntax_runner'
|
||||
require 'factory_girl/find_definitions'
|
||||
require 'factory_girl/reload'
|
||||
require 'factory_girl/version'
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module FactoryGirl
|
||||
class AttributeAssigner
|
||||
def initialize(evaluator, &instance_builder)
|
||||
def initialize(evaluator, build_class, &instance_builder)
|
||||
@build_class = build_class
|
||||
@instance_builder = instance_builder
|
||||
@evaluator = evaluator
|
||||
@attribute_list = evaluator.class.attribute_list
|
||||
|
@ -18,7 +19,7 @@ module FactoryGirl
|
|||
end
|
||||
|
||||
def hash
|
||||
@evaluator.instance = NullObject.new
|
||||
@evaluator.instance = build_hash
|
||||
|
||||
attributes_to_set_on_hash.inject({}) do |result, attribute|
|
||||
result[attribute] = get(attribute)
|
||||
|
@ -32,6 +33,10 @@ module FactoryGirl
|
|||
@build_class_instance ||= @evaluator.instance_exec(&@instance_builder)
|
||||
end
|
||||
|
||||
def build_hash
|
||||
@build_hash ||= NullObject.new(hash_instance_methods_to_respond_to)
|
||||
end
|
||||
|
||||
def get(attribute_name)
|
||||
@evaluator.send(attribute_name)
|
||||
end
|
||||
|
@ -64,6 +69,10 @@ module FactoryGirl
|
|||
@evaluator.__overrides.keys
|
||||
end
|
||||
|
||||
def hash_instance_methods_to_respond_to
|
||||
@attribute_list.map(&:name) + override_names + @build_class.instance_methods
|
||||
end
|
||||
|
||||
def alias_names_to_ignore
|
||||
@attribute_list.reject(&:ignored).map do |attribute|
|
||||
override_names.map {|override| attribute.name if attribute.alias_for?(override) && attribute.name != override && !ignored_attribute_names.include?(override) }
|
||||
|
|
|
@ -47,7 +47,11 @@ module FactoryGirl
|
|||
if @cached_attributes.key?(method_name)
|
||||
@cached_attributes[method_name]
|
||||
else
|
||||
@instance.send(method_name, *args, &block)
|
||||
if @instance.respond_to?(method_name)
|
||||
@instance.send(method_name, *args, &block)
|
||||
else
|
||||
SyntaxRunner.new.send(method_name, *args, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ module FactoryGirl
|
|||
strategy = strategy_class.new
|
||||
|
||||
evaluator = evaluator_class.new(strategy, overrides.symbolize_keys)
|
||||
attribute_assigner = AttributeAssigner.new(evaluator, &instance_builder)
|
||||
attribute_assigner = AttributeAssigner.new(evaluator, build_class, &instance_builder)
|
||||
|
||||
evaluation = Evaluation.new(attribute_assigner, to_create)
|
||||
evaluation.add_observer(CallbackRunner.new(callbacks, evaluator))
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
module FactoryGirl
|
||||
class NullObject < ::BasicObject
|
||||
def method_missing(*args)
|
||||
nil
|
||||
def initialize(methods_to_respond_to)
|
||||
@methods_to_respond_to = methods_to_respond_to.map(&:to_s)
|
||||
end
|
||||
|
||||
def method_missing(name, *args, &block)
|
||||
if respond_to?(name)
|
||||
nil
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def respond_to?(method, include_private=false)
|
||||
@methods_to_respond_to.include? method.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
module FactoryGirl
|
||||
class SyntaxRunner
|
||||
include Syntax::Methods
|
||||
end
|
||||
end
|
|
@ -0,0 +1,41 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe "syntax methods within dynamic attributes" do
|
||||
before do
|
||||
define_model("Post", title: :string, user_id: :integer) do
|
||||
belongs_to :user
|
||||
|
||||
def generate
|
||||
"generate result"
|
||||
end
|
||||
end
|
||||
define_model("User", email: :string)
|
||||
|
||||
FactoryGirl.define do
|
||||
sequence(:email_address) {|n| "person-#{n}@example.com" }
|
||||
|
||||
factory :user do
|
||||
email { generate(:email_address) }
|
||||
end
|
||||
|
||||
factory :post do
|
||||
title { generate }
|
||||
user { build(:user) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "can access syntax methods from dynamic attributes" do
|
||||
FactoryGirl.build(:user).email.should == "person-1@example.com"
|
||||
FactoryGirl.attributes_for(:user)[:email].should == "person-2@example.com"
|
||||
end
|
||||
|
||||
it "can access syntax methods from dynamic attributes" do
|
||||
FactoryGirl.build(:post).user.should be_instance_of(User)
|
||||
end
|
||||
|
||||
it "can access methods already existing on the class" do
|
||||
FactoryGirl.build(:post).title.should == "generate result"
|
||||
FactoryGirl.attributes_for(:post)[:title].should be_nil
|
||||
end
|
||||
end
|
|
@ -1,8 +1,22 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe FactoryGirl::NullObject do
|
||||
its(:id) { should be_nil }
|
||||
its(:age) { should be_nil }
|
||||
its(:name) { should be_nil }
|
||||
its(:admin?) { should be_nil }
|
||||
let(:methods_to_respond_to) { %w[id age name admin?] }
|
||||
let(:methods_to_not_respond_to) { %w[email date_of_birth title] }
|
||||
|
||||
subject { FactoryGirl::NullObject.new(methods_to_respond_to) }
|
||||
|
||||
it "responds to the given methods" do
|
||||
methods_to_respond_to.each do |method_name|
|
||||
subject.__send__(method_name).should be_nil
|
||||
subject.respond_to?(method_name).should be_true
|
||||
end
|
||||
end
|
||||
|
||||
it "does not respond to other methods" do
|
||||
methods_to_not_respond_to.each do |method_name|
|
||||
expect { subject.__send__(method_name) }.to raise_error(NoMethodError)
|
||||
subject.respond_to?(method_name).should be_false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue