diff options
Diffstat (limited to 'activemodel')
22 files changed, 353 insertions, 113 deletions
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb index 803f5b0157..544121c593 100644 --- a/activemodel/lib/active_model.rb +++ b/activemodel/lib/active_model.rb @@ -21,21 +21,27 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -activesupport_path = "#{File.dirname(__FILE__)}/../../../activesupport/lib" +activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" $:.unshift(activesupport_path) if File.directory?(activesupport_path) require 'active_support' -require 'active_support/inflector' - module ActiveModel + autoload :Attributes, 'active_model/attributes' autoload :Base, 'active_model/base' - autoload :Observing, 'active_model/observing' - autoload :Validations, 'active_model/validations' - autoload :Errors, 'active_model/errors' autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods' - autoload :TestCase, 'active_model/test_case' + autoload :Errors, 'active_model/errors' + autoload :Name, 'active_model/naming' + autoload :Naming, 'active_model/naming' + autoload :Observer, 'active_model/observing' + autoload :Observing, 'active_model/observing' autoload :StateMachine, 'active_model/state_machine' + autoload :TestCase, 'active_model/test_case' + autoload :Validations, 'active_model/validations' autoload :ValidationsRepairHelper, 'active_model/validations_repair_helper' + + module Serializers + autoload :JSON, 'active_model/serializers/json' + end end I18n.load_path << File.dirname(__FILE__) + '/active_model/locale/en.yml' diff --git a/activemodel/lib/active_model/attributes.rb b/activemodel/lib/active_model/attributes.rb new file mode 100644 index 0000000000..4665525281 --- /dev/null +++ b/activemodel/lib/active_model/attributes.rb @@ -0,0 +1,17 @@ +require 'active_support/core_ext/object/instance_variables' + +module ActiveModel + module Attributes + def attributes + instance_values + end + + def read_attribute(attr_name) + instance_variable_get(:"@#{attr_name}") + end + + def write_attribute(attr_name, value) + instance_variable_set(:"@#{attr_name}", value) + end + end +end diff --git a/activemodel/lib/active_model/deprecated_error_methods.rb b/activemodel/lib/active_model/deprecated_error_methods.rb index 433de8931a..dd8050c549 100644 --- a/activemodel/lib/active_model/deprecated_error_methods.rb +++ b/activemodel/lib/active_model/deprecated_error_methods.rb @@ -19,7 +19,7 @@ module ActiveModel ActiveSupport::Deprecation.warn "Errors#add_to_base(msg) has been deprecated, use Errors#[:base] << msg instead" self[:base] << msg end - + def invalid?(attribute) ActiveSupport::Deprecation.warn "Errors#invalid?(attribute) has been deprecated, use Errors#[attribute].any? instead" self[attribute].any? @@ -30,4 +30,4 @@ module ActiveModel to_a.each { |error| yield error } end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 4be91d0505..a4cf700231 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/string/inflections' + module ActiveModel class Errors < Hash include DeprecatedErrorMethods @@ -23,7 +25,7 @@ module ActiveModel end def each - each_key do |attribute| + each_key do |attribute| self[attribute].each { |error| yield attribute, error } end end @@ -66,7 +68,7 @@ module ActiveModel # Will add an error message to each of the attributes in +attributes+ that is empty. def add_on_empty(attributes, custom_message = nil) [attributes].flatten.each do |attribute| - value = @base.get_attribute_value(attribute) + value = @base.send(attribute) is_empty = value.respond_to?(:empty?) ? value.empty? : false add(attribute, :empty, :default => custom_message) unless !value.nil? && !is_empty end @@ -75,7 +77,7 @@ module ActiveModel # Will add an error message to each of the attributes in +attributes+ that is blank (using Object#blank?). def add_on_blank(attributes, custom_message = nil) [attributes].flatten.each do |attribute| - value = @base.get_attribute_value(attribute) + value = @base.send(attribute) add(attribute, :blank, :default => custom_message) if value.blank? end end @@ -94,6 +96,7 @@ module ActiveModel full_messages = [] each do |attribute, messages| + messages = Array.wrap(messages) next if messages.empty? if attribute == :base @@ -111,15 +114,15 @@ module ActiveModel end # Translates an error message in it's default scope (<tt>activemodel.errrors.messages</tt>). - # Error messages are first looked up in <tt>models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>, if it's not there, - # it's looked up in <tt>models.MODEL.MESSAGE</tt> and if that is not there it returns the translation of the - # default message (e.g. <tt>activemodel.errors.messages.MESSAGE</tt>). The translated model name, + # Error messages are first looked up in <tt>models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>, if it's not there, + # it's looked up in <tt>models.MODEL.MESSAGE</tt> and if that is not there it returns the translation of the + # default message (e.g. <tt>activemodel.errors.messages.MESSAGE</tt>). The translated model name, # translated attribute name and the value are available for interpolation. # # When using inheritence in your models, it will check all the inherited models too, but only if the model itself # hasn't been found. Say you have <tt>class Admin < User; end</tt> and you wanted the translation for the <tt>:blank</tt> # error +message+ for the <tt>title</tt> +attribute+, it looks for these translations: - # + # # <ol> # <li><tt>activemodel.errors.models.admin.attributes.title.blank</tt></li> # <li><tt>activemodel.errors.models.admin.blank</tt></li> @@ -135,7 +138,7 @@ module ActiveModel klass_ancestors += @base.class.ancestors.reject {|x| x.is_a?(Module)} defaults = klass_ancestors.map do |klass| - [ :"models.#{klass.name.underscore}.attributes.#{attribute}.#{message}", + [ :"models.#{klass.name.underscore}.attributes.#{attribute}.#{message}", :"models.#{klass.name.underscore}.#{message}" ] end @@ -143,7 +146,7 @@ module ActiveModel defaults = defaults.compact.flatten << :"messages.#{message}" key = defaults.shift - value = @base.get_attribute_value(attribute) + value = @base.send(attribute) options = { :default => defaults, :model => @base.class.name.humanize, @@ -155,4 +158,4 @@ module ActiveModel I18n.translate(key, options) end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb new file mode 100644 index 0000000000..ffb44e3824 --- /dev/null +++ b/activemodel/lib/active_model/naming.rb @@ -0,0 +1,25 @@ +require 'active_support/inflector' + +module ActiveModel + class Name < String + attr_reader :singular, :plural, :element, :collection, :partial_path + alias_method :cache_key, :collection + + def initialize(name) + super + @singular = ActiveSupport::Inflector.underscore(self).tr('/', '_').freeze + @plural = ActiveSupport::Inflector.pluralize(@singular).freeze + @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze + @collection = ActiveSupport::Inflector.tableize(self).freeze + @partial_path = "#{@collection}/#{@element}".freeze + end + end + + module Naming + # Returns an ActiveModel::Name object for module. It can be + # used to retrieve all kinds of naming-related information. + def model_name + @_model_name ||= ActiveModel::Name.new(name) + end + end +end diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index d3c6d8e482..7bad2397ae 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -1,69 +1,90 @@ require 'observer' require 'singleton' +require 'active_support/core_ext/string/inflections' +require 'active_support/core_ext/array/wrap' module ActiveModel module Observing + extend ActiveSupport::Concern + + included do + extend Observable + end + module ClassMethods - def observers - @observers ||= [] - end - + # Activates the observers assigned. Examples: + # + # # Calls PersonObserver.instance + # ActiveRecord::Base.observers = :person_observer + # + # # Calls Cacher.instance and GarbageCollector.instance + # ActiveRecord::Base.observers = :cacher, :garbage_collector + # + # # Same as above, just using explicit class references + # ActiveRecord::Base.observers = Cacher, GarbageCollector + # + # Note: Setting this does not instantiate the observers yet. +instantiate_observers+ is + # called during startup, and before each development request. def observers=(*values) @observers = values.flatten end - + + # Gets the current observers. + def observers + @observers ||= [] + end + + # Instantiate the global Active Record observers. def instantiate_observers observers.each { |o| instantiate_observer(o) } end - - protected - def instantiate_observer(observer) - # string/symbol - if observer.respond_to?(:to_sym) - observer = observer.to_s.camelize.constantize.instance - elsif observer.respond_to?(:instance) - observer.instance - else - raise ArgumentError, "#{observer} must be a lowercase, underscored class name (or an instance of the class itself) responding to the instance method. Example: Person.observers = :big_brother # calls BigBrother.instance" + + protected + def instantiate_observer(observer) + # string/symbol + if observer.respond_to?(:to_sym) + observer = observer.to_s.camelize.constantize.instance + elsif observer.respond_to?(:instance) + observer.instance + else + raise ArgumentError, "#{observer} must be a lowercase, underscored class name (or an instance of the class itself) responding to the instance method. Example: Person.observers = :big_brother # calls BigBrother.instance" + end + end + + # Notify observers when the observed class is subclassed. + def inherited(subclass) + super + changed + notify_observers :observed_class_inherited, subclass end - end - - # Notify observers when the observed class is subclassed. - def inherited(subclass) - super - changed - notify_observers :observed_class_inherited, subclass - end - end - - def self.included(receiver) - receiver.extend Observable, ClassMethods end + + private + def notify(method) #:nodoc: + self.class.changed + self.class.notify_observers(method, self) + end end class Observer include Singleton - attr_writer :observed_classes class << self - attr_accessor :models # Attaches the observer to the supplied model classes. def observe(*models) - @models = models.flatten - @models.collect! { |model| model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model } + models.flatten! + models.collect! { |model| model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model } + define_method(:observed_classes) { models } end - def observed_class_name - @observed_class_name ||= - if guessed_name = name.scan(/(.*)Observer/)[0] - @observed_class_name = guessed_name[0] - end + def observed_classes + Array.wrap(observed_class) end # The class observed by default is inferred from the observer's class name: - # assert_equal [Person], PersonObserver.observed_class + # assert_equal Person, PersonObserver.observed_class def observed_class - if observed_class_name + if observed_class_name = name[/(.*)Observer/, 1] observed_class_name.constantize else nil @@ -73,8 +94,11 @@ module ActiveModel # Start observing the declared classes and their subclasses. def initialize - self.observed_classes = self.class.models if self.class.models - observed_classes.each { |klass| klass.add_observer(self) } + observed_classes.each { |klass| add_observer!(klass) } + end + + def observed_classes + self.class.observed_classes end # Send observed_method(object) if the method exists. @@ -86,12 +110,12 @@ module ActiveModel # Passes the new subclass. def observed_class_inherited(subclass) #:nodoc: self.class.observe(observed_classes + [subclass]) - subclass.add_observer(self) + add_observer!(subclass) end - protected - def observed_classes - @observed_classes ||= [self.class.observed_class] - end + protected + def add_observer!(klass) + klass.add_observer(self) + end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb new file mode 100644 index 0000000000..60b5cbe948 --- /dev/null +++ b/activemodel/lib/active_model/serializers/json.rb @@ -0,0 +1,38 @@ +require 'active_support/json' +require 'active_support/core_ext/class/attribute_accessors' +require 'active_support/core_ext/hash/except' +require 'active_support/core_ext/hash/slice' + +module ActiveModel + module Serializers + module JSON + extend ActiveSupport::Concern + include ActiveModel::Attributes + + included do + cattr_accessor :include_root_in_json, :instance_writer => false + end + + def encode_json(encoder) + options = encoder.options || {} + + hash = if options[:only] + only = Array.wrap(options[:only]).map { |attr| attr.to_s } + attributes.slice(*only) + elsif options[:except] + except = Array.wrap(options[:except]).map { |attr| attr.to_s } + attributes.except(*except) + else + attributes + end + + hash = { self.class.model_name.element => hash } if include_root_in_json + ActiveSupport::JSON.encode(hash) + end + + def as_json(options = nil) + self + end + end + end +end diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 336c2757fc..5223cea135 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -1,3 +1,6 @@ +require 'active_support/core_ext/array/extract_options' +require 'active_support/core_ext/hash/keys' + module ActiveModel module Validations extend ActiveSupport::Concern @@ -61,7 +64,7 @@ module ActiveModel # Declare the validation. send(validation_method(options[:on]), options) do |record| attrs.each do |attr| - value = record.get_attribute_value(attr) + value = record.send(attr) next if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank]) yield record, attr, value end @@ -69,10 +72,9 @@ module ActiveModel end private - - def validation_method(on) - :validate - end + def validation_method(on) + :validate + end end # Returns the Errors object that holds all information about attribute error messages. @@ -91,10 +93,6 @@ module ActiveModel def invalid? !valid? end - - def get_attribute_value(attribute) - respond_to?(attribute.to_sym) ? send(attribute.to_sym) : instance_variable_get(:"@#{attribute}") - end end end diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb index 0c9ef51726..b65c9b933d 100644 --- a/activemodel/lib/active_model/validations/acceptance.rb +++ b/activemodel/lib/active_model/validations/acceptance.rb @@ -39,10 +39,10 @@ module ActiveModel validates_each(attr_names,configuration) do |record, attr_name, value| unless value == configuration[:accept] - record.errors.add(attr_name, :accepted, :default => configuration[:message]) + record.errors.add(attr_name, :accepted, :default => configuration[:message]) end end end end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index b9823172f7..d414224dd2 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -36,10 +36,10 @@ module ActiveModel validates_each(attr_names, configuration) do |record, attr_name, value| unless record.send("#{attr_name}_confirmation").nil? or value == record.send("#{attr_name}_confirmation") - record.errors.add(attr_name, :confirmation, :default => configuration[:message]) + record.errors.add(attr_name, :confirmation, :default => configuration[:message]) end end end end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb index 0aa9848ee1..2cfdec97a5 100644 --- a/activemodel/lib/active_model/validations/exclusion.rb +++ b/activemodel/lib/active_model/validations/exclusion.rb @@ -29,10 +29,10 @@ module ActiveModel validates_each(attr_names, configuration) do |record, attr_name, value| if enum.include?(value) - record.errors.add(attr_name, :exclusion, :default => configuration[:message], :value => value) + record.errors.add(attr_name, :exclusion, :default => configuration[:message], :value => value) end end end end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb index 8efce8ba2b..6f3b668bf0 100644 --- a/activemodel/lib/active_model/validations/format.rb +++ b/activemodel/lib/active_model/validations/format.rb @@ -32,10 +32,10 @@ module ActiveModel validates_each(attr_names, configuration) do |record, attr_name, value| unless value.to_s =~ configuration[:with] - record.errors.add(attr_name, :invalid, :default => configuration[:message], :value => value) + record.errors.add(attr_name, :invalid, :default => configuration[:message], :value => value) end end end end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index a4bc8fe035..0d7dc5cd64 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -29,10 +29,10 @@ module ActiveModel validates_each(attr_names, configuration) do |record, attr_name, value| unless enum.include?(value) - record.errors.add(attr_name, :inclusion, :default => configuration[:message], :value => value) + record.errors.add(attr_name, :inclusion, :default => configuration[:message], :value => value) end end end end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb index bb9a269a02..db0439d447 100644 --- a/activemodel/lib/active_model/validations/length.rb +++ b/activemodel/lib/active_model/validations/length.rb @@ -81,7 +81,7 @@ module ActiveModel validates_each(attrs, options) do |record, attr, value| value = options[:tokenizer].call(value) if value.kind_of?(String) unless !value.nil? and value.size.method(validity_checks[option])[option_value] - record.errors.add(attr, key, :default => custom_message, :count => option_value) + record.errors.add(attr, key, :default => custom_message, :count => option_value) end end end @@ -90,4 +90,4 @@ module ActiveModel alias_method :validates_size_of, :validates_length_of end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 79fca2f1ea..ada6e28594 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -71,7 +71,7 @@ module ActiveModel case option when :odd, :even unless raw_value.to_i.method(ALL_NUMERICALITY_CHECKS[option])[] - record.errors.add(attr_name, option, :value => raw_value, :default => configuration[:message]) + record.errors.add(attr_name, option, :value => raw_value, :default => configuration[:message]) end else unless raw_value.method(ALL_NUMERICALITY_CHECKS[option])[configuration[option]] @@ -83,4 +83,4 @@ module ActiveModel end end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index 518bc8a952..72d6b1c6f0 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveModel module Validations module ClassMethods @@ -16,7 +18,7 @@ module ActiveModel # # Configuration options: # * <tt>message</tt> - A custom error message (default is: "can't be blank"). - # * <tt>on</tt> - Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, + # * <tt>on</tt> - Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, # <tt>:update</tt>). # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should # occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). @@ -36,4 +38,4 @@ module ActiveModel end end end -end
\ No newline at end of file +end diff --git a/activemodel/test/cases/attributes_test.rb b/activemodel/test/cases/attributes_test.rb new file mode 100644 index 0000000000..5f3ea839a4 --- /dev/null +++ b/activemodel/test/cases/attributes_test.rb @@ -0,0 +1,30 @@ +require 'cases/helper' + +class AttributesTest < ActiveModel::TestCase + class Person + include ActiveModel::Attributes + attr_accessor :name + end + + test "reads attribute" do + p = Person.new + assert_equal nil, p.read_attribute(:name) + + p.name = "Josh" + assert_equal "Josh", p.read_attribute(:name) + end + + test "writes attribute" do + p = Person.new + assert_equal nil, p.name + + p.write_attribute(:name, "Josh") + assert_equal "Josh", p.name + end + + test "returns all attributes" do + p = Person.new + p.name = "Josh" + assert_equal({"name" => "Josh"}, p.attributes) + end +end diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb index f023109a60..3c0bd15236 100644 --- a/activemodel/test/cases/helper.rb +++ b/activemodel/test/cases/helper.rb @@ -10,8 +10,6 @@ ActiveSupport::Deprecation.debug = true require 'rubygems' require 'test/unit' -gem 'mocha', '>= 0.9.5' -require 'mocha' begin require 'ruby-debug' diff --git a/activemodel/test/cases/json_serialization_test.rb b/activemodel/test/cases/json_serialization_test.rb new file mode 100644 index 0000000000..abcec67a85 --- /dev/null +++ b/activemodel/test/cases/json_serialization_test.rb @@ -0,0 +1,64 @@ +require 'cases/helper' + +class JsonSerializationTest < ActiveModel::TestCase + class Contact + extend ActiveModel::Naming + include ActiveModel::Serializers::JSON + attr_accessor :name, :age, :created_at, :awesome, :preferences + end + + def setup + @contact = Contact.new + @contact.name = 'Konata Izumi' + @contact.age = 16 + @contact.created_at = Time.utc(2006, 8, 1) + @contact.awesome = true + @contact.preferences = { 'shows' => 'anime' } + end + + test "should include root in json" do + begin + Contact.include_root_in_json = true + json = @contact.to_json + + assert_match %r{^\{"contact":\{}, json + assert_match %r{"name":"Konata Izumi"}, json + assert_match %r{"age":16}, json + assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))})) + assert_match %r{"awesome":true}, json + assert_match %r{"preferences":\{"shows":"anime"\}}, json + ensure + Contact.include_root_in_json = false + end + end + + test "should encode all encodable attributes" do + json = @contact.to_json + + assert_match %r{"name":"Konata Izumi"}, json + assert_match %r{"age":16}, json + assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))})) + assert_match %r{"awesome":true}, json + assert_match %r{"preferences":\{"shows":"anime"\}}, json + end + + test "should allow attribute filtering with only" do + json = @contact.to_json(:only => [:name, :age]) + + assert_match %r{"name":"Konata Izumi"}, json + assert_match %r{"age":16}, json + assert_no_match %r{"awesome":true}, json + assert !json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))})) + assert_no_match %r{"preferences":\{"shows":"anime"\}}, json + end + + test "should allow attribute filtering with except" do + json = @contact.to_json(:except => [:name, :age]) + + assert_no_match %r{"name":"Konata Izumi"}, json + assert_no_match %r{"age":16}, json + assert_match %r{"awesome":true}, json + assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))})) + assert_match %r{"preferences":\{"shows":"anime"\}}, json + end +end diff --git a/activemodel/test/cases/naming_test.rb b/activemodel/test/cases/naming_test.rb new file mode 100644 index 0000000000..e75d4541a3 --- /dev/null +++ b/activemodel/test/cases/naming_test.rb @@ -0,0 +1,27 @@ +require 'cases/helper' + +class NamingTest < Test::Unit::TestCase + def setup + @model_name = ActiveModel::Name.new('Post::TrackBack') + end + + def test_singular + assert_equal 'post_track_back', @model_name.singular + end + + def test_plural + assert_equal 'post_track_backs', @model_name.plural + end + + def test_element + assert_equal 'track_back', @model_name.element + end + + def test_collection + assert_equal 'post/track_backs', @model_name.collection + end + + def test_partial_path + assert_equal 'post/track_backs/track_back', @model_name.partial_path + end +end diff --git a/activemodel/test/cases/observing_test.rb b/activemodel/test/cases/observing_test.rb index 421ac4b4f8..564451fa2f 100644 --- a/activemodel/test/cases/observing_test.rb +++ b/activemodel/test/cases/observing_test.rb @@ -9,7 +9,7 @@ class FooObserver < ActiveModel::Observer class << self public :new end - + attr_accessor :stub def on_spec(record) @@ -28,12 +28,12 @@ class ObservingTest < ActiveModel::TestCase test "initializes model with no cached observers" do assert ObservedModel.observers.empty?, "Not empty: #{ObservedModel.observers.inspect}" end - + test "stores cached observers in an array" do ObservedModel.observers << :foo assert ObservedModel.observers.include?(:foo), ":foo not in #{ObservedModel.observers.inspect}" end - + test "flattens array of assigned cached observers" do ObservedModel.observers = [[:foo], :bar] assert ObservedModel.observers.include?(:foo), ":foo not in #{ObservedModel.observers.inspect}" @@ -57,22 +57,30 @@ class ObservingTest < ActiveModel::TestCase ObservedModel::Observer.expects(:instance) ObservedModel.instantiate_observers end - + test "passes observers to subclasses" do FooObserver.instance bar = Class.new(Foo) assert_equal Foo.count_observers, bar.count_observers end end - + class ObserverTest < ActiveModel::TestCase def setup ObservedModel.observers = :foo_observer - FooObserver.models = nil + FooObserver.instance_eval do + alias_method :original_observed_classes, :observed_classes + end + end + + def teardown + FooObserver.instance_eval do + alias_method :observed_classes, :original_observed_classes + end end test "guesses implicit observable model name" do - assert_equal 'Foo', FooObserver.observed_class_name + assert_equal Foo, FooObserver.observed_class end test "tracks implicit observable models" do @@ -80,7 +88,7 @@ class ObserverTest < ActiveModel::TestCase assert instance.send(:observed_classes).include?(Foo), "Foo not in #{instance.send(:observed_classes).inspect}" assert !instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{instance.send(:observed_classes).inspect}" end - + test "tracks explicit observed model class" do old_instance = FooObserver.new assert !old_instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{old_instance.send(:observed_classes).inspect}" @@ -88,7 +96,7 @@ class ObserverTest < ActiveModel::TestCase instance = FooObserver.new assert instance.send(:observed_classes).include?(ObservedModel), "ObservedModel not in #{instance.send(:observed_classes).inspect}" end - + test "tracks explicit observed model as string" do old_instance = FooObserver.new assert !old_instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{old_instance.send(:observed_classes).inspect}" @@ -96,7 +104,7 @@ class ObserverTest < ActiveModel::TestCase instance = FooObserver.new assert instance.send(:observed_classes).include?(ObservedModel), "ObservedModel not in #{instance.send(:observed_classes).inspect}" end - + test "tracks explicit observed model as symbol" do old_instance = FooObserver.new assert !old_instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{old_instance.send(:observed_classes).inspect}" @@ -104,7 +112,7 @@ class ObserverTest < ActiveModel::TestCase instance = FooObserver.new assert instance.send(:observed_classes).include?(ObservedModel), "ObservedModel not in #{instance.send(:observed_classes).inspect}" end - + test "calls existing observer event" do foo = Foo.new FooObserver.instance.stub = stub @@ -112,7 +120,7 @@ class ObserverTest < ActiveModel::TestCase Foo.send(:changed) Foo.send(:notify_observers, :on_spec, foo) end - + test "skips nonexistent observer event" do foo = Foo.new Foo.send(:changed) diff --git a/activemodel/test/cases/validations/presence_validation_test.rb b/activemodel/test/cases/validations/presence_validation_test.rb index f6bed4903a..aa5bdf1e62 100644 --- a/activemodel/test/cases/validations/presence_validation_test.rb +++ b/activemodel/test/cases/validations/presence_validation_test.rb @@ -31,15 +31,15 @@ class PresenceValidationTest < ActiveModel::TestCase assert t.save end - def test_validates_presence_of_with_custom_message_using_quotes - repair_validations(Developer) do - Developer.validates_presence_of :non_existent, :message=> "This string contains 'single' and \"double\" quotes" - d = Developer.new - d.name = "Joe" - assert !d.valid? - assert_equal ["This string contains 'single' and \"double\" quotes"], d.errors[:non_existent] - end - end + # def test_validates_presence_of_with_custom_message_using_quotes + # repair_validations(Developer) do + # Developer.validates_presence_of :non_existent, :message=> "This string contains 'single' and \"double\" quotes" + # d = Developer.new + # d.name = "Joe" + # assert !d.valid? + # assert_equal ["This string contains 'single' and \"double\" quotes"], d.errors[:non_existent] + # end + # end def test_validates_presence_of_for_ruby_class repair_validations(Person) do |