aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/CHANGELOG107
-rw-r--r--activemodel/CHANGELOG.md109
-rw-r--r--activemodel/activemodel.gemspec2
-rw-r--r--activemodel/lib/active_model/attribute_methods.rb59
-rw-r--r--activemodel/lib/active_model/dirty.rb2
-rw-r--r--activemodel/lib/active_model/errors.rb47
-rw-r--r--activemodel/lib/active_model/naming.rb24
-rw-r--r--activemodel/lib/active_model/observing.rb3
-rw-r--r--activemodel/lib/active_model/secure_password.rb4
-rw-r--r--activemodel/lib/active_model/validations/validates.rb2
-rw-r--r--activemodel/lib/active_model/validator.rb2
-rw-r--r--activemodel/test/cases/errors_test.rb64
-rw-r--r--activemodel/test/cases/naming_test.rb38
-rw-r--r--activemodel/test/cases/secure_password_test.rb10
-rw-r--r--activemodel/test/cases/validations/exclusion_validation_test.rb12
-rw-r--r--activemodel/test/cases/validations/format_validation_test.rb24
-rw-r--r--activemodel/test/cases/validations/inclusion_validation_test.rb12
-rw-r--r--activemodel/test/models/blog_post.rb8
18 files changed, 322 insertions, 207 deletions
diff --git a/activemodel/CHANGELOG b/activemodel/CHANGELOG
deleted file mode 100644
index 3d26d646b0..0000000000
--- a/activemodel/CHANGELOG
+++ /dev/null
@@ -1,107 +0,0 @@
-* Add ability to define strict validation(with :strict => true option) that always raises exception when fails [Bogdan Gusiev]
-
-* Deprecate "Model.model_name.partial_path" in favor of "model.to_partial_path" [Grant Hutchins, Peter Jaros]
-
-* Provide mass_assignment_sanitizer as an easy API to replace the sanitizer behavior. Also support both :logger (default) and :strict sanitizer behavior [Bogdan Gusiev]
-
-*Rails 3.1.0 (August 30, 2011)*
-
-* Alternate I18n namespace lookup is no longer supported.
- Instead of "activerecord.models.admins.post", do "activerecord.models.admins/post" instead [José Valim]
-
-* attr_accessible and friends now accepts :as as option to specify a role [Josh Kalderimis]
-
-* Add support for proc or lambda as an option for InclusionValidator,
- ExclusionValidator, and FormatValidator [Prem Sichanugrist]
-
- You can now supply Proc, lambda, or anything that respond to #call in those
- validations, and it will be called with current record as an argument.
- That given proc or lambda must returns an object which respond to #include? for
- InclusionValidator and ExclusionValidator, and returns a regular expression
- object for FormatValidator.
-
-* Added ActiveModel::SecurePassword to encapsulate dead-simple password usage with BCrypt encryption and salting [DHH]
-
-* ActiveModel::AttributeMethods allows attributes to be defined on demand [Alexander Uvarov]
-
-* Add support for selectively enabling/disabling observers [Myron Marston]
-
-
-*Rails 3.0.7 (April 18, 2011)*
-
-*No changes.
-
-
-*Rails 3.0.6 (April 5, 2011)
-
-* Fix when database column name has some symbolic characters (e.g. Oracle CASE# VARCHAR2(20)) #5818 #6850 [Robert Pankowecki, Santiago Pastorino]
-
-* Fix length validation for fixnums #6556 [Andriy Tyurnikov]
-
-* Fix i18n key collision with namespaced models #6448 [yves.senn]
-
-
-*Rails 3.0.5 (February 26, 2011)*
-
-* No changes.
-
-
-*Rails 3.0.4 (February 8, 2011)*
-
-* No changes.
-
-
-*Rails 3.0.3 (November 16, 2010)*
-
-* No changes.
-
-
-*Rails 3.0.2 (November 15, 2010)*
-
-* No changes
-
-
-*Rails 3.0.1 (October 15, 2010)*
-
-* No Changes, just a version bump.
-
-
-*Rails 3.0.0 (August 29, 2010)*
-
-* Added ActiveModel::MassAssignmentSecurity [Eric Chapweske, Josh Kalderimis]
-
-* JSON supports a custom root option: to_json(:root => 'custom') #4515 [Jatinder Singh]
-
-* #new_record? and #destroyed? were removed from ActiveModel::Lint. Use
- persisted? instead. A model is persisted if it's not a new_record? and it was
- not destroyed? [MG]
-
-* Added validations reflection in ActiveModel::Validations [JV]
-
- Model.validators
- Model.validators_on(:field)
-
-* #to_key was added to ActiveModel::Lint so we can generate DOM IDs for
- AMo objects with composite keys [MG]
-
-* ActiveModel::Observer#add_observer!
-
- It has a custom hook to define after_find that should really be in a
- ActiveRecord::Observer subclass:
-
- def add_observer!(klass)
- klass.add_observer(self)
- klass.class_eval 'def after_find() end' unless klass.respond_to?(:after_find)
- end
-
-* Change the ActiveModel::Base.include_root_in_json default to true for Rails 3 [DHH]
-
-* Add validates_format_of :without => /regexp/ option. #430 [Elliot Winkler, Peer Allan]
-
- Example :
-
- validates_format_of :subdomain, :without => /www|admin|mail/
-
-* Introduce validates_with to encapsulate attribute validations in a class. #2630 [Jeff Dean]
-
-* Extracted from Active Record and Active Resource.
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
new file mode 100644
index 0000000000..71a737caff
--- /dev/null
+++ b/activemodel/CHANGELOG.md
@@ -0,0 +1,109 @@
+* Added ActiveModel::Errors#added? to check if a specific error has been added *Martin Svalin*
+
+* Add ability to define strict validation(with :strict => true option) that always raises exception when fails *Bogdan Gusiev*
+
+* Deprecate "Model.model_name.partial_path" in favor of "model.to_partial_path" *Grant Hutchins, Peter Jaros*
+
+* Provide mass_assignment_sanitizer as an easy API to replace the sanitizer behavior. Also support both :logger (default) and :strict sanitizer behavior *Bogdan Gusiev*
+
+## Rails 3.1.0 (August 30, 2011) ##
+
+* Alternate I18n namespace lookup is no longer supported.
+ Instead of "activerecord.models.admins.post", do "activerecord.models.admins/post" instead *José Valim*
+
+* attr_accessible and friends now accepts :as as option to specify a role *Josh Kalderimis*
+
+* Add support for proc or lambda as an option for InclusionValidator,
+ ExclusionValidator, and FormatValidator *Prem Sichanugrist*
+
+ You can now supply Proc, lambda, or anything that respond to #call in those
+ validations, and it will be called with current record as an argument.
+ That given proc or lambda must returns an object which respond to #include? for
+ InclusionValidator and ExclusionValidator, and returns a regular expression
+ object for FormatValidator.
+
+* Added ActiveModel::SecurePassword to encapsulate dead-simple password usage with BCrypt encryption and salting *DHH*
+
+* ActiveModel::AttributeMethods allows attributes to be defined on demand *Alexander Uvarov*
+
+* Add support for selectively enabling/disabling observers *Myron Marston*
+
+
+## Rails 3.0.7 (April 18, 2011) ##
+
+* No changes.
+
+
+* Rails 3.0.6 (April 5, 2011)
+
+* Fix when database column name has some symbolic characters (e.g. Oracle CASE# VARCHAR2(20)) #5818 #6850 *Robert Pankowecki, Santiago Pastorino*
+
+* Fix length validation for fixnums #6556 *Andriy Tyurnikov*
+
+* Fix i18n key collision with namespaced models #6448 *yves.senn*
+
+
+## Rails 3.0.5 (February 26, 2011) ##
+
+* No changes.
+
+
+## Rails 3.0.4 (February 8, 2011) ##
+
+* No changes.
+
+
+## Rails 3.0.3 (November 16, 2010) ##
+
+* No changes.
+
+
+## Rails 3.0.2 (November 15, 2010) ##
+
+* No changes
+
+
+## Rails 3.0.1 (October 15, 2010) ##
+
+* No Changes, just a version bump.
+
+
+## Rails 3.0.0 (August 29, 2010) ##
+
+* Added ActiveModel::MassAssignmentSecurity *Eric Chapweske, Josh Kalderimis*
+
+* JSON supports a custom root option: to_json(:root => 'custom') #4515 *Jatinder Singh*
+
+* #new_record? and #destroyed? were removed from ActiveModel::Lint. Use
+ persisted? instead. A model is persisted if it's not a new_record? and it was
+ not destroyed? *MG*
+
+* Added validations reflection in ActiveModel::Validations *JV*
+
+ Model.validators
+ Model.validators_on(:field)
+
+* #to_key was added to ActiveModel::Lint so we can generate DOM IDs for
+ AMo objects with composite keys *MG*
+
+* ActiveModel::Observer#add_observer!
+
+ It has a custom hook to define after_find that should really be in a
+ ActiveRecord::Observer subclass:
+
+ def add_observer!(klass)
+ klass.add_observer(self)
+ klass.class_eval 'def after_find() end' unless klass.respond_to?(:after_find)
+ end
+
+* Change the ActiveModel::Base.include_root_in_json default to true for Rails 3 *DHH*
+
+* Add validates_format_of :without => /regexp/ option. #430 *Elliot Winkler, Peer Allan*
+
+ Example :
+
+ validates_format_of :subdomain, :without => /www|admin|mail/
+
+* Introduce validates_with to encapsulate attribute validations in a class. #2630 *Jeff Dean*
+
+* Extracted from Active Record and Active Resource.
diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec
index 260ad01b65..49f664bf89 100644
--- a/activemodel/activemodel.gemspec
+++ b/activemodel/activemodel.gemspec
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
s.email = 'david@loudthinking.com'
s.homepage = 'http://www.rubyonrails.org'
- s.files = Dir['CHANGELOG', 'MIT-LICENSE', 'README.rdoc', 'lib/**/*']
+ s.files = Dir['CHANGELOG.md', 'MIT-LICENSE', 'README.rdoc', 'lib/**/*']
s.require_path = 'lib'
s.add_dependency('activesupport', version)
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb
index ef0b95424e..e69cb5c459 100644
--- a/activemodel/lib/active_model/attribute_methods.rb
+++ b/activemodel/lib/active_model/attribute_methods.rb
@@ -57,7 +57,8 @@ module ActiveModel
module AttributeMethods
extend ActiveSupport::Concern
- COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?=]?\z/
+ NAME_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?=]?\z/
+ CALL_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?]?\z/
included do
class_attribute :attribute_method_matchers, :instance_writer => false
@@ -112,7 +113,7 @@ module ActiveModel
# If we can compile the method name, do it. Otherwise use define_method.
# This is an important *optimization*, please don't change it. define_method
# has slower dispatch and consumes more memory.
- if name =~ COMPILABLE_REGEXP
+ if name =~ NAME_COMPILABLE_REGEXP
sing.class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{name}; #{value.nil? ? 'nil' : value.to_s.inspect}; end
RUBY
@@ -240,18 +241,7 @@ module ActiveModel
attribute_method_matchers.each do |matcher|
matcher_new = matcher.method_name(new_name).to_s
matcher_old = matcher.method_name(old_name).to_s
-
- if matcher_new =~ COMPILABLE_REGEXP && matcher_old =~ COMPILABLE_REGEXP
- module_eval <<-RUBY, __FILE__, __LINE__ + 1
- def #{matcher_new}(*args)
- send(:#{matcher_old}, *args)
- end
- RUBY
- else
- define_method(matcher_new) do |*args|
- send(matcher_old, *args)
- end
- end
+ define_optimized_call self, matcher_new, matcher_old
end
end
@@ -293,17 +283,7 @@ module ActiveModel
if respond_to?(generate_method)
send(generate_method, attr_name)
else
- if method_name =~ COMPILABLE_REGEXP
- defn = "def #{method_name}(*args)"
- else
- defn = "define_method(:'#{method_name}') do |*args|"
- end
-
- generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
- #{defn}
- send(:#{matcher.method_missing_target}, '#{attr_name}', *args)
- end
- RUBY
+ define_optimized_call generated_attribute_methods, method_name, matcher.method_missing_target, attr_name.to_s
end
end
end
@@ -342,11 +322,11 @@ module ActiveModel
# used to alleviate the GC, which ultimately also speeds up the app
# significantly (in our case our test suite finishes 10% faster with
# this cache).
- def attribute_method_matchers_cache
+ def attribute_method_matchers_cache #:nodoc:
@attribute_method_matchers_cache ||= {}
end
- def attribute_method_matcher(method_name)
+ def attribute_method_matcher(method_name) #:nodoc:
if attribute_method_matchers_cache.key?(method_name)
attribute_method_matchers_cache[method_name]
else
@@ -359,6 +339,31 @@ module ActiveModel
end
end
+ # Define a method `name` in `mod` that dispatches to `send`
+ # using the given `extra` args. This fallbacks `define_method`
+ # and `send` if the given names cannot be compiled.
+ def define_optimized_call(mod, name, send, *extra) #:nodoc:
+ if name =~ NAME_COMPILABLE_REGEXP
+ defn = "def #{name}(*args)"
+ else
+ defn = "define_method(:'#{name}') do |*args|"
+ end
+
+ extra = (extra.map(&:inspect) << "*args").join(", ")
+
+ if send =~ CALL_COMPILABLE_REGEXP
+ target = "#{send}(#{extra})"
+ else
+ target = "send(:'#{send}', #{extra})"
+ end
+
+ mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
+ #{defn}
+ #{target}
+ end
+ RUBY
+ end
+
class AttributeMethodMatcher
attr_reader :prefix, :suffix, :method_missing_target
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index 166cccf161..026f077ee7 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -98,7 +98,7 @@ module ActiveModel
# person.name = 'bob'
# person.changed? # => true
def changed?
- !changed_attributes.empty?
+ changed_attributes.any?
end
# List of attributes with unsaved changes.
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index d91e4a2b6a..8337b04c0d 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -205,21 +205,14 @@ module ActiveModel
messages.dup
end
- # Adds +message+ to the error messages on +attribute+, which will be returned on a call to
- # <tt>on(attribute)</tt> for the same attribute. More than one error can be added to the same
- # +attribute+ in which case an array will be returned on a call to <tt>on(attribute)</tt>.
+ # Adds +message+ to the error messages on +attribute+. More than one error can be added to the same
+ # +attribute+.
# If no +message+ is supplied, <tt>:invalid</tt> is assumed.
#
# If +message+ is a symbol, it will be translated using the appropriate scope (see +translate_error+).
# If +message+ is a proc, it will be called, allowing for things like <tt>Time.now</tt> to be used within an error.
def add(attribute, message = nil, options = {})
- message ||= :invalid
-
- if message.is_a?(Symbol)
- message = generate_message(attribute, message, options.except(*CALLBACKS_OPTIONS))
- elsif message.is_a?(Proc)
- message = message.call
- end
+ message = normalize_message(attribute, message, options)
if options[:strict]
raise ActiveModel::StrictValidationFailed, message
end
@@ -244,6 +237,15 @@ module ActiveModel
end
end
+ # Returns true if an error on the attribute with the given message is present, false otherwise.
+ # +message+ is treated the same as for +add+.
+ # p.errors.add :name, :blank
+ # p.errors.added? :name, :blank # => true
+ def added?(attribute, message = nil, options = {})
+ message = normalize_message(attribute, message, options)
+ self[attribute].include? message
+ end
+
# Returns all the full error messages in an array.
#
# class Company
@@ -300,13 +302,17 @@ module ActiveModel
def generate_message(attribute, type = :invalid, options = {})
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}" ]
+ if @base.class.respond_to?(:i18n_scope)
+ 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}" ]
+ end
+ else
+ defaults = []
end
defaults << options.delete(:message)
- defaults << :"#{@base.class.i18n_scope}.errors.messages.#{type}"
+ defaults << :"#{@base.class.i18n_scope}.errors.messages.#{type}" if @base.class.respond_to?(:i18n_scope)
defaults << :"errors.attributes.#{attribute}.#{type}"
defaults << :"errors.messages.#{type}"
@@ -325,6 +331,19 @@ module ActiveModel
I18n.translate(key, options)
end
+
+ private
+ def normalize_message(attribute, message, options)
+ message ||= :invalid
+
+ if message.is_a?(Symbol)
+ generate_message(attribute, message, options.except(*CALLBACKS_OPTIONS))
+ elsif message.is_a?(Proc)
+ message.call
+ else
+ message
+ end
+ end
end
class StrictValidationFailed < StandardError
diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb
index f16459ede2..2566920d63 100644
--- a/activemodel/lib/active_model/naming.rb
+++ b/activemodel/lib/active_model/naming.rb
@@ -13,18 +13,18 @@ module ActiveModel
def initialize(klass, namespace = nil, name = nil)
name ||= klass.name
super(name)
- @unnamespaced = self.sub(/^#{namespace.name}::/, '') if namespace
- @klass = klass
- @singular = _singularize(self).freeze
- @plural = ActiveSupport::Inflector.pluralize(@singular).freeze
- @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze
- @human = ActiveSupport::Inflector.humanize(@element).freeze
- @collection = ActiveSupport::Inflector.tableize(self).freeze
+ @unnamespaced = self.sub(/^#{namespace.name}::/, '') if namespace
+ @klass = klass
+ @singular = _singularize(self).freeze
+ @plural = ActiveSupport::Inflector.pluralize(@singular).freeze
+ @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze
+ @human = ActiveSupport::Inflector.humanize(@element).freeze
+ @collection = ActiveSupport::Inflector.tableize(self).freeze
@partial_path = "#{@collection}/#{@element}".freeze
- @param_key = (namespace ? _singularize(@unnamespaced) : @singular).freeze
- @route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural).freeze
- @i18n_key = self.underscore.to_sym
+ @param_key = (namespace ? _singularize(@unnamespaced) : @singular).freeze
+ @route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural).freeze
+ @i18n_key = self.underscore.to_sym
end
# Transform the model name into a more humane format, using I18n. By default,
@@ -79,7 +79,9 @@ module ActiveModel
# used to retrieve all kinds of naming-related information.
def model_name
@_model_name ||= begin
- namespace = self.parents.detect { |n| n.respond_to?(:_railtie) }
+ namespace = self.parents.detect do |n|
+ n.respond_to?(:use_relative_model_naming?) && n.use_relative_model_naming?
+ end
ActiveModel::Name.new(self, namespace)
end
end
diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb
index 7a910d18e7..cd8eb357de 100644
--- a/activemodel/lib/active_model/observing.rb
+++ b/activemodel/lib/active_model/observing.rb
@@ -187,8 +187,7 @@ module ActiveModel
def observe(*models)
models.flatten!
models.collect! { |model| model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model }
- remove_possible_method(:observed_classes)
- define_method(:observed_classes) { models }
+ redefine_method(:observed_classes) { models }
end
# Returns an array of Classes to observe.
diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb
index 7a109d9a52..db78864c67 100644
--- a/activemodel/lib/active_model/secure_password.rb
+++ b/activemodel/lib/active_model/secure_password.rb
@@ -32,8 +32,8 @@ module ActiveModel
# User.find_by_name("david").try(:authenticate, "notright") # => nil
# User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user
def has_secure_password
- # Load bcrypt-ruby only when has_secured_password is used to avoid make ActiveModel
- # (and by extension the entire framework) dependent on a binary library.
+ # Load bcrypt-ruby only when has_secure_password is used.
+ # This is to avoid ActiveModel (and by extension the entire framework) being dependent on a binary library.
gem 'bcrypt-ruby', '~> 3.0.0'
require 'bcrypt'
diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb
index fbceb81e8f..8e09f6ac35 100644
--- a/activemodel/lib/active_model/validations/validates.rb
+++ b/activemodel/lib/active_model/validations/validates.rb
@@ -57,7 +57,7 @@ module ActiveModel
#
# Additionally validator classes may be in another namespace and still used within any class.
#
- # validates :name, :'file/title' => true
+ # validates :name, :'film/title' => true
#
# The validators hash can also handle regular expressions, ranges,
# arrays and strings in shortcut form, e.g.
diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb
index 0e444738ba..35ec98c822 100644
--- a/activemodel/lib/active_model/validator.rb
+++ b/activemodel/lib/active_model/validator.rb
@@ -57,7 +57,7 @@ module ActiveModel #:nodoc:
# To add behavior to the initialize method, use the following signature:
#
# class MyValidator < ActiveModel::Validator
- # def initialize(record, options)
+ # def initialize(options)
# super
# @my_custom_field = options[:field_name] || :first_name
# end
diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb
index 4c76bb43a8..8ddedb160a 100644
--- a/activemodel/test/cases/errors_test.rb
+++ b/activemodel/test/cases/errors_test.rb
@@ -66,6 +66,63 @@ class ErrorsTest < ActiveModel::TestCase
assert_equal ["can not be blank"], person.errors[:name]
end
+ test "should be able to add an error with a symbol" do
+ person = Person.new
+ person.errors.add(:name, :blank)
+ message = person.errors.generate_message(:name, :blank)
+ assert_equal [message], person.errors[:name]
+ end
+
+ test "should be able to add an error with a proc" do
+ person = Person.new
+ message = Proc.new { "can not be blank" }
+ person.errors.add(:name, message)
+ assert_equal ["can not be blank"], person.errors[:name]
+ end
+
+ test "added? should be true if that error was added" do
+ person = Person.new
+ person.errors.add(:name, "can not be blank")
+ assert person.errors.added?(:name, "can not be blank")
+ end
+
+ test "added? should handle when message is a symbol" do
+ person = Person.new
+ person.errors.add(:name, :blank)
+ assert person.errors.added?(:name, :blank)
+ end
+
+ test "added? should handle when message is a proc" do
+ person = Person.new
+ message = Proc.new { "can not be blank" }
+ person.errors.add(:name, message)
+ assert person.errors.added?(:name, message)
+ end
+
+ test "added? should default message to :invalid" do
+ person = Person.new
+ person.errors.add(:name, :invalid)
+ assert person.errors.added?(:name)
+ end
+
+ test "added? should be true when several errors are present, and we ask for one of them" do
+ person = Person.new
+ person.errors.add(:name, "can not be blank")
+ person.errors.add(:name, "is invalid")
+ assert person.errors.added?(:name, "can not be blank")
+ end
+
+ test "added? should be false if no errors are present" do
+ person = Person.new
+ assert !person.errors.added?(:name)
+ end
+
+ test "added? should be false when an error is present, but we check for another error" do
+ person = Person.new
+ person.errors.add(:name, "is invalid")
+ assert !person.errors.added?(:name, "can not be blank")
+ end
+
test 'should respond to size' do
person = Person.new
person.errors.add(:name, "can not be blank")
@@ -112,5 +169,12 @@ class ErrorsTest < ActiveModel::TestCase
assert_equal ["is invalid"], hash[:email]
end
+ test "generate_message should work without i18n_scope" do
+ person = Person.new
+ assert !Person.respond_to?(:i18n_scope)
+ assert_nothing_raised {
+ person.errors.generate_message(:name, :blank)
+ }
+ end
end
diff --git a/activemodel/test/cases/naming_test.rb b/activemodel/test/cases/naming_test.rb
index 5f943729dd..a5ee2d6090 100644
--- a/activemodel/test/cases/naming_test.rb
+++ b/activemodel/test/cases/naming_test.rb
@@ -74,10 +74,6 @@ class NamingWithNamespacedModelInIsolatedNamespaceTest < ActiveModel::TestCase
def test_param_key
assert_equal 'post', @model_name.param_key
end
-
- def test_recognizing_namespace
- assert_equal 'Post', Blog::Post.model_name.instance_variable_get("@unnamespaced")
- end
end
class NamingWithNamespacedModelInSharedNamespaceTest < ActiveModel::TestCase
@@ -160,6 +156,40 @@ class NamingWithSuppliedModelNameTest < ActiveModel::TestCase
end
end
+class NamingUsingRelativeModelNameTest < ActiveModel::TestCase
+ def setup
+ @model_name = Blog::Post.model_name
+ end
+
+ def test_singular
+ assert_equal 'blog_post', @model_name.singular
+ end
+
+ def test_plural
+ assert_equal 'blog_posts', @model_name.plural
+ end
+
+ def test_element
+ assert_equal 'post', @model_name.element
+ end
+
+ def test_collection
+ assert_equal 'blog/posts', @model_name.collection
+ end
+
+ def test_human
+ assert_equal 'Post', @model_name.human
+ end
+
+ def test_route_key
+ assert_equal 'posts', @model_name.route_key
+ end
+
+ def test_param_key
+ assert_equal 'post', @model_name.param_key
+ end
+end
+
class NamingHelpersTest < Test::Unit::TestCase
def setup
@klass = Contact
diff --git a/activemodel/test/cases/secure_password_test.rb b/activemodel/test/cases/secure_password_test.rb
index 6950c3be1f..4338a3fc53 100644
--- a/activemodel/test/cases/secure_password_test.rb
+++ b/activemodel/test/cases/secure_password_test.rb
@@ -10,15 +10,13 @@ class SecurePasswordTest < ActiveModel::TestCase
end
test "blank password" do
- user = User.new
- user.password = ''
- assert !user.valid?, 'user should be invalid'
+ @user.password = ''
+ assert !@user.valid?, 'user should be invalid'
end
test "nil password" do
- user = User.new
- user.password = nil
- assert !user.valid?, 'user should be invalid'
+ @user.password = nil
+ assert !@user.valid?, 'user should be invalid'
end
test "password must be present" do
diff --git a/activemodel/test/cases/validations/exclusion_validation_test.rb b/activemodel/test/cases/validations/exclusion_validation_test.rb
index 72a383f128..adab8ccb2b 100644
--- a/activemodel/test/cases/validations/exclusion_validation_test.rb
+++ b/activemodel/test/cases/validations/exclusion_validation_test.rb
@@ -46,12 +46,12 @@ class ExclusionValidationTest < ActiveModel::TestCase
def test_validates_exclusion_of_with_lambda
Topic.validates_exclusion_of :title, :in => lambda{ |topic| topic.author_name == "sikachu" ? %w( monkey elephant ) : %w( abe wasabi ) }
- p = Topic.new
- p.title = "elephant"
- p.author_name = "sikachu"
- assert p.invalid?
+ t = Topic.new
+ t.title = "elephant"
+ t.author_name = "sikachu"
+ assert t.invalid?
- p.title = "wasabi"
- assert p.valid?
+ t.title = "wasabi"
+ assert t.valid?
end
end
diff --git a/activemodel/test/cases/validations/format_validation_test.rb b/activemodel/test/cases/validations/format_validation_test.rb
index 2ce714fef0..41a1131bcb 100644
--- a/activemodel/test/cases/validations/format_validation_test.rb
+++ b/activemodel/test/cases/validations/format_validation_test.rb
@@ -101,25 +101,25 @@ class PresenceValidationTest < ActiveModel::TestCase
def test_validates_format_of_with_lambda
Topic.validates_format_of :content, :with => lambda{ |topic| topic.title == "digit" ? /\A\d+\Z/ : /\A\S+\Z/ }
- p = Topic.new
- p.title = "digit"
- p.content = "Pixies"
- assert p.invalid?
+ t = Topic.new
+ t.title = "digit"
+ t.content = "Pixies"
+ assert t.invalid?
- p.content = "1234"
- assert p.valid?
+ t.content = "1234"
+ assert t.valid?
end
def test_validates_format_of_without_lambda
Topic.validates_format_of :content, :without => lambda{ |topic| topic.title == "characters" ? /\A\d+\Z/ : /\A\S+\Z/ }
- p = Topic.new
- p.title = "characters"
- p.content = "1234"
- assert p.invalid?
+ t = Topic.new
+ t.title = "characters"
+ t.content = "1234"
+ assert t.invalid?
- p.content = "Pixies"
- assert p.valid?
+ t.content = "Pixies"
+ assert t.valid?
end
def test_validates_format_of_for_ruby_class
diff --git a/activemodel/test/cases/validations/inclusion_validation_test.rb b/activemodel/test/cases/validations/inclusion_validation_test.rb
index 413da92de4..851d345eab 100644
--- a/activemodel/test/cases/validations/inclusion_validation_test.rb
+++ b/activemodel/test/cases/validations/inclusion_validation_test.rb
@@ -78,12 +78,12 @@ class InclusionValidationTest < ActiveModel::TestCase
def test_validates_inclusion_of_with_lambda
Topic.validates_inclusion_of :title, :in => lambda{ |topic| topic.author_name == "sikachu" ? %w( monkey elephant ) : %w( abe wasabi ) }
- p = Topic.new
- p.title = "wasabi"
- p.author_name = "sikachu"
- assert p.invalid?
+ t = Topic.new
+ t.title = "wasabi"
+ t.author_name = "sikachu"
+ assert t.invalid?
- p.title = "elephant"
- assert p.valid?
+ t.title = "elephant"
+ assert t.valid?
end
end
diff --git a/activemodel/test/models/blog_post.rb b/activemodel/test/models/blog_post.rb
index d289177259..46eba857df 100644
--- a/activemodel/test/models/blog_post.rb
+++ b/activemodel/test/models/blog_post.rb
@@ -1,10 +1,6 @@
module Blog
- def self._railtie
- Object.new
- end
-
- def self.table_name_prefix
- "blog_"
+ def self.use_relative_model_naming?
+ true
end
class Post