diff options
author | Pratik Naik <pratiknaik@gmail.com> | 2010-03-12 16:00:01 +0000 |
---|---|---|
committer | Pratik Naik <pratiknaik@gmail.com> | 2010-03-12 16:00:01 +0000 |
commit | e68bfaf1fe1a7890a67af6f444281185f507cf9e (patch) | |
tree | 5e73caccdcdd65d0ac97f9eb92195928f30925f2 /activemodel/lib/active_model | |
parent | ef6462c73003b28c8e060a06120abb9cd67b6d52 (diff) | |
parent | 16846553b8866eab2aa3b128a2a23a221a25f7e3 (diff) | |
download | rails-e68bfaf1fe1a7890a67af6f444281185f507cf9e.tar.gz rails-e68bfaf1fe1a7890a67af6f444281185f507cf9e.tar.bz2 rails-e68bfaf1fe1a7890a67af6f444281185f507cf9e.zip |
Merge remote branch 'mainstream/master'
Conflicts:
activerecord/lib/active_record/base.rb
railties/lib/rails/configuration.rb
railties/lib/rails/log_subscriber.rb
Diffstat (limited to 'activemodel/lib/active_model')
-rw-r--r-- | activemodel/lib/active_model/attribute_methods.rb | 11 | ||||
-rw-r--r-- | activemodel/lib/active_model/conversion.rb | 45 | ||||
-rw-r--r-- | activemodel/lib/active_model/lint.rb | 40 | ||||
-rw-r--r-- | activemodel/lib/active_model/naming.rb | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/validations.rb | 23 | ||||
-rw-r--r-- | activemodel/lib/active_model/validations/with.rb | 9 | ||||
-rw-r--r-- | activemodel/lib/active_model/validator.rb | 18 | ||||
-rw-r--r-- | activemodel/lib/active_model/version.rb | 5 |
8 files changed, 123 insertions, 30 deletions
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index f7fb66bdfc..c1334069fa 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -21,7 +21,6 @@ module ActiveModel # A minimal implementation could be: # # class Person - # # include ActiveModel::AttributeMethods # # attribute_method_affix :prefix => 'reset_', :suffix => '_to_default!' @@ -44,9 +43,13 @@ module ActiveModel # def reset_attribute_to_default!(attr) # send("#{attr}=", "Default Name") # end - # # end - # + # + # Please notice that whenever you include ActiveModel::AtributeMethods in your class, + # it requires you to implement a <tt>attributes</tt> methods which returns a hash with + # each attribute name in your model as hash key and the attribute value as hash value. + # Hash keys must be a string. + # module AttributeMethods extend ActiveSupport::Concern @@ -85,7 +88,7 @@ module ActiveModel # AttributePerson.inheritance_column # # => 'address_id' def define_attr_method(name, value=nil, &block) - sing = metaclass + sing = singleton_class sing.send :alias_method, "original_#{name}", name if block_given? sing.send :define_method, name, &block diff --git a/activemodel/lib/active_model/conversion.rb b/activemodel/lib/active_model/conversion.rb index c14a07c7dc..585c20dcdf 100644 --- a/activemodel/lib/active_model/conversion.rb +++ b/activemodel/lib/active_model/conversion.rb @@ -1,19 +1,44 @@ module ActiveModel - # If your object is already designed to implement all of the Active Model featurs - # include this module in your Class. - # - # class MyClass + # Handle default conversions: to_model, to_key and to_param. + # + # == Example + # + # Let's take for example this non persisted object. + # + # class ContactMessage # include ActiveModel::Conversion + # + # # ContactMessage are never persisted in the DB + # def persisted? + # false + # end # end - # - # Returns self to the <tt>:to_model</tt> method. - # - # If your model does not act like an Active Model object, then you should define - # <tt>:to_model</tt> yourself returning a proxy object that wraps your object - # with Active Model compliant methods. + # + # cm = ContactMessage.new + # cm.to_model == self #=> true + # cm.to_key #=> nil + # cm.to_param #=> nil + # module Conversion + # If your object is already designed to implement all of the Active Model you can use + # the default to_model implementation, which simply returns self. + # + # If your model does not act like an Active Model object, then you should define + # <tt>:to_model</tt> yourself returning a proxy object that wraps your object + # with Active Model compliant methods. def to_model self end + + # Returns an Enumerable of all (primary) key attributes or nil if persisted? is fakse + def to_key + persisted? ? [id] : nil + end + + # Returns a string representing the object's key suitable for use in URLs, + # or nil if persisted? is false + def to_param + to_key ? to_key.join('-') : nil + end end end diff --git a/activemodel/lib/active_model/lint.rb b/activemodel/lib/active_model/lint.rb index 7bf0ad712d..13ddb622d1 100644 --- a/activemodel/lib/active_model/lint.rb +++ b/activemodel/lib/active_model/lint.rb @@ -13,6 +13,33 @@ module ActiveModel module Lint module Tests + + # == Responds to <tt>to_key</tt> + # + # Returns an Enumerable of all (primary) key attributes + # or nil if model.persisted? is false + def test_to_key + assert model.respond_to?(:to_key), "The model should respond to to_key" + def model.persisted?() false end + assert model.to_key.nil? + end + + # == Responds to <tt>to_param</tt> + # + # Returns a string representing the object's key suitable for use in URLs + # or nil if model.persisted? is false. + # + # Implementers can decide to either raise an exception or provide a default + # in case the record uses a composite primary key. There are no tests for this + # behavior in lint because it doesn't make sense to force any of the possible + # implementation strategies on the implementer. However, if the resource is + # not persisted?, then to_param should always return nil. + def test_to_param + assert model.respond_to?(:to_param), "The model should respond to to_param" + def model.persisted?() false end + assert model.to_param.nil? + end + # == Responds to <tt>valid?</tt> # # Returns a boolean that specifies whether the object is in a valid or invalid @@ -22,21 +49,16 @@ module ActiveModel assert_boolean model.valid?, "valid?" end - # == Responds to <tt>new_record?</tt> + # == Responds to <tt>persisted?</tt> # # Returns a boolean that specifies whether the object has been persisted yet. # This is used when calculating the URL for an object. If the object is # not persisted, a form for that object, for instance, will be POSTed to the # collection. If it is persisted, a form for the object will put PUTed to the # URL for the object. - def test_new_record? - assert model.respond_to?(:new_record?), "The model should respond to new_record?" - assert_boolean model.new_record?, "new_record?" - end - - def test_destroyed? - assert model.respond_to?(:destroyed?), "The model should respond to destroyed?" - assert_boolean model.destroyed?, "destroyed?" + def test_persisted? + assert model.respond_to?(:persisted?), "The model should respond to persisted?" + assert_boolean model.persisted?, "persisted?" end # == Naming diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index b9fb5fe0c8..8cdd3d2fe8 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -42,7 +42,7 @@ module ActiveModel # To implement, just extend ActiveModel::Naming in your object: # # class BookCover - # exten ActiveModel::Naming + # extend ActiveModel::Naming # end # # BookCover.model_name #=> "BookCover" diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 03733a9c89..ba8648f8c9 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/array/extract_options' +require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/hash/keys' require 'active_model/errors' @@ -45,6 +46,9 @@ module ActiveModel included do extend ActiveModel::Translation define_callbacks :validate, :scope => :name + + class_attribute :_validators + self._validators = Hash.new { |h,k| h[k] = [] } end module ClassMethods @@ -117,12 +121,23 @@ module ActiveModel end set_callback(:validate, *args, &block) end - - private - + + # List all validators that being used to validate the model using +validates_with+ + # method. + def validators + _validators.values.flatten.uniq + end + + # List all validators that being used to validate a specific attribute. + def validators_on(attribute) + _validators[attribute.to_sym] + end + + private + def _merge_attributes(attr_names) options = attr_names.extract_options! - options.merge(:attributes => attr_names) + options.merge(:attributes => attr_names.flatten) end end diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index db563876af..83d3ea80d6 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -62,6 +62,15 @@ module ActiveModel args.each do |klass| validator = klass.new(options, &block) validator.setup(self) if validator.respond_to?(:setup) + + if validator.respond_to?(:attributes) && !validator.attributes.empty? + validator.attributes.each do |attribute| + _validators[attribute.to_sym] << validator + end + else + _validators[nil] << validator + end + validate(validator, options) end end diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb index ad9729de00..b61f0cb266 100644 --- a/activemodel/lib/active_model/validator.rb +++ b/activemodel/lib/active_model/validator.rb @@ -1,3 +1,5 @@ +require "active_support/core_ext/module/anonymous" + module ActiveModel #:nodoc: # A simple base class that can be used along with # +ActiveModel::Validations::ClassMethods.validates_with+ @@ -88,11 +90,27 @@ module ActiveModel #:nodoc: class Validator attr_reader :options + # Returns the kind of the validator. + # + # == Examples + # + # PresenceValidator.kind #=> :presence + # UniquenessValidator.kind #=> :uniqueness + # + def self.kind + @kind ||= name.split('::').last.underscore.sub(/_validator$/, '').to_sym unless anonymous? + end + # Accepts options that will be made availible through the +options+ reader. def initialize(options) @options = options end + # Return the kind for this validator. + def kind + self.class.kind + end + # Override this method in subclasses with validation logic, adding errors # to the records +errors+ array where necessary. def validate(record) diff --git a/activemodel/lib/active_model/version.rb b/activemodel/lib/active_model/version.rb index d51423ae1b..85d0eed180 100644 --- a/activemodel/lib/active_model/version.rb +++ b/activemodel/lib/active_model/version.rb @@ -2,8 +2,9 @@ module ActiveModel module VERSION #:nodoc: MAJOR = 3 MINOR = 0 - TINY = "0.beta1" + TINY = 0 + BUILD = "beta1" - STRING = [MAJOR, MINOR, TINY].join('.') + STRING = [MAJOR, MINOR, TINY, BUILD].join('.') end end |