diff options
Diffstat (limited to 'activemodel/lib/active_model')
-rw-r--r-- | activemodel/lib/active_model/attribute_methods.rb | 22 | ||||
-rw-r--r-- | activemodel/lib/active_model/callbacks.rb | 7 | ||||
-rw-r--r-- | activemodel/lib/active_model/errors.rb | 71 | ||||
-rw-r--r-- | activemodel/lib/active_model/mass_assignment_security.rb | 38 | ||||
-rw-r--r-- | activemodel/lib/active_model/observing.rb | 10 | ||||
-rw-r--r-- | activemodel/lib/active_model/secure_password.rb | 34 | ||||
-rw-r--r-- | activemodel/lib/active_model/serialization.rb | 4 | ||||
-rw-r--r-- | activemodel/lib/active_model/validations.rb | 8 | ||||
-rw-r--r-- | activemodel/lib/active_model/validations/callbacks.rb | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/validations/validates.rb | 11 | ||||
-rw-r--r-- | activemodel/lib/active_model/validations/with.rb | 12 |
11 files changed, 134 insertions, 85 deletions
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index fc5f5c4c66..8f3782eb48 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -98,7 +98,7 @@ module ActiveModel def define_attr_method(name, value=nil, &block) sing = singleton_class sing.class_eval <<-eorb, __FILE__, __LINE__ + 1 - if method_defined?(:'original_#{name}') + if method_defined?('original_#{name}') undef :'original_#{name}' end alias_method :'original_#{name}', :'#{name}' @@ -109,7 +109,7 @@ module ActiveModel # use eval instead of a block to work around a memory leak in dev # mode in fcgi sing.class_eval <<-eorb, __FILE__, __LINE__ + 1 - def #{name}; #{value.to_s.inspect}; end + def #{name}; #{value.nil? ? 'nil' : value.to_s.inspect}; end eorb end end @@ -229,15 +229,13 @@ module ActiveModel def alias_attribute(new_name, old_name) attribute_method_matchers.each do |matcher| - module_eval <<-STR, __FILE__, __LINE__ + 1 - def #{matcher.method_name(new_name)}(*args) - send(:#{matcher.method_name(old_name)}, *args) - end - STR + define_method(matcher.method_name(new_name)) do |*args| + send(matcher.method_name(old_name), *args) + end end end - # Declares a the attributes that should be prefixed and suffixed by + # Declares the attributes that should be prefixed and suffixed by # ActiveModel::AttributeMethods. # # To use, pass in an array of attribute names (as strings or symbols), @@ -274,11 +272,11 @@ module ActiveModel method_name = matcher.method_name(attr_name) generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1 - if method_defined?(:'#{method_name}') + if method_defined?('#{method_name}') undef :'#{method_name}' end - def #{method_name}(*args) - send(:#{matcher.method_missing_target}, '#{attr_name}', *args) + define_method('#{method_name}') do |*args| + send('#{matcher.method_missing_target}', '#{attr_name}', *args) end STR end @@ -325,7 +323,7 @@ module ActiveModel options.symbolize_keys! @prefix, @suffix = options[:prefix] || '', options[:suffix] || '' @regex = /^(#{Regexp.escape(@prefix)})(.+?)(#{Regexp.escape(@suffix)})$/ - @method_missing_target = :"#{@prefix}attribute#{@suffix}" + @method_missing_target = "#{@prefix}attribute#{@suffix}" @method_name = "#{prefix}%s#{suffix}" end diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb index aaa41f5ec6..2a1f51a9a7 100644 --- a/activemodel/lib/active_model/callbacks.rb +++ b/activemodel/lib/active_model/callbacks.rb @@ -24,14 +24,11 @@ module ActiveModel # you want callbacks on in a block so that the callbacks get a chance to fire: # # def create - # _run_create_callbacks do + # run_callbacks :create do # # Your create action methods here # end # end # - # The _run_<method_name>_callbacks methods are dynamically created when you extend - # the <tt>ActiveModel::Callbacks</tt> module. - # # Then in your class, you can use the +before_create+, +after_create+ and +around_create+ # methods, just as you would in an Active Record module. # @@ -102,7 +99,7 @@ module ActiveModel define_callbacks(callback, options) types.each do |type| - send(:"_define_#{type}_model_callback", self, callback) + send("_define_#{type}_model_callback", self, callback) end end end diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index fdca852c7a..5e3cf510b0 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -60,9 +60,13 @@ module ActiveModel # p.validate! # => ["can not be nil"] # p.errors.full_messages # => ["name can not be nil"] # # etc.. - class Errors < ActiveSupport::OrderedHash + class Errors + include Enumerable + CALLBACKS_OPTIONS = [:if, :unless, :on, :allow_nil, :allow_blank] + attr_reader :messages + # Pass in the instance of the object that is using the errors object. # # class Person @@ -71,12 +75,29 @@ module ActiveModel # end # end def initialize(base) - @base = base - super() + @base = base + @messages = ActiveSupport::OrderedHash.new + end + + # Clear the messages + def clear + messages.clear + end + + # Do the error messages include an error with key +error+? + def include?(error) + messages.include? error end - alias_method :get, :[] - alias_method :set, :[]= + # Get messages for +key+ + def get(key) + messages[key] + end + + # Set messages for +key+ to +value+ + def set(key, value) + messages[key] = value + end # When passed a symbol or a name of a method, returns an array of errors # for the method. @@ -110,7 +131,7 @@ module ActiveModel # # then yield :name and "must be specified" # end def each - each_key do |attribute| + messages.each_key do |attribute| self[attribute].each { |error| yield attribute, error } end end @@ -125,6 +146,16 @@ module ActiveModel values.flatten.size end + # Returns all message values + def values + messages.values + end + + # Returns all message keys + def keys + messages.keys + end + # Returns an array of error messages, with the attribute name included # # p.errors.add(:name, "can't be blank") @@ -147,7 +178,7 @@ module ActiveModel def empty? all? { |k, v| v && v.empty? } end - + alias_method :blank?, :empty? # Returns an xml formatted representation of the Errors hash. # # p.errors.add(:name, "can't be blank") @@ -169,9 +200,7 @@ module ActiveModel end def to_hash - hash = ActiveSupport::OrderedHash.new - each { |k, v| (hash[k] ||= []) << v } - hash + messages.dup end # Adds +message+ to the error messages on +attribute+, which will be returned on a call to @@ -221,26 +250,20 @@ module ActiveModel # company.errors.full_messages # => # ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Address can't be blank"] def full_messages - full_messages = [] - - each do |attribute, messages| - messages = Array.wrap(messages) - next if messages.empty? - + map { |attribute, message| if attribute == :base - messages.each {|m| full_messages << m } + message else attr_name = attribute.to_s.gsub('.', '_').humanize attr_name = @base.class.human_attribute_name(attribute, :default => attr_name) - options = { :default => "%{attribute} %{message}", :attribute => attr_name } - messages.each do |m| - full_messages << I18n.t(:"errors.format", options.merge(:message => m)) - end + I18n.t(:"errors.format", { + :default => "%{attribute} %{message}", + :attribute => attr_name, + :message => message + }) end - end - - full_messages + } end # Translates an error message in its default scope diff --git a/activemodel/lib/active_model/mass_assignment_security.rb b/activemodel/lib/active_model/mass_assignment_security.rb index 66cd9fdde6..97e31d4243 100644 --- a/activemodel/lib/active_model/mass_assignment_security.rb +++ b/activemodel/lib/active_model/mass_assignment_security.rb @@ -20,32 +20,32 @@ module ActiveModel # For example, a logged in user may need to assign additional attributes depending # on their role: # - # class AccountsController < ApplicationController - # include ActiveModel::MassAssignmentSecurity + # class AccountsController < ApplicationController + # include ActiveModel::MassAssignmentSecurity # - # attr_accessible :first_name, :last_name + # attr_accessible :first_name, :last_name # - # def self.admin_accessible_attributes - # accessible_attributes + [ :plan_id ] - # end + # def self.admin_accessible_attributes + # accessible_attributes + [ :plan_id ] + # end # - # def update - # ... - # @account.update_attributes(account_params) - # ... - # end + # def update + # ... + # @account.update_attributes(account_params) + # ... + # end # - # protected + # protected # - # def account_params - # sanitize_for_mass_assignment(params[:account]) - # end + # def account_params + # sanitize_for_mass_assignment(params[:account]) + # end # - # def mass_assignment_authorizer - # admin ? admin_accessible_attributes : super - # end + # def mass_assignment_authorizer + # admin ? admin_accessible_attributes : super + # end # - # end + # end # module ClassMethods # Attributes named in this macro are protected from mass-assignment diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index 0d2dd36e59..bf4fd0740c 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -13,14 +13,18 @@ module ActiveModel # # Activates the observers assigned. Examples: # + # class ORM + # include ActiveModel::Observing + # end + # # # Calls PersonObserver.instance - # ActiveRecord::Base.observers = :person_observer + # ORM.observers = :person_observer # # # Calls Cacher.instance and GarbageCollector.instance - # ActiveRecord::Base.observers = :cacher, :garbage_collector + # ORM.observers = :cacher, :garbage_collector # # # Same as above, just using explicit class references - # ActiveRecord::Base.observers = Cacher, GarbageCollector + # ORM.observers = Cacher, GarbageCollector # # Note: Setting this does not instantiate the observers yet. # +instantiate_observers+ is called during startup, and before diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 52941942b8..957d0ddaaa 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -33,26 +33,34 @@ module ActiveModel attr_reader :password attr_accessor :password_confirmation - attr_protected(:password_digest) if respond_to?(:attr_protected) - validates_confirmation_of :password validates_presence_of :password_digest + + include InstanceMethodsOnActivation + + if respond_to?(:attributes_protected_by_default) + def self.attributes_protected_by_default + super + ['password_digest'] + end + end end end - # Returns self if the password is correct, otherwise false. - def authenticate(unencrypted_password) - if BCrypt::Password.new(password_digest) == unencrypted_password - self - else - false + module InstanceMethodsOnActivation + # Returns self if the password is correct, otherwise false. + def authenticate(unencrypted_password) + if BCrypt::Password.new(password_digest) == unencrypted_password + self + else + false + end end - end - # Encrypts the password into the password_digest attribute. - def password=(unencrypted_password) - @password = unencrypted_password - self.password_digest = BCrypt::Password.create(unencrypted_password) + # Encrypts the password into the password_digest attribute. + def password=(unencrypted_password) + @password = unencrypted_password + self.password_digest = BCrypt::Password.create(unencrypted_password) + end end end end diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb index 37739b98a1..caf44a2ee0 100644 --- a/activemodel/lib/active_model/serialization.rb +++ b/activemodel/lib/active_model/serialization.rb @@ -15,7 +15,7 @@ module ActiveModel # attr_accessor :name # # def attributes - # @attributes ||= {'name' => 'nil'} + # {'name' => name} # end # # end @@ -45,7 +45,7 @@ module ActiveModel # attr_accessor :name # # def attributes - # @attributes ||= {'name' => 'nil'} + # {'name' => name} # end # # end diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 6cb015a144..efd071fedc 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -146,8 +146,10 @@ module ActiveModel end # List all validators that being used to validate a specific attribute. - def validators_on(attribute) - _validators[attribute.to_sym] + def validators_on(*attributes) + attributes.map do |attribute| + _validators[attribute.to_sym] + end.flatten end # Check if method is an attribute method or not. @@ -207,7 +209,7 @@ module ActiveModel protected def run_validations! - _run_validate_callbacks + run_callbacks :validate errors.empty? end end diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb index 621518de5b..adc2867ad0 100644 --- a/activemodel/lib/active_model/validations/callbacks.rb +++ b/activemodel/lib/active_model/validations/callbacks.rb @@ -50,7 +50,7 @@ module ActiveModel # Overwrite run validations to include callbacks. def run_validations! - _run_validation_callbacks { super } + run_callbacks(:validation) { super } end end end diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 0132f68282..7ff42de00b 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -81,10 +81,9 @@ module ActiveModel # def validates(*attributes) defaults = attributes.extract_options! - validations = defaults.slice!(:if, :unless, :on, :allow_blank, :allow_nil) + validations = defaults.slice!(*_validates_default_keys) raise ArgumentError, "You need to supply at least one attribute" if attributes.empty? - raise ArgumentError, "Attribute names must be symbols" if attributes.any?{ |attribute| !attribute.is_a?(Symbol) } raise ArgumentError, "You need to supply at least one validation" if validations.empty? defaults.merge!(:attributes => attributes) @@ -104,6 +103,12 @@ module ActiveModel protected + # When creating custom validators, it might be useful to be able to specify + # additional default keys. This can be done by overwriting this method. + def _validates_default_keys + [ :if, :unless, :on, :allow_blank, :allow_nil ] + end + def _parse_validates_options(options) #:nodoc: case options when TrueClass @@ -118,4 +123,4 @@ module ActiveModel end end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 200efd4eb5..1663697727 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -8,6 +8,18 @@ module ActiveModel end end + class WithValidator < EachValidator + def validate_each(record, attr, val) + method_name = options[:with] + + if record.method(method_name).arity == 0 + record.send method_name + else + record.send method_name, attr + end + end + end + module ClassMethods # Passes the record off to the class or classes specified and allows them # to add errors based on more complex conditions. |