require 'mr/factory' require 'mr/factory/config' require 'mr/factory/record_stack' require 'mr/fake_record' module MR; end module MR::Factory class RecordFactory attr_reader :record_class, :config def initialize(record_class, &block) @record_class = record_class @config = Config.new(record_class) self.instance_eval(&block) if block end def record(args = nil) @record_class.new.tap do |record| self.config.apply_args(record, args || {}) end end alias :instance :record def saved_record(args = nil) record = self.record(args).tap(&:save!) record.reset_save_called if record.kind_of?(MR::FakeRecord) record end alias :saved_instance :saved_record def stack(args = nil) MR::Factory::RecordStack.for_record(self.record(args), self.config) end alias :instance_stack :stack def stack_record(args = nil) self.stack(args).record end def saved_stack(args = nil) self.stack(args).tap(&:create) end def saved_stack_record(args = nil) self.saved_stack(args).record end def saved_dependencies_stack(args = nil) self.stack(args).tap(&:create_deps) end alias :saved_deps_stack :saved_dependencies_stack def saved_dependencies_stack_record(args = nil) self.saved_deps_stack(args).record end alias :saved_deps_stack_record :saved_dependencies_stack_record private def default_association(association_name, factory, options = nil) self.config.add_association_factory(association_name, factory, options) rescue NoAssociationError => exception raise exception.class, exception.message, caller end def default_args(&block) self.config.set_default_args(&block) end class Config include MR::Factory::WithAssociationsConfig def build_associated_record(association_name, record_class) self.factory_for(association_name, record_class).record end def ar_association_for(record, name) if (reflection = record.class.reflect_on_association(name)) record.association(reflection.name) end end private def apply_default_args(record) column_defaults.each do |column_name, column_type| record.send("#{column_name}=", MR::Factory.send(column_type)) end super(record) end def build_factory_for_record_class(record_class) MR::Factory::RecordFactory.new(record_class) end def column_defaults @column_defaults ||= begin association_column_names = association_column_names(self.record_class) self.record_class.columns.inject({}) do |args, column| column_type = column.type || column.sql_type if should_default_column?(column, association_column_names, column_type) args[column.name.to_s] = column_type end args end end end def should_default_column?(column, association_column_names, column_type) !column.primary && !association_column_names.include?(column.name) && !column_type.nil? && MR::Factory.respond_to?(column_type) end def association_column_names(record_class) names = [] record_class.reflect_on_all_associations(:belongs_to).each do |reflection| names << reflection.foreign_type if reflection.options[:polymorphic] names << reflection.foreign_key end names end end end end