diff --git a/lib/shoulda/matchers.rb b/lib/shoulda/matchers.rb index 3786927a..910a7fc5 100644 --- a/lib/shoulda/matchers.rb +++ b/lib/shoulda/matchers.rb @@ -3,6 +3,7 @@ require 'shoulda/matchers/doublespeak' require 'shoulda/matchers/error' require 'shoulda/matchers/matcher_context' require 'shoulda/matchers/rails_shim' +require 'shoulda/matchers/util' require 'shoulda/matchers/version' require 'shoulda/matchers/warn' diff --git a/lib/shoulda/matchers/util.rb b/lib/shoulda/matchers/util.rb new file mode 100644 index 00000000..d14ef6cc --- /dev/null +++ b/lib/shoulda/matchers/util.rb @@ -0,0 +1,15 @@ +module Shoulda + module Matchers + # @private + module Util + def self.deconstantize(path) + if defined?(ActiveSupport::Inflector) && + ActiveSupport::Inflector.respond_to?(:deconstantize) + ActiveSupport::Inflector.deconstantize(path) + else + path.to_s[0...(path.to_s.rindex('::') || 0)] + end + end + end + end +end diff --git a/spec/support/class_builder.rb b/spec/support/class_builder.rb index 67833854..41a002e5 100644 --- a/spec/support/class_builder.rb +++ b/spec/support/class_builder.rb @@ -7,31 +7,37 @@ module ClassBuilder end end - def define_class(class_name, base = Object, &block) + def self.parse_constant_name(name) + namespace = Shoulda::Matchers::Util.deconstantize(name) + qualified_namespace = (namespace.presence || 'Object').constantize + name_without_namespace = name.to_s.demodulize + [qualified_namespace, name_without_namespace] + end + + def define_class(class_name, parent_class = Object, &block) class_name = class_name.to_s.camelize - if Object.const_defined?(class_name) - Object.__send__(:remove_const, class_name) + namespace, name_without_namespace = + ClassBuilder.parse_constant_name(class_name) + + if namespace.const_defined?(name_without_namespace, false) + namespace.__send__(:remove_const, name_without_namespace) end - # FIXME: ActionMailer 3.2 calls `name.underscore` immediately upon - # subclassing. Class.new.name == nil. So, Class.new(ActionMailer::Base) - # errors out since it's trying to do `nil.underscore`. This is very ugly but - # allows us to test against ActionMailer 3.2.x. - eval <<-A_REAL_CLASS_FOR_ACTION_MAILER_3_2 - class ::#{class_name} < #{base} - end - A_REAL_CLASS_FOR_ACTION_MAILER_3_2 + eval <<-RUBY + class #{namespace}::#{name_without_namespace} < #{parent_class} + end + RUBY - Object.const_get(class_name).tap do |constant_class| - constant_class.unloadable + namespace.const_get(name_without_namespace).tap do |constant| + constant.unloadable if block_given? - constant_class.class_eval(&block) + constant.class_eval(&block) end - if constant_class.respond_to?(:reset_column_information) - constant_class.reset_column_information + if constant.respond_to?(:reset_column_information) + constant.reset_column_information end end end diff --git a/spec/support/model_builder.rb b/spec/support/model_builder.rb index 80126fd7..1b6225a1 100644 --- a/spec/support/model_builder.rb +++ b/spec/support/model_builder.rb @@ -46,7 +46,8 @@ module ModelBuilder def define_model(name, columns = {}, &block) class_name = name.to_s.pluralize.classify - table_name = class_name.tableize + table_name = class_name.tableize.gsub('/', '_') + table_block = lambda do |table| columns.each do |name, specification| if specification.is_a?(Hash) @@ -64,7 +65,13 @@ module ModelBuilder create_table(table_name, &table_block) end - define_model_class(class_name, &block) + define_model_class(class_name).tap do |model| + if block + model.class_eval(&block) + end + + model.table_name = table_name + end end def drop_created_tables