From 2650742bd02e108bc4ccdc59efa54b4916e3a443 Mon Sep 17 00:00:00 2001 From: Samuel Kadolph Date: Thu, 9 Dec 2010 13:30:02 -0500 Subject: Add support for namespaced validators Includes test and documentation for new feature Signed-off-by: Santiago Pastorino --- activemodel/lib/active_model/validations/validates.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 77c5073c6e..0132f68282 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -55,6 +55,10 @@ module ActiveModel # validates :name, :title => true # end # + # Additionally validator classes may be in another namespace and still used within any class. + # + # validates :name, :'file/title' => true + # # The validators hash can also handle regular expressions, ranges, # arrays and strings in shortcut form, e.g. # @@ -86,8 +90,10 @@ module ActiveModel defaults.merge!(:attributes => attributes) validations.each do |key, options| + key = "#{key.to_s.camelize}Validator" + begin - validator = const_get("#{key.to_s.camelize}Validator") + validator = key.include?('::') ? key.constantize : const_get(key) rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end -- cgit v1.2.3 From 972011a2e58be5caf84bf06dd954ba095c823984 Mon Sep 17 00:00:00 2001 From: Samuel Kadolph Date: Thu, 9 Dec 2010 13:30:02 -0500 Subject: Add support for namespaced validators Includes test and documentation for new feature Signed-off-by: Santiago Pastorino --- activemodel/lib/active_model/validations/validates.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 77c5073c6e..0132f68282 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -55,6 +55,10 @@ module ActiveModel # validates :name, :title => true # end # + # Additionally validator classes may be in another namespace and still used within any class. + # + # validates :name, :'file/title' => true + # # The validators hash can also handle regular expressions, ranges, # arrays and strings in shortcut form, e.g. # @@ -86,8 +90,10 @@ module ActiveModel defaults.merge!(:attributes => attributes) validations.each do |key, options| + key = "#{key.to_s.camelize}Validator" + begin - validator = const_get("#{key.to_s.camelize}Validator") + validator = key.include?('::') ? key.constantize : const_get(key) rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end -- cgit v1.2.3 From a3fbbb626fb8618162d39a55aeb5383406085e6c Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Fri, 17 Dec 2010 14:37:22 +0900 Subject: 'nil' => nil --- activemodel/lib/active_model/serialization.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb index 37739b98a1..f659419293 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'} + # @attributes ||= {'name' => nil} # end # # end @@ -45,7 +45,7 @@ module ActiveModel # attr_accessor :name # # def attributes - # @attributes ||= {'name' => 'nil'} + # @attributes ||= {'name' => nil} # end # # end -- cgit v1.2.3 From bcf4e4f2b02157cecc1f1727a95cdf5bfa471771 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 18 Dec 2010 13:38:05 -0800 Subject: Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePassword) to encapsulate dead-simple password usage with SHA2 encryption and salting --- activemodel/lib/active_model.rb | 1 + activemodel/lib/active_model/secure_password.rb | 73 +++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 activemodel/lib/active_model/secure_password.rb (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb index be0f24ff92..dd6ee058cc 100644 --- a/activemodel/lib/active_model.rb +++ b/activemodel/lib/active_model.rb @@ -42,6 +42,7 @@ module ActiveModel autoload :Naming autoload :Observer, 'active_model/observing' autoload :Observing + autoload :SecurePassword autoload :Serialization autoload :TestCase autoload :Translation diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb new file mode 100644 index 0000000000..0599ce6865 --- /dev/null +++ b/activemodel/lib/active_model/secure_password.rb @@ -0,0 +1,73 @@ +require 'digest/sha2' + +module ActiveModel + module SecurePassword + extend ActiveSupport::Concern + + module ClassMethods + # Adds methods to set and authenticate against a SHA2-encrypted and salted password. + # This mechanism requires you to have password_digest and password_salt attributes. + # + # Validations for presence of password, confirmation of password (using a "password_confirmation" attribute), + # and strength of password (at least 6 chars, not "password") are automatically added. + # You can add more validations by hand if need be. + # + # Example using Active Record (which automatically includes ActiveModel::SecurePassword): + # + # # Schema: User(name:string, password_digest:string, password_salt:string) + # class User < ActiveRecord::Base + # has_secure_password + # end + # + # user = User.new(:name => "david", :password => "secret", :password_confirmation => "nomatch") + # user.save # => false, password not long enough + # user.password = "mUc3m00RsqyRe" + # user.save # => false, confirmation doesn't match + # user.password_confirmation = "mUc3m00RsqyRe" + # user.save # => true + # user.authenticate("notright") # => false + # user.authenticate("mUc3m00RsqyRe") # => user + # User.find_by_name("david").try(:authenticate, "notright") # => nil + # User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user + def has_secure_password + attr_reader :password + attr_accessor :password_confirmation + + attr_protected(:password_digest, :password_salt) if respond_to?(:attr_protected) + + validates_confirmation_of :password + validates_presence_of :password_digest + validate :password_must_be_strong + end + end + + module InstanceMethods + # Returns self if the password is correct, otherwise false. + def authenticate(unencrypted_password) + password_digest == encrypt_password(unencrypted_password) ? self : false + end + + # Encrypts the password into the password_digest attribute. + def password=(unencrypted_password) + @password = unencrypted_password + self.password_digest = encrypt_password(unencrypted_password) + end + + private + def salt_for_password + self.password_salt ||= self.object_id.to_s + rand.to_s + end + + def encrypt_password(unencrypted_password) + Digest::SHA2.hexdigest(unencrypted_password + salt_for_password) + end + + def password_must_be_strong + if @password.present? + errors.add(:password, "must be longer than 6 characters") unless @password.size > 6 + errors.add(:password, "can't be 'password'") if @password == "password" + end + end + end + end +end \ No newline at end of file -- cgit v1.2.3 From 39b5ea6e01f6fc652cc63ab4e7e701cfaa9f9405 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 18 Dec 2010 15:39:32 -0800 Subject: Switch from SHA2 to BCrypt (easy Windows compatibility is coming shortly with new compiled gem) --- activemodel/lib/active_model/secure_password.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 0599ce6865..900205cf3f 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -1,4 +1,4 @@ -require 'digest/sha2' +require 'bcrypt' module ActiveModel module SecurePassword @@ -44,13 +44,17 @@ module ActiveModel module InstanceMethods # Returns self if the password is correct, otherwise false. def authenticate(unencrypted_password) - password_digest == encrypt_password(unencrypted_password) ? self : false + if BCrypt::Password.new(password_digest) == (unencrypted_password + salt_for_password) + self + else + false + end end # Encrypts the password into the password_digest attribute. def password=(unencrypted_password) @password = unencrypted_password - self.password_digest = encrypt_password(unencrypted_password) + self.password_digest = BCrypt::Password.create(unencrypted_password + salt_for_password) end private @@ -58,10 +62,6 @@ module ActiveModel self.password_salt ||= self.object_id.to_s + rand.to_s end - def encrypt_password(unencrypted_password) - Digest::SHA2.hexdigest(unencrypted_password + salt_for_password) - end - def password_must_be_strong if @password.present? errors.add(:password, "must be longer than 6 characters") unless @password.size > 6 -- cgit v1.2.3 From bd9dc4ff23ab1e185df6ccf35d6058c0a3d234ce Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 18 Dec 2010 19:09:07 -0800 Subject: BCrypt does its own salting, lovely! --- activemodel/lib/active_model/secure_password.rb | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 900205cf3f..54191f41df 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -4,17 +4,19 @@ module ActiveModel module SecurePassword extend ActiveSupport::Concern + WEAK_PASSWORDS = %w( password qwerty 123456 ) + module ClassMethods - # Adds methods to set and authenticate against a SHA2-encrypted and salted password. - # This mechanism requires you to have password_digest and password_salt attributes. + # Adds methods to set and authenticate against a BCrypt password. + # This mechanism requires you to have a password_digest attribute. # # Validations for presence of password, confirmation of password (using a "password_confirmation" attribute), - # and strength of password (at least 6 chars, not "password") are automatically added. + # and strength of password (at least 6 chars, not "password", etc) are automatically added. # You can add more validations by hand if need be. # # Example using Active Record (which automatically includes ActiveModel::SecurePassword): # - # # Schema: User(name:string, password_digest:string, password_salt:string) + # # Schema: User(name:string, password_digest:string) # class User < ActiveRecord::Base # has_secure_password # end @@ -33,7 +35,7 @@ module ActiveModel attr_reader :password attr_accessor :password_confirmation - attr_protected(:password_digest, :password_salt) if respond_to?(:attr_protected) + attr_protected(:password_digest) if respond_to?(:attr_protected) validates_confirmation_of :password validates_presence_of :password_digest @@ -44,7 +46,7 @@ module ActiveModel module InstanceMethods # Returns self if the password is correct, otherwise false. def authenticate(unencrypted_password) - if BCrypt::Password.new(password_digest) == (unencrypted_password + salt_for_password) + if BCrypt::Password.new(password_digest) == unencrypted_password self else false @@ -54,18 +56,15 @@ module ActiveModel # Encrypts the password into the password_digest attribute. def password=(unencrypted_password) @password = unencrypted_password - self.password_digest = BCrypt::Password.create(unencrypted_password + salt_for_password) + self.password_digest = BCrypt::Password.create(unencrypted_password) end - private - def salt_for_password - self.password_salt ||= self.object_id.to_s + rand.to_s - end + private def password_must_be_strong if @password.present? errors.add(:password, "must be longer than 6 characters") unless @password.size > 6 - errors.add(:password, "can't be 'password'") if @password == "password" + errors.add(:password, "is a too weak and common") if WEAK_PASSWORDS.include?(@password) end end end -- cgit v1.2.3 From d592fa946d43fdadf23f872a5c3334fb4f108f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 19 Dec 2010 09:28:15 +0100 Subject: Avoid warnings and fix small typo on SecurePassword. --- activemodel/lib/active_model/secure_password.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 54191f41df..3e7d3174ac 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -62,9 +62,9 @@ module ActiveModel private def password_must_be_strong - if @password.present? - errors.add(:password, "must be longer than 6 characters") unless @password.size > 6 - errors.add(:password, "is a too weak and common") if WEAK_PASSWORDS.include?(@password) + if password.present? + errors.add(:password, "must be longer than 6 characters") unless password.size > 6 + errors.add(:password, "is too weak and common") if WEAK_PASSWORDS.include?(password) end end end -- cgit v1.2.3 From b8f6dd8cbb2de870a4805800fd89148a417bc612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 19 Dec 2010 09:30:46 +0100 Subject: Add missing require and remove extra module. --- activemodel/lib/active_model/secure_password.rb | 39 ++++++++++++------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 3e7d3174ac..cd6256e3d6 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/object/blank' require 'bcrypt' module ActiveModel @@ -43,30 +44,28 @@ module ActiveModel end end - module InstanceMethods - # 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 + # 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 - # Encrypts the password into the password_digest attribute. - def password=(unencrypted_password) - @password = unencrypted_password - self.password_digest = BCrypt::Password.create(unencrypted_password) - end + # Encrypts the password into the password_digest attribute. + def password=(unencrypted_password) + @password = unencrypted_password + self.password_digest = BCrypt::Password.create(unencrypted_password) + end + private - private - def password_must_be_strong - if password.present? - errors.add(:password, "must be longer than 6 characters") unless password.size > 6 - errors.add(:password, "is too weak and common") if WEAK_PASSWORDS.include?(password) - end - end + def password_must_be_strong + if password.present? + errors.add(:password, "must be longer than 6 characters") unless password.size > 6 + errors.add(:password, "is too weak and common") if WEAK_PASSWORDS.include?(password) + end end end end \ No newline at end of file -- cgit v1.2.3 From 432556b9238b182dbd380a8f9936e3ca5dc6fa57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 19 Dec 2010 09:34:31 +0100 Subject: Make password messages translatable. --- activemodel/lib/active_model/locale/en.yml | 4 ++++ activemodel/lib/active_model/secure_password.rb | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/locale/en.yml b/activemodel/lib/active_model/locale/en.yml index 44425b4a28..c370a1f33e 100644 --- a/activemodel/lib/active_model/locale/en.yml +++ b/activemodel/lib/active_model/locale/en.yml @@ -25,3 +25,7 @@ en: less_than_or_equal_to: "must be less than or equal to %{count}" odd: "must be odd" even: "must be even" + + attributes: + password: + unsecure: "is too weak and common" diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index cd6256e3d6..cd997a61db 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -63,8 +63,8 @@ module ActiveModel def password_must_be_strong if password.present? - errors.add(:password, "must be longer than 6 characters") unless password.size > 6 - errors.add(:password, "is too weak and common") if WEAK_PASSWORDS.include?(password) + errors.add(:password, :too_short, :count => 7) unless password.size > 6 + errors.add(:password, :unsecure) if WEAK_PASSWORDS.include?(password) end end end -- cgit v1.2.3 From 863de37b05900f037132656812b7ef550d096ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 19 Dec 2010 09:37:08 +0100 Subject: 'unsecure' => 'insecure' --- activemodel/lib/active_model/locale/en.yml | 2 +- activemodel/lib/active_model/secure_password.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/locale/en.yml b/activemodel/lib/active_model/locale/en.yml index c370a1f33e..4a27355c6c 100644 --- a/activemodel/lib/active_model/locale/en.yml +++ b/activemodel/lib/active_model/locale/en.yml @@ -28,4 +28,4 @@ en: attributes: password: - unsecure: "is too weak and common" + insecure: "is too weak and common" diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index cd997a61db..1dcd389f8a 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -64,7 +64,7 @@ module ActiveModel def password_must_be_strong if password.present? errors.add(:password, :too_short, :count => 7) unless password.size > 6 - errors.add(:password, :unsecure) if WEAK_PASSWORDS.include?(password) + errors.add(:password, :insecure) if WEAK_PASSWORDS.include?(password) end end end -- cgit v1.2.3 From a39a3337698ca42ab158dc3b4b08ea75039b8a89 Mon Sep 17 00:00:00 2001 From: Mikel Lindsaar Date: Sun, 19 Dec 2010 20:39:54 +1100 Subject: Added ability to specify which passwords you want as weak passwords --- activemodel/lib/active_model/secure_password.rb | 31 ++++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 1dcd389f8a..06af18dfd1 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -5,12 +5,10 @@ module ActiveModel module SecurePassword extend ActiveSupport::Concern - WEAK_PASSWORDS = %w( password qwerty 123456 ) - module ClassMethods # Adds methods to set and authenticate against a BCrypt password. # This mechanism requires you to have a password_digest attribute. - # + # # Validations for presence of password, confirmation of password (using a "password_confirmation" attribute), # and strength of password (at least 6 chars, not "password", etc) are automatically added. # You can add more validations by hand if need be. @@ -24,9 +22,9 @@ module ActiveModel # # user = User.new(:name => "david", :password => "secret", :password_confirmation => "nomatch") # user.save # => false, password not long enough - # user.password = "mUc3m00RsqyRe" + # user.password = "mUc3m00RsqyRe" # user.save # => false, confirmation doesn't match - # user.password_confirmation = "mUc3m00RsqyRe" + # user.password_confirmation = "mUc3m00RsqyRe" # user.save # => true # user.authenticate("notright") # => false # user.authenticate("mUc3m00RsqyRe") # => user @@ -42,6 +40,27 @@ module ActiveModel validates_presence_of :password_digest validate :password_must_be_strong end + + # Allows you to specify the set of weak passwords that will be validated against + # if you specify has_secure_password in your model. + # + # The default set of weak passwords are: + # + # class User < ActiveRecord::Base + # weak_passwords = %w( password qwerty 123456 mypass ) + # end + def weak_passwords=(*values) + @weak_passwords = values.flatten + end + + # Returns the list of current weak passwords defined. Defaults to the standard + # list of 'password', 'qwerty' and '123456' + # + # User.weak_passwords #=> ['password', 'qwerty', '123456'] + def weak_passwords + @weak_passwords ||= %w( password qwerty 123456 ) + end + end # Returns self if the password is correct, otherwise false. @@ -64,7 +83,7 @@ module ActiveModel def password_must_be_strong if password.present? errors.add(:password, :too_short, :count => 7) unless password.size > 6 - errors.add(:password, :insecure) if WEAK_PASSWORDS.include?(password) + errors.add(:password, :insecure) if self.class.weak_passwords.include?(password) end end end -- cgit v1.2.3 From fa14df08a845abc61a6ed5bed1742ba59a4c2b8d Mon Sep 17 00:00:00 2001 From: Mikel Lindsaar Date: Sun, 19 Dec 2010 20:54:15 +1100 Subject: Fix incorrect docs --- activemodel/lib/active_model/secure_password.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 06af18dfd1..c5f32fa3fa 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -42,9 +42,7 @@ module ActiveModel end # Allows you to specify the set of weak passwords that will be validated against - # if you specify has_secure_password in your model. - # - # The default set of weak passwords are: + # if you specify has_secure_password in your model: # # class User < ActiveRecord::Base # weak_passwords = %w( password qwerty 123456 mypass ) -- cgit v1.2.3 From 6c217f98db6984c8d000103ac3cf66970eeaeb3f Mon Sep 17 00:00:00 2001 From: Mikel Lindsaar Date: Sun, 19 Dec 2010 21:28:37 +1100 Subject: Add set_weak_passwords call in alignment with set_table_name. --- activemodel/lib/active_model/secure_password.rb | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index c5f32fa3fa..6703d5daac 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -41,12 +41,18 @@ module ActiveModel validate :password_must_be_strong end - # Allows you to specify the set of weak passwords that will be validated against - # if you specify has_secure_password in your model: + # Specify the weak passwords to be used in the model: # - # class User < ActiveRecord::Base - # weak_passwords = %w( password qwerty 123456 mypass ) + # class User + # weak_passwords %w( password qwerty 123456 mypass ) # end + def set_weak_passwords(values) + @weak_passwords = values + end + + # Change the list of weak passwords that will be validated against: + # + # User.weak_passwords = %w( password qwerty 123456 mypass ) def weak_passwords=(*values) @weak_passwords = values.flatten end @@ -55,7 +61,7 @@ module ActiveModel # list of 'password', 'qwerty' and '123456' # # User.weak_passwords #=> ['password', 'qwerty', '123456'] - def weak_passwords + def weak_passwords(values = nil) @weak_passwords ||= %w( password qwerty 123456 ) end -- cgit v1.2.3 From 6d80f3a1ba52248cb8837af5ad40a23dc4fea213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 19 Dec 2010 13:30:19 +0100 Subject: Use class_attribute to ensure weak_passwords are inheritable. --- activemodel/lib/active_model/secure_password.rb | 26 ++++++++----------------- 1 file changed, 8 insertions(+), 18 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 6703d5daac..8da08f34ec 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -1,10 +1,16 @@ require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/class/attribute' require 'bcrypt' module ActiveModel module SecurePassword extend ActiveSupport::Concern + included do + class_attribute :weak_passwords + self.weak_passwords = %w( password qwerty 123456 ) + end + module ClassMethods # Adds methods to set and authenticate against a BCrypt password. # This mechanism requires you to have a password_digest attribute. @@ -44,27 +50,11 @@ module ActiveModel # Specify the weak passwords to be used in the model: # # class User - # weak_passwords %w( password qwerty 123456 mypass ) + # set_weak_passwords %w( password qwerty 123456 mypass ) # end def set_weak_passwords(values) - @weak_passwords = values - end - - # Change the list of weak passwords that will be validated against: - # - # User.weak_passwords = %w( password qwerty 123456 mypass ) - def weak_passwords=(*values) - @weak_passwords = values.flatten + self.weak_passwords = values end - - # Returns the list of current weak passwords defined. Defaults to the standard - # list of 'password', 'qwerty' and '123456' - # - # User.weak_passwords #=> ['password', 'qwerty', '123456'] - def weak_passwords(values = nil) - @weak_passwords ||= %w( password qwerty 123456 ) - end - end # Returns self if the password is correct, otherwise false. -- cgit v1.2.3 From 08ccd29b5b1e3badc2176a8036fea138b774c38f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 19 Dec 2010 14:58:14 -0200 Subject: Remove weak_passwords list and the length/strong password validator, leave that up to the programmer --- activemodel/lib/active_model/locale/en.yml | 4 --- activemodel/lib/active_model/secure_password.rb | 37 ++++--------------------- 2 files changed, 6 insertions(+), 35 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/locale/en.yml b/activemodel/lib/active_model/locale/en.yml index 4a27355c6c..44425b4a28 100644 --- a/activemodel/lib/active_model/locale/en.yml +++ b/activemodel/lib/active_model/locale/en.yml @@ -25,7 +25,3 @@ en: less_than_or_equal_to: "must be less than or equal to %{count}" odd: "must be odd" even: "must be even" - - attributes: - password: - insecure: "is too weak and common" diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 8da08f34ec..f4411cde80 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -1,22 +1,16 @@ -require 'active_support/core_ext/object/blank' -require 'active_support/core_ext/class/attribute' +require 'active_support/concern' require 'bcrypt' module ActiveModel module SecurePassword extend ActiveSupport::Concern - included do - class_attribute :weak_passwords - self.weak_passwords = %w( password qwerty 123456 ) - end - module ClassMethods # Adds methods to set and authenticate against a BCrypt password. # This mechanism requires you to have a password_digest attribute. # - # Validations for presence of password, confirmation of password (using a "password_confirmation" attribute), - # and strength of password (at least 6 chars, not "password", etc) are automatically added. + # Validations for presence of password, confirmation of password (using + # a "password_confirmation" attribute) are automatically added. # You can add more validations by hand if need be. # # Example using Active Record (which automatically includes ActiveModel::SecurePassword): @@ -26,8 +20,8 @@ module ActiveModel # has_secure_password # end # - # user = User.new(:name => "david", :password => "secret", :password_confirmation => "nomatch") - # user.save # => false, password not long enough + # user = User.new(:name => "david", :password => "", :password_confirmation => "nomatch") + # user.save # => false, password required # user.password = "mUc3m00RsqyRe" # user.save # => false, confirmation doesn't match # user.password_confirmation = "mUc3m00RsqyRe" @@ -44,16 +38,6 @@ module ActiveModel validates_confirmation_of :password validates_presence_of :password_digest - validate :password_must_be_strong - end - - # Specify the weak passwords to be used in the model: - # - # class User - # set_weak_passwords %w( password qwerty 123456 mypass ) - # end - def set_weak_passwords(values) - self.weak_passwords = values end end @@ -71,14 +55,5 @@ module ActiveModel @password = unencrypted_password self.password_digest = BCrypt::Password.create(unencrypted_password) end - - private - - def password_must_be_strong - if password.present? - errors.add(:password, :too_short, :count => 7) unless password.size > 6 - errors.add(:password, :insecure) if self.class.weak_passwords.include?(password) - end - end end -end \ No newline at end of file +end -- cgit v1.2.3 From 5fb42ac478923c78ebc3e457acea4dc6726e3796 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 19 Dec 2010 18:50:18 -0200 Subject: Tests and docs which explain the use of validate with a block and without arguments --- activemodel/lib/active_model/validations.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index b044caa8d3..6cb015a144 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -104,7 +104,7 @@ module ActiveModel # end # end # - # Or with a block which is passed with the current record to be validated: + # With a block which is passed with the current record to be validated: # # class Comment # include ActiveModel::Validations @@ -118,6 +118,16 @@ module ActiveModel # end # end # + # Or with a block where self points to the current record to be validated: + # + # class Comment + # include ActiveModel::Validations + # + # validate do + # errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee) + # end + # end + # def validate(*args, &block) options = args.extract_options! if options.key?(:on) -- cgit v1.2.3 From ab2bde45f8140a3ebf8b478e688ef612fc4181fc Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 19 Dec 2010 19:15:26 -0200 Subject: Remove require AS::Concern from places where is already in --- activemodel/lib/active_model/dirty.rb | 1 - activemodel/lib/active_model/secure_password.rb | 1 - 2 files changed, 2 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb index 1dfd0b6132..a479795d51 100644 --- a/activemodel/lib/active_model/dirty.rb +++ b/activemodel/lib/active_model/dirty.rb @@ -1,5 +1,4 @@ require 'active_model/attribute_methods' -require 'active_support/concern' require 'active_support/hash_with_indifferent_access' require 'active_support/core_ext/object/duplicable' diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index f4411cde80..52941942b8 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -1,4 +1,3 @@ -require 'active_support/concern' require 'bcrypt' module ActiveModel -- cgit v1.2.3 From 207f266ccaaa9cd04cd2a7513ae5598c4358b510 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 20 Dec 2010 17:33:26 -0800 Subject: define_attr_method must serialize nil correctly --- activemodel/lib/active_model/attribute_methods.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index fc5f5c4c66..33454123ce 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -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 -- cgit v1.2.3 From 6b099975fa7e18356b19eca659595713512209e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 27 Dec 2010 09:30:36 +0100 Subject: No need to symbolize these. --- activemodel/lib/active_model/attribute_methods.rb | 2 +- activemodel/lib/active_model/callbacks.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index 33454123ce..67f88b4088 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -325,7 +325,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..7302a869c8 100644 --- a/activemodel/lib/active_model/callbacks.rb +++ b/activemodel/lib/active_model/callbacks.rb @@ -102,7 +102,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 -- cgit v1.2.3 From 43433b3fb4b9c054e0bcaaa1f7456b3fececd268 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 29 Dec 2010 10:18:14 -0800 Subject: Instance methods shouldnt be added until you actually call has_secure_password --- activemodel/lib/active_model/secure_password.rb | 26 ++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 52941942b8..7e8370a04c 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -37,22 +37,26 @@ module ActiveModel validates_confirmation_of :password validates_presence_of :password_digest + + include InstanceMethodsOnActivation 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 -- cgit v1.2.3 From 8de5595e4d101a53f33ae8c48837855d8594f320 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Wed, 5 Jan 2011 17:26:25 +0530 Subject: fix difference between behaviour of blank and empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activemodel/lib/active_model/errors.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index fdca852c7a..0dc10e3c7d 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -147,7 +147,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") -- cgit v1.2.3 From da82b0a746c36ea1274041b0d2401903abf33904 Mon Sep 17 00:00:00 2001 From: brainopia Date: Sat, 15 Jan 2011 03:10:10 +0300 Subject: Remove reference to ActiveRecord from ActiveModel comments --- activemodel/lib/active_model/observing.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'activemodel/lib') 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 -- cgit v1.2.3 From 1a051259b426d624e846f76c3fc6011693603e55 Mon Sep 17 00:00:00 2001 From: Daniel Schierbeck Date: Sat, 15 Jan 2011 17:54:02 +0100 Subject: Properly indent code example block --- .../lib/active_model/mass_assignment_security.rb | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'activemodel/lib') 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 -- cgit v1.2.3 From d8919d3151f4379853df102a630d5db468bf3430 Mon Sep 17 00:00:00 2001 From: Paul Yoder Date: Thu, 27 Jan 2011 09:27:35 -0600 Subject: Deleted extra "a" in method comment --- activemodel/lib/active_model/attribute_methods.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index 67f88b4088..34669c1542 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -237,7 +237,7 @@ module ActiveModel 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), -- cgit v1.2.3 From 57bc25c5f8129f57b08a2dc7c319b86778dd8a40 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sun, 9 Jan 2011 10:15:05 -0800 Subject: Use run_callbacks; the generated _run__callbacks method is not a public interface. Signed-off-by: Santiago Pastorino --- activemodel/lib/active_model/callbacks.rb | 5 +---- activemodel/lib/active_model/validations.rb | 2 +- activemodel/lib/active_model/validations/callbacks.rb | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb index 7302a869c8..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__callbacks methods are dynamically created when you extend - # the ActiveModel::Callbacks 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. # diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 6cb015a144..cdf23c7b1b 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -207,7 +207,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 -- cgit v1.2.3 From bca070ef2ddbbe7e093c340ec7722e4dca0f37a5 Mon Sep 17 00:00:00 2001 From: Caleb Land Date: Thu, 3 Feb 2011 13:46:03 -0500 Subject: allow spaces and other characters in attribute names [#4725 state:resolved] * define the dynamically defined methods with 'define_method' instead of def * wrap some string injected method names in quotes Signed-off-by: Santiago Pastorino --- activemodel/lib/active_model/attribute_methods.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index 34669c1542..f46fa3a5e2 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -230,8 +230,8 @@ 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) + define_method(:'#{matcher.method_name(new_name)}') do |*args| + send(:'#{matcher.method_name(old_name)}', *args) end STR end @@ -277,8 +277,8 @@ module ActiveModel 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 -- cgit v1.2.3 From 6f4d9989dd1b4d396aa8c37c9a9a7f240911d9b5 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 3 Feb 2011 20:37:02 -0200 Subject: method_defined?, define_method and send accepts a string as argument --- activemodel/lib/active_model/attribute_methods.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index f46fa3a5e2..9a89b0db9c 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}' @@ -230,8 +230,8 @@ module ActiveModel def alias_attribute(new_name, old_name) attribute_method_matchers.each do |matcher| module_eval <<-STR, __FILE__, __LINE__ + 1 - define_method(:'#{matcher.method_name(new_name)}') do |*args| - send(:'#{matcher.method_name(old_name)}', *args) + define_method('#{matcher.method_name(new_name)}') do |*args| + send('#{matcher.method_name(old_name)}', *args) end STR end @@ -274,11 +274,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 - define_method(:'#{method_name}') do |*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 -- cgit v1.2.3 From 082326deb5ba7e78d4a51ef6b8783d668066ed23 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 3 Feb 2011 20:47:02 -0200 Subject: module_eval is not needed here --- activemodel/lib/active_model/attribute_methods.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index 9a89b0db9c..8f3782eb48 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -229,11 +229,9 @@ module ActiveModel def alias_attribute(new_name, old_name) attribute_method_matchers.each do |matcher| - module_eval <<-STR, __FILE__, __LINE__ + 1 - define_method('#{matcher.method_name(new_name)}') do |*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 -- cgit v1.2.3 From 7176ade35b4d6b167873991e0851f3fb9d46ae3b Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Sat, 5 Feb 2011 15:37:38 -0800 Subject: Do not require that validation attributes be specified as symbols --- activemodel/lib/active_model/validations/validates.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 0132f68282..172ca70c19 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -84,7 +84,6 @@ module ActiveModel validations = defaults.slice!(:if, :unless, :on, :allow_blank, :allow_nil) 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) @@ -118,4 +117,4 @@ module ActiveModel end end end -end \ No newline at end of file +end -- cgit v1.2.3 From ed7614aa7de2eaeba16c9af11cf09b4fd7ed6819 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Sat, 5 Feb 2011 16:00:57 -0800 Subject: Provide a way to specify alternate option keys for validates --- activemodel/lib/active_model/validations/validates.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 172ca70c19..7ff42de00b 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -81,7 +81,7 @@ 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, "You need to supply at least one validation" if validations.empty? @@ -103,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 -- cgit v1.2.3 From e9e9ed6b60a42a7c3afe3c4a9f8cf6d1e5422e59 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Sat, 5 Feb 2011 16:33:00 -0800 Subject: Be able to pass a validator method to #validates --- activemodel/lib/active_model/validations/with.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 200efd4eb5..16d81263a2 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -8,6 +8,12 @@ module ActiveModel end end + class WithValidator < EachValidator + def validate_each(record, attr, val) + record.send options[:with] + 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. -- cgit v1.2.3 From cd13fbd8d8071b822f6d4f8967ef80c617c036ba Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Sat, 5 Feb 2011 16:44:35 -0800 Subject: Optionally pass in the attribute being validated to an instance method validator --- activemodel/lib/active_model/validations/with.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 16d81263a2..1663697727 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -10,7 +10,13 @@ module ActiveModel class WithValidator < EachValidator def validate_each(record, attr, val) - record.send options[:with] + method_name = options[:with] + + if record.method(method_name).arity == 0 + record.send method_name + else + record.send method_name, attr + end end end -- cgit v1.2.3 From cf9324e5909e71ec0a2477338e696b6af2f17f13 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Sat, 5 Feb 2011 20:27:02 -0800 Subject: Find all validators for multiple attributes --- activemodel/lib/active_model/validations.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index cdf23c7b1b..a0f90452b3 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.inject([]) do |all, attribute| + all |= _validators[attribute.to_sym] || [] + end end # Check if method is an attribute method or not. -- cgit v1.2.3 From 285fdbae2bafd5de415a685b57af36254197348c Mon Sep 17 00:00:00 2001 From: Nathaniel Bibler Date: Sat, 1 Jan 2011 21:12:24 -0500 Subject: Fixed broken, memoized attributes method example [#6245 state:committed] Signed-off-by: Santiago Pastorino --- activemodel/lib/active_model/serialization.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb index f659419293..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 -- cgit v1.2.3 From 933adce8f45b41a5a6b6bb31ba9d6fb5188f4a35 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Feb 2011 19:15:06 -0200 Subject: Use map + flatten here --- activemodel/lib/active_model/validations.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index a0f90452b3..efd071fedc 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -147,9 +147,9 @@ module ActiveModel # List all validators that being used to validate a specific attribute. def validators_on(*attributes) - attributes.inject([]) do |all, attribute| - all |= _validators[attribute.to_sym] || [] - end + attributes.map do |attribute| + _validators[attribute.to_sym] + end.flatten end # Check if method is an attribute method or not. -- cgit v1.2.3 From ed6e09c1b181b000d8f409305ddce27fca571674 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 8 Feb 2011 17:22:23 -0800 Subject: use 1 call to concat rather than calling << n times --- activemodel/lib/active_model/errors.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 0dc10e3c7d..ea23073a29 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -228,15 +228,15 @@ module ActiveModel next if messages.empty? if attribute == :base - messages.each {|m| full_messages << m } + full_messages.concat messages 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 + full_messages.concat messages.map { |m| + I18n.t(:"errors.format", options.merge(:message => m)) + } end end -- cgit v1.2.3 From 307e6b2b74ba3ae72602dc33e6d45cd3e46181c7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 8 Feb 2011 17:40:49 -0800 Subject: favor composition over inheritence --- activemodel/lib/active_model/errors.rb | 42 ++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 9 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index ea23073a29..9d278220a8 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,24 @@ 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 - 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 +126,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 +141,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") @@ -169,9 +195,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 -- cgit v1.2.3 From c6b4ef082f80255c1e3ec6e4feb1d199ed1e7efa Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 9 Feb 2011 08:31:22 -0800 Subject: use map rather than array concatenation --- activemodel/lib/active_model/errors.rb | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 9d278220a8..04d996f78c 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -245,26 +245,21 @@ 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| + map { |attribute, messages| messages = Array.wrap(messages) - next if messages.empty? if attribute == :base - full_messages.concat messages + messages 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 } - full_messages.concat messages.map { |m| + messages.map { |m| I18n.t(:"errors.format", options.merge(:message => m)) } end - end - - full_messages + }.flatten end # Translates an error message in its default scope -- cgit v1.2.3 From 51d84c1d33ee244edfd02f4a703b852ded087370 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 9 Feb 2011 08:42:13 -0800 Subject: we do not need message to be an array --- activemodel/lib/active_model/errors.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 04d996f78c..003c94a409 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -245,21 +245,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 - map { |attribute, messages| - messages = Array.wrap(messages) - + map { |attribute, message| if attribute == :base - messages + 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.map { |m| - I18n.t(:"errors.format", options.merge(:message => m)) - } + I18n.t(:"errors.format", { + :default => "%{attribute} %{message}", + :attribute => attr_name, + :message => message + }) end - }.flatten + } end # Translates an error message in its default scope -- cgit v1.2.3 From f48d32c0cff36cb505443ff72738def3a82c2886 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 9 Feb 2011 09:19:15 -0800 Subject: implementing include? on AM::Errors --- activemodel/lib/active_model/errors.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 003c94a409..5e3cf510b0 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -84,6 +84,11 @@ module ActiveModel messages.clear end + # Do the error messages include an error with key +error+? + def include?(error) + messages.include? error + end + # Get messages for +key+ def get(key) messages[key] -- cgit v1.2.3 From ad31549ab3044afc336c05243481c0f663689584 Mon Sep 17 00:00:00 2001 From: Tsutomu Kuroda Date: Wed, 26 Jan 2011 11:35:02 +0900 Subject: Override attributes_protected_by_default when has_secure_password is called. attr_protected should not be called, because it nullifies the mass assignment protection that has been set by attr_accessible. Signed-off-by: Santiago Pastorino --- activemodel/lib/active_model/secure_password.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 7e8370a04c..957d0ddaaa 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -33,12 +33,16 @@ 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 -- cgit v1.2.3 From bd7d8665a083f534f9d1aaa544d912f933b4fd61 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Wed, 16 Feb 2011 14:15:48 -0800 Subject: add note about observer config for rails apps ActiveModel::Observer and ActiveRecord::Observer have similar documentation, but a Rails user looking at the ActiveModel version might not realize that a change to config/application.rb is required to activate the observer. This change adds a note to that effect, pointing to the AR version from the AM version. --- activemodel/lib/active_model/observing.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index bf4fd0740c..dde3a882cf 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -156,6 +156,10 @@ module ActiveModel # The AuditObserver will now act on both updates to Account and Balance by treating # them both as records. # + # If you're using an Observer in a Rails application with Active Record, be sure to + # read about the necessary configuration in the documentation for + # ActiveRecord::Observer. + # class Observer include Singleton -- cgit v1.2.3 From a906deabc6554f6271b3d9a84384c101edaad921 Mon Sep 17 00:00:00 2001 From: Nicholas Rowe Date: Thu, 17 Feb 2011 20:34:22 -0500 Subject: fix type: remove extra period --- activemodel/lib/active_model/naming.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index 44aedc8efd..3f430f94a6 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -69,7 +69,7 @@ module ActiveModel # # Providing the functionality that ActiveModel::Naming provides in your object # is required to pass the Active Model Lint test. So either extending the provided - # method below, or rolling your own is required.. + # method below, or rolling your own is required. module Naming # Returns an ActiveModel::Name object for module. It can be # used to retrieve all kinds of naming-related information. -- cgit v1.2.3 From fbfa30a1eeaaab22ac8f43a4137ec8282920fe15 Mon Sep 17 00:00:00 2001 From: Frederick Cheung Date: Fri, 18 Feb 2011 17:55:29 +0000 Subject: Change validates inclusion to use cover? for Ranges in ruby 1.9 [#6453 state:committed] Signed-off-by: Xavier Noria --- .../lib/active_model/validations/inclusion.rb | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 049b093618..108586b8df 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -8,9 +8,26 @@ module ActiveModel ":in option of the configuration hash" unless options[:in].respond_to?(:include?) end - def validate_each(record, attribute, value) - unless options[:in].include?(value) - record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) + # On Ruby 1.9 Range#include? checks all possible values in the range for equality, + # so it may be slow for large ranges. The new Range#cover? uses the previous logic + # of comparing a value with the range endpoints. + if (1..2).respond_to?(:cover?) + def validate_each(record, attribute, value) + included = if options[:in].is_a?(Range) + options[:in].cover?(value) + else + options[:in].include?(value) + end + + unless included + record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) + end + end + else + def validate_each(record, attribute, value) + unless options[:in].include?(value) + record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) + end end end end -- cgit v1.2.3 From 8d96b89110d2c16d395ec3a5dc13e33be76b8e78 Mon Sep 17 00:00:00 2001 From: Peer Allan Date: Fri, 18 Feb 2011 20:51:56 -0600 Subject: Clarification of ActiveRecord ActiveModel validation documentation --- activemodel/lib/active_model/validations.rb | 4 ++-- activemodel/lib/active_model/validations/acceptance.rb | 2 +- activemodel/lib/active_model/validations/confirmation.rb | 2 +- activemodel/lib/active_model/validations/format.rb | 2 +- activemodel/lib/active_model/validations/length.rb | 2 +- activemodel/lib/active_model/validations/numericality.rb | 2 +- activemodel/lib/active_model/validations/presence.rb | 3 +-- 7 files changed, 8 insertions(+), 9 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index efd071fedc..5e2c7b411d 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -71,8 +71,8 @@ module ActiveModel # end # # Options: - # * :on - Specifies when this validation is active (default is - # :save, other options :create, :update). + # * :on - Specifies the context where this validation is active + # (e.g. :on => :create or :on => :special_rules) # * :allow_nil - Skip validation if attribute is +nil+. # * :allow_blank - Skip validation if attribute is blank. # * :if - Specifies a method, proc or string to call to determine diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb index a7296d8e1d..fba44defc1 100644 --- a/activemodel/lib/active_model/validations/acceptance.rb +++ b/activemodel/lib/active_model/validations/acceptance.rb @@ -38,7 +38,7 @@ module ActiveModel # * :message - A custom error message (default is: "must be # accepted"). # * :on - Specifies when this validation is active (default is - # :save, other options are :create and + # nil, other options are :create and # :update). # * :allow_nil - Skip validation if attribute is +nil+ (default # is true). diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index 00df10cef0..bcefc7d888 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -46,7 +46,7 @@ module ActiveModel # * :message - A custom error message (default is: "doesn't match # confirmation"). # * :on - Specifies when this validation is active (default is - # :save, other options :create, :update). + # :nil, other options :create, :update). # * :if - Specifies a method, proc or string to call to determine # if the validation should occur (e.g. :if => :allow_validation, # or :if => Proc.new { |user| user.signup_step > 2 }). The diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb index 104f403492..ca8920bce6 100644 --- a/activemodel/lib/active_model/validations/format.rb +++ b/activemodel/lib/active_model/validations/format.rb @@ -51,7 +51,7 @@ module ActiveModel # * :allow_blank - If set to true, skips this validation if the attribute is blank (default is +false+). # * :with - Regular expression that if the attribute matches will result in a successful validation. # * :without - Regular expression that if the attribute does not match will result in a successful validation. - # * :on - Specifies when this validation is active (default is :save, other options :create, :update). + # * :on - Specifies when this validation is active (default is nil, other options :create, :update). # * :if - Specifies a method, proc or string to call to determine if the validation should # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The # method, proc or string should return or evaluate to a true or false value. diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb index 5a46ecb4ac..97a5cb012e 100644 --- a/activemodel/lib/active_model/validations/length.rb +++ b/activemodel/lib/active_model/validations/length.rb @@ -83,7 +83,7 @@ module ActiveModel # * :too_short - The error message if the attribute goes under the minimum (default is: "is too short (min is %{count} characters)"). # * :wrong_length - The error message if using the :is method and the attribute is the wrong size (default is: "is the wrong length (should be %{count} characters)"). # * :message - The error message to use for a :minimum, :maximum, or :is violation. An alias of the appropriate too_long/too_short/wrong_length message. - # * :on - Specifies when this validation is active (default is :save, other options :create, :update). + # * :on - Specifies the context where this validation is active (e.g. :on => :create or :on => :special_rules) # * :if - Specifies a method, proc or string to call to determine if the validation should # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The # method, proc or string should return or evaluate to a true or false value. diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 95fe20de75..7b155bb7f7 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -93,7 +93,7 @@ module ActiveModel # # Configuration options: # * :message - A custom error message (default is: "is not a number"). - # * :on - Specifies when this validation is active (default is :save, other options :create, :update). + # * :on - Specifies the context where this validation is active (e.g. :on => :create or :on => :special_rules) # * :only_integer - Specifies whether the value has to be an integer, e.g. an integral value (default is +false+). # * :allow_nil - Skip validation if attribute is +nil+ (default is +false+). Notice that for fixnum and float columns empty strings are converted to +nil+. # * :greater_than - Specifies the value must be greater than the supplied value. diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index 28c4640b17..3bfd6f15d1 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -26,8 +26,7 @@ module ActiveModel # # Configuration options: # * message - A custom error message (default is: "can't be blank"). - # * on - Specifies when this validation is active (default is :save, other options :create, - # :update). + # * :on - Specifies the context where this validation is active (e.g. :on => :create or :on => :special_rules) # * if - Specifies a method, proc or string to call to determine if the validation should # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). # The method, proc or string should return or evaluate to a true or false value. -- cgit v1.2.3 From 511bf2a0505309c65bbf2ad9394e3c548762ea5d Mon Sep 17 00:00:00 2001 From: Diego Carrion Date: Sat, 19 Feb 2011 21:13:33 -0200 Subject: refactored ActiveModel::Validations::InclusionValidator#validate_each [#6455 state:committed] Signed-off-by: Santiago Pastorino --- .../lib/active_model/validations/inclusion.rb | 26 +++++++--------------- 1 file changed, 8 insertions(+), 18 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 108586b8df..b0903a6a2c 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/range.rb' + module ActiveModel # == Active Model Inclusion Validator @@ -8,27 +10,15 @@ module ActiveModel ":in option of the configuration hash" unless options[:in].respond_to?(:include?) end + def validate_each(record, attribute, value) + record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) unless options[:in].send(include?, value) + end + # On Ruby 1.9 Range#include? checks all possible values in the range for equality, # so it may be slow for large ranges. The new Range#cover? uses the previous logic # of comparing a value with the range endpoints. - if (1..2).respond_to?(:cover?) - def validate_each(record, attribute, value) - included = if options[:in].is_a?(Range) - options[:in].cover?(value) - else - options[:in].include?(value) - end - - unless included - record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) - end - end - else - def validate_each(record, attribute, value) - unless options[:in].include?(value) - record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) - end - end + def include? + options[:in].is_a?(Range) ? :cover? : :include? end end -- cgit v1.2.3 From e2d54fb3f17ac30c91d855c45060ec5518b75ec5 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sun, 20 Feb 2011 10:52:24 +0100 Subject: documents the backported Range#cover?, and related stuff --- activemodel/lib/active_model/validations/inclusion.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index b0903a6a2c..3ee2a3ccd1 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -14,9 +14,9 @@ module ActiveModel record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) unless options[:in].send(include?, value) end - # On Ruby 1.9 Range#include? checks all possible values in the range for equality, - # so it may be slow for large ranges. The new Range#cover? uses the previous logic - # of comparing a value with the range endpoints. + # In Ruby 1.9 Range#include? on non-numeric ranges checks all possible values in the + # range for equality, so it may be slow for large ranges. The new Range#cover? + # uses the previous logic of comparing a value with the range endpoints. def include? options[:in].is_a?(Range) ? :cover? : :include? end @@ -33,6 +33,8 @@ module ActiveModel # # Configuration options: # * :in - An enumerable object of available items. + # If the enumerable is a range the test is performed with Range#cover? + # (backported in Active Support for 1.8), otherwise with include?. # * :message - Specifies a custom error message (default is: "is not included in the list"). # * :allow_nil - If set to true, skips this validation if the attribute is +nil+ (default is +false+). # * :allow_blank - If set to true, skips this validation if the attribute is blank (default is +false+). -- cgit v1.2.3 From 6d7a8267b98b0ffc5f1b45c0a35ba0548f2084e8 Mon Sep 17 00:00:00 2001 From: Nicholas Rowe Date: Sun, 20 Feb 2011 21:05:41 -0500 Subject: Documentation: Added small comments to Observering module --- activemodel/lib/active_model/observing.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index dde3a882cf..f09bdca9d1 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -48,6 +48,7 @@ module ActiveModel observers.each { |o| instantiate_observer(o) } end + # Add a new Observer to the pool def add_observer(observer) unless observer.respond_to? :update raise ArgumentError, "observer needs to respond to `update'" @@ -55,12 +56,14 @@ module ActiveModel observer_instances << observer end + # Notify list of observers of a change def notify_observers(*arg) for observer in observer_instances observer.update(*arg) end end + # Total number of observers def count_observers observer_instances.size end -- cgit v1.2.3 From 34316d8b7e6b830e97ebbe124ac6d9a19ce77d2d Mon Sep 17 00:00:00 2001 From: Nicholas Rowe Date: Sun, 20 Feb 2011 21:35:43 -0500 Subject: Docs: Update to_xml documentation to match as_json docuemntation --- activemodel/lib/active_model/serializers/xml.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb index b897baa614..0b0116d32c 100644 --- a/activemodel/lib/active_model/serializers/xml.rb +++ b/activemodel/lib/active_model/serializers/xml.rb @@ -134,6 +134,31 @@ module ActiveModel # Returns XML representing the model. Configuration can be # passed through +options+. + # + # Without any +options+, the returned XML string will include all the model's + # attributes. For example: + # + # konata = User.find(1) + # konata.to_xml + # + # + # + # 1 + # David + # 16 + # 2011-01-30T22:29:23Z + # + # + # The :only and :except options can be used to limit the attributes + # included, and work similar to the +attributes+ method. + # + # To include the result of some method calls on the model use :methods + # + # To include associations use :include + # + # For further documentation see activerecord/lib/active_record/serializers/xml_serializer.xml + + def to_xml(options = {}, &block) Serializer.new(self, options).serialize(&block) end -- cgit v1.2.3 From 843a5b9a3aa3e20f3a3b50fea16351dcddcfde75 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Mon, 21 Feb 2011 11:00:03 +0100 Subject: copy-edits 34316d8 --- activemodel/lib/active_model/serializers/xml.rb | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb index 0b0116d32c..d4295e6afe 100644 --- a/activemodel/lib/active_model/serializers/xml.rb +++ b/activemodel/lib/active_model/serializers/xml.rb @@ -146,19 +146,17 @@ module ActiveModel # 1 # David # 16 - # 2011-01-30T22:29:23Z + # 2011-01-30T22:29:23Z # # # The :only and :except options can be used to limit the attributes # included, and work similar to the +attributes+ method. - # - # To include the result of some method calls on the model use :methods # - # To include associations use :include + # To include the result of some method calls on the model use :methods. # - # For further documentation see activerecord/lib/active_record/serializers/xml_serializer.xml - - + # To include associations use :include. + # + # For further documentation see activerecord/lib/active_record/serializers/xml_serializer.xml. def to_xml(options = {}, &block) Serializer.new(self, options).serialize(&block) end -- cgit v1.2.3 From 9297027e082c69e590fc090132cee495ce0fc4b1 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Mon, 21 Feb 2011 11:01:26 +0100 Subject: copy-edits 6d7a826 --- activemodel/lib/active_model/observing.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index f09bdca9d1..af036b560e 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -48,7 +48,7 @@ module ActiveModel observers.each { |o| instantiate_observer(o) } end - # Add a new Observer to the pool + # Add a new observer to the pool. def add_observer(observer) unless observer.respond_to? :update raise ArgumentError, "observer needs to respond to `update'" @@ -56,14 +56,14 @@ module ActiveModel observer_instances << observer end - # Notify list of observers of a change + # Notify list of observers of a change. def notify_observers(*arg) for observer in observer_instances observer.update(*arg) end end - # Total number of observers + # Total number of observers. def count_observers observer_instances.size end -- cgit v1.2.3 From b481574a33764e2db1caf01c233a9c9ac9723780 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Mon, 21 Feb 2011 11:37:08 +0100 Subject: copy-edits 8d96b89 --- activemodel/lib/active_model/validations.rb | 4 ++-- activemodel/lib/active_model/validations/acceptance.rb | 6 +++--- activemodel/lib/active_model/validations/confirmation.rb | 5 +++-- activemodel/lib/active_model/validations/exclusion.rb | 3 +++ activemodel/lib/active_model/validations/format.rb | 4 +++- activemodel/lib/active_model/validations/inclusion.rb | 3 +++ activemodel/lib/active_model/validations/length.rb | 4 +++- activemodel/lib/active_model/validations/numericality.rb | 4 +++- activemodel/lib/active_model/validations/presence.rb | 4 +++- 9 files changed, 26 insertions(+), 11 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 5e2c7b411d..98af88b5a0 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -71,8 +71,8 @@ module ActiveModel # end # # Options: - # * :on - Specifies the context where this validation is active - # (e.g. :on => :create or :on => :special_rules) + # * :on - Specifies the context where this validation is active + # (e.g. :on => :create or :on => :custom_validation_context) # * :allow_nil - Skip validation if attribute is +nil+. # * :allow_blank - Skip validation if attribute is blank. # * :if - Specifies a method, proc or string to call to determine diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb index fba44defc1..4f390613aa 100644 --- a/activemodel/lib/active_model/validations/acceptance.rb +++ b/activemodel/lib/active_model/validations/acceptance.rb @@ -37,9 +37,9 @@ module ActiveModel # Configuration options: # * :message - A custom error message (default is: "must be # accepted"). - # * :on - Specifies when this validation is active (default is - # nil, other options are :create and - # :update). + # * :on - Specifies when this validation is active. Runs in all + # validation contexts by default (+nil+), other options are :create + # and :update. # * :allow_nil - Skip validation if attribute is +nil+ (default # is true). # * :accept - Specifies value that is considered accepted. diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index bcefc7d888..e6d10cfff8 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -45,8 +45,9 @@ module ActiveModel # Configuration options: # * :message - A custom error message (default is: "doesn't match # confirmation"). - # * :on - Specifies when this validation is active (default is - # :nil, other options :create, :update). + # * :on - Specifies when this validation is active. Runs in all + # validation contexts by default (+nil+), other options are :create + # and :update. # * :if - Specifies a method, proc or string to call to determine # if the validation should occur (e.g. :if => :allow_validation, # or :if => Proc.new { |user| user.signup_step > 2 }). The diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb index 4138892786..e38e565d09 100644 --- a/activemodel/lib/active_model/validations/exclusion.rb +++ b/activemodel/lib/active_model/validations/exclusion.rb @@ -29,6 +29,9 @@ module ActiveModel # * :message - Specifies a custom error message (default is: "is reserved"). # * :allow_nil - If set to true, skips this validation if the attribute is +nil+ (default is +false+). # * :allow_blank - If set to true, skips this validation if the attribute is blank (default is +false+). + # * :on - Specifies when this validation is active. Runs in all + # validation contexts by default (+nil+), other options are :create + # and :update. # * :if - Specifies a method, proc or string to call to determine if the validation should # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The # method, proc or string should return or evaluate to a true or false value. diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb index ca8920bce6..541f53a834 100644 --- a/activemodel/lib/active_model/validations/format.rb +++ b/activemodel/lib/active_model/validations/format.rb @@ -51,7 +51,9 @@ module ActiveModel # * :allow_blank - If set to true, skips this validation if the attribute is blank (default is +false+). # * :with - Regular expression that if the attribute matches will result in a successful validation. # * :without - Regular expression that if the attribute does not match will result in a successful validation. - # * :on - Specifies when this validation is active (default is nil, other options :create, :update). + # * :on - Specifies when this validation is active. Runs in all + # validation contexts by default (+nil+), other options are :create + # and :update. # * :if - Specifies a method, proc or string to call to determine if the validation should # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The # method, proc or string should return or evaluate to a true or false value. diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 108586b8df..7d4ccc0d4f 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -46,6 +46,9 @@ module ActiveModel # * :message - Specifies a custom error message (default is: "is not included in the list"). # * :allow_nil - If set to true, skips this validation if the attribute is +nil+ (default is +false+). # * :allow_blank - If set to true, skips this validation if the attribute is blank (default is +false+). + # * :on - Specifies when this validation is active. Runs in all + # validation contexts by default (+nil+), other options are :create + # and :update. # * :if - Specifies a method, proc or string to call to determine if the validation should # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The # method, proc or string should return or evaluate to a true or false value. diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb index 97a5cb012e..7af6c83460 100644 --- a/activemodel/lib/active_model/validations/length.rb +++ b/activemodel/lib/active_model/validations/length.rb @@ -83,7 +83,9 @@ module ActiveModel # * :too_short - The error message if the attribute goes under the minimum (default is: "is too short (min is %{count} characters)"). # * :wrong_length - The error message if using the :is method and the attribute is the wrong size (default is: "is the wrong length (should be %{count} characters)"). # * :message - The error message to use for a :minimum, :maximum, or :is violation. An alias of the appropriate too_long/too_short/wrong_length message. - # * :on - Specifies the context where this validation is active (e.g. :on => :create or :on => :special_rules) + # * :on - Specifies when this validation is active. Runs in all + # validation contexts by default (+nil+), other options are :create + # and :update. # * :if - Specifies a method, proc or string to call to determine if the validation should # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The # method, proc or string should return or evaluate to a true or false value. diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 7b155bb7f7..ae576462e6 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -93,7 +93,9 @@ module ActiveModel # # Configuration options: # * :message - A custom error message (default is: "is not a number"). - # * :on - Specifies the context where this validation is active (e.g. :on => :create or :on => :special_rules) + # * :on - Specifies when this validation is active. Runs in all + # validation contexts by default (+nil+), other options are :create + # and :update. # * :only_integer - Specifies whether the value has to be an integer, e.g. an integral value (default is +false+). # * :allow_nil - Skip validation if attribute is +nil+ (default is +false+). Notice that for fixnum and float columns empty strings are converted to +nil+. # * :greater_than - Specifies the value must be greater than the supplied value. diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index 3bfd6f15d1..cfb4c33dcc 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -26,7 +26,9 @@ module ActiveModel # # Configuration options: # * message - A custom error message (default is: "can't be blank"). - # * :on - Specifies the context where this validation is active (e.g. :on => :create or :on => :special_rules) + # * :on - Specifies when this validation is active. Runs in all + # validation contexts by default (+nil+), other options are :create + # and :update. # * if - Specifies a method, proc or string to call to determine if the validation should # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). # The method, proc or string should return or evaluate to a true or false value. -- cgit v1.2.3 From 839d06f5f28740a9641a1b91e5df94f64e224547 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Wed, 5 Jan 2011 03:58:45 +0700 Subject: We're in 2011, let's update our license Signed-off-by: Santiago Pastorino --- activemodel/lib/active_model.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb index dd6ee058cc..d0e2a6f39c 100644 --- a/activemodel/lib/active_model.rb +++ b/activemodel/lib/active_model.rb @@ -1,5 +1,5 @@ #-- -# Copyright (c) 2004-2010 David Heinemeier Hansson +# Copyright (c) 2004-2011 David Heinemeier Hansson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the -- cgit v1.2.3 From a00bed0c48f469d1cd2de364bfaddbc724046195 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 27 Feb 2011 21:23:59 -0200 Subject: Revert "Properly interpolate i18n keys in modules [#5572 state:resolved]" This breaks #6448, you should use :"module/class" as key for namespacing [#6448 state:committed] This reverts commit 8d30193b08bd2321a7a78a1f481bd5e4d4d45557. --- activemodel/lib/active_model/errors.rb | 4 ++-- activemodel/lib/active_model/naming.rb | 15 +++++---------- activemodel/lib/active_model/translation.rb | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 5e3cf510b0..c2f0228785 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -295,8 +295,8 @@ module ActiveModel type = options.delete(:message) if options[:message].is_a?(Symbol) defaults = @base.class.lookup_ancestors.map do |klass| - [ :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}", - :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.i18n_key}.#{type}" ] + [ :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.underscore}.attributes.#{attribute}.#{type}", + :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.underscore}.#{type}" ] end defaults << options.delete(:message) diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index 3f430f94a6..eb9b847509 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -4,7 +4,7 @@ require 'active_support/core_ext/module/introspection' module ActiveModel class Name < String - attr_reader :singular, :plural, :element, :collection, :partial_path, :route_key, :param_key, :i18n_key + attr_reader :singular, :plural, :element, :collection, :partial_path, :route_key, :param_key alias_method :cache_key, :collection def initialize(klass, namespace = nil) @@ -20,7 +20,6 @@ module ActiveModel @partial_path = "#{@collection}/#{@element}".freeze @param_key = (namespace ? _singularize(@unnamespaced) : @singular).freeze @route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural).freeze - @i18n_key = _singularize(self, '.').to_sym end # Transform the model name into a more humane format, using I18n. By default, @@ -34,7 +33,7 @@ module ActiveModel @klass.respond_to?(:i18n_scope) defaults = @klass.lookup_ancestors.map do |klass| - klass.model_name.i18n_key + klass.model_name.underscore.to_sym end defaults << options[:default] if options[:default] @@ -45,10 +44,9 @@ module ActiveModel end private - - def _singularize(string, replacement='_') - ActiveSupport::Inflector.underscore(string).tr('/', replacement) - end + def _singularize(str) + ActiveSupport::Inflector.underscore(str).tr('/', '_') + end end # == Active Model Naming @@ -64,9 +62,6 @@ module ActiveModel # BookCover.model_name # => "BookCover" # BookCover.model_name.human # => "Book cover" # - # BookCover.model_name.i18n_key # => "book_cover" - # BookModule::BookCover.model_name.i18n_key # => "book_module.book_cover" - # # Providing the functionality that ActiveModel::Naming provides in your object # is required to pass the Active Model Lint test. So either extending the provided # method below, or rolling your own is required. diff --git a/activemodel/lib/active_model/translation.rb b/activemodel/lib/active_model/translation.rb index 920a133159..dbb76244e4 100644 --- a/activemodel/lib/active_model/translation.rb +++ b/activemodel/lib/active_model/translation.rb @@ -44,7 +44,7 @@ module ActiveModel # Specify +options+ with additional translating options. def human_attribute_name(attribute, options = {}) defaults = lookup_ancestors.map do |klass| - :"#{self.i18n_scope}.attributes.#{klass.model_name.i18n_key}.#{attribute}" + :"#{self.i18n_scope}.attributes.#{klass.model_name.underscore}.#{attribute}" end defaults << :"attributes.#{attribute}" -- cgit v1.2.3