Created
April 16, 2011 02:38
-
-
Save jemmyw/922804 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
World(FactoryGirlStepHelpers) | |
module DataStepHelpers | |
def str_to_name(str) | |
str.to_s.strip.gsub(/\s+/m, '_').underscore | |
end | |
def get_instance(name) | |
instance_variable_get('@%s' % str_to_name(name).singularize) | |
end | |
def db_token(str) | |
eval("\"#{str.gsub(/"/m, '\"')}\"") | |
end | |
# Find the association on an active record object | |
def find_association_by_name(instance, name) | |
name = str_to_name(name) | |
instance.class.reflect_on_association(name.to_s.singularize.to_sym) || | |
instance.class.reflect_on_association(name.to_s.pluralize.to_sym) | |
end | |
# Find the first association that accepts the given object on an active record object | |
# A macro can be passed specifying the type of association (:belongs_to, :has_many, :has_one) | |
def find_association_for(instance, object, macro=nil) | |
instance.class.reflect_on_all_associations(macro).detect do |association| | |
if association.options[:polymorphic] | |
unless association.collection? | |
association.active_record == object | |
end | |
else | |
object.is_a?(association.klass) | |
end | |
end | |
end | |
# Given an instance, object and association on the instance, finds the inverse | |
# association on the object for the instance. | |
def find_inverse_association(instance, object, association) | |
if association.collection? | |
find_association_for(object, instance, :belongs_to) | |
else | |
find_association_for(object, instance, :has_many) | |
end | |
end | |
# Assign one object to another. This involves searching the first | |
# objects methods for assignment or collection associated with the | |
# second object. If invert is true then this will run the same | |
# method inverted. | |
def assign_object_without_association(instance, object, invert = true) | |
member_object_method_name = object.class.name.underscore + '=' | |
collection_object_method_name = object.class.name.pluralize.underscore | |
if invert | |
assign_object_without_association(object, instance, false) rescue nil | |
end | |
if instance.respond_to?(member_object_method_name) | |
instance.send(member_object_method_name, object) | |
elsif instance.respond_to?(collection_object_method_name) | |
instance.send(collection_object_method_name) << object | |
else | |
fail "Could not associate #{object.class.name} with #{instance.class.name}" | |
end | |
instance.save! | |
instance.reload | |
end | |
# Assign an object to an association | |
def assign_to_association(instance, object, association) | |
if association.collection? | |
proxy = instance.send(association.name) | |
proxy << object | |
else | |
instance.send('%s=' % association.name, object) | |
end | |
end | |
# Assign an object to an instanc eusing an association | |
def assign_object_with_association(instance, object, association, invert = true) | |
inverse_association = association.inverse_of || find_inverse_association(instance, object, association) | |
assign_to_association(instance, object, association) | |
if invert && inverse_association | |
assign_to_association(object, instance, inverse_association) | |
object.save! | |
end | |
instance.save! | |
instance.reload | |
object.reload | |
end | |
# Assign an object to an instance. Can specify an association name or object to use. Can | |
# specify invert to assign the instance to the object as well. | |
def assign_object_to_instance(instance, object, association_name_or_object = nil, invert = true) | |
association = association_name_or_object | |
if association.nil? | |
association = find_association_for(instance, object) | |
elsif association.is_a?(String) || association.is_a?(Symbol) | |
association = find_association_by_name(instance, association) | |
end | |
if association.nil? | |
assign_object_without_association(instance, object, invert) | |
else | |
assign_object_with_association(instance, object, association, invert) | |
end | |
end | |
end | |
World(DataStepHelpers) | |
Given /^there is an? ([^:]+)$/ do |factory_name| | |
factory_name = str_to_name(factory_name) | |
factory = Factory.factories[factory_name.to_sym] | |
object = Factory(factory.factory_name) | |
instance_variable_set('@%s' % factory_name.singularize, object) | |
end | |
Given /^there is an? (.+):$/ do |factory_name, table| | |
factory_name = str_to_name(factory_name) | |
factory = Factory.factories[factory_name.to_sym] | |
rows = [table.headers] + table.rows | |
attributes = convert_human_hash_to_attribute_hash(Hash[*rows.flatten], factory.associations) | |
object = Factory(factory.factory_name, attributes) | |
instance_variable_set('@%s' % factory_name.singularize, object) | |
end | |
Given /^the (.+) has an? ([^:]+)$/ do |instance, association_name| | |
instance = get_instance(instance) | |
association = find_association_by_name(instance, association_name) | |
# If we can't find the association, find the factory and work it out from there | |
if association.nil? | |
factory = Factory.factories[str_to_name(association_name).to_sym] | |
association_name = nil | |
else | |
factory = Factory.factories[association.class_name.underscore.to_sym] | |
end | |
object = Factory.build(factory.factory_name) | |
assign_object_to_instance(instance, object, association_name) rescue nil # don't worry if we couldn't assign | |
instance_variable_set('@%s' % factory.factory_name.to_s.singularize, object) | |
end | |
Given /^the (.+) has an? (.+):$/ do |instance, association_name, table| | |
instance = get_instance(instance) | |
association = find_association_by_name(instance, association_name) | |
# If we can't find the association, find the factory and work it out from there | |
if association.nil? | |
factory = Factory.factories[str_to_name(association_name).to_sym] | |
association_name = nil | |
else | |
factory = Factory.factories[association.class_name.underscore.to_sym] | |
end | |
rows = [table.headers] + table.rows | |
attributes = convert_human_hash_to_attribute_hash(Hash[*rows.flatten], factory.associations) | |
object = Factory.build(factory.factory_name, attributes) | |
assign_object_to_instance(instance, object, association_name) | |
instance_variable_set('@%s' % factory.factory_name.to_s.singularize, object) | |
end | |
Given /^the (.+) is associated with the (.+?)(?: by (.+))?$/ do |child, instance, association_name| | |
instance = get_instance(instance) | |
child = get_instance(child) | |
assign_object_to_instance(instance, child, association_name) | |
end | |
Given /^the (.+) has (.+) set to "([^"]*)"$/ do |instance, field, value| | |
instance = get_instance(instance) | |
value = case value | |
when 'nil' | |
nil | |
when /^\d+$/ | |
value.to_d | |
when /^#\{/ | |
db_token(value) | |
else | |
value | |
end | |
instance.send('%s=' % field, value) | |
instance.save! | |
instance.reload | |
end | |
Then /^the (.+) should have (.+) set to "([^"]*)"$/ do |instance, field, value| | |
get_instance(instance).reload.send(field).to_s.should == value | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment