aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/test/cases
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel/test/cases')
-rw-r--r--activemodel/test/cases/attribute_methods_test.rb109
-rw-r--r--activemodel/test/cases/conversion_test.rb9
-rw-r--r--activemodel/test/cases/dirty_test.rb9
-rw-r--r--activemodel/test/cases/errors_test.rb38
-rw-r--r--activemodel/test/cases/helper.rb1
-rw-r--r--activemodel/test/cases/mass_assignment_security/black_list_test.rb8
-rw-r--r--activemodel/test/cases/mass_assignment_security/sanitizer_test.rb37
-rw-r--r--activemodel/test/cases/mass_assignment_security/white_list_test.rb9
-rw-r--r--activemodel/test/cases/mass_assignment_security_test.rb34
-rw-r--r--activemodel/test/cases/naming_test.rb53
-rw-r--r--activemodel/test/cases/observing_test.rb12
-rw-r--r--activemodel/test/cases/serialization_test.rb110
-rw-r--r--activemodel/test/cases/serializers/json_serialization_test.rb73
-rw-r--r--activemodel/test/cases/serializers/xml_serialization_test.rb77
-rw-r--r--activemodel/test/cases/validations/conditional_validation_test.rb24
-rw-r--r--activemodel/test/cases/validations/format_validation_test.rb2
-rw-r--r--activemodel/test/cases/validations/inclusion_validation_test.rb2
-rw-r--r--activemodel/test/cases/validations/length_validation_test.rb30
-rw-r--r--activemodel/test/cases/validations_test.rb33
19 files changed, 587 insertions, 83 deletions
diff --git a/activemodel/test/cases/attribute_methods_test.rb b/activemodel/test/cases/attribute_methods_test.rb
index 022c6716bd..67471ed497 100644
--- a/activemodel/test/cases/attribute_methods_test.rb
+++ b/activemodel/test/cases/attribute_methods_test.rb
@@ -3,8 +3,6 @@ require 'cases/helper'
class ModelWithAttributes
include ActiveModel::AttributeMethods
- attribute_method_suffix ''
-
class << self
define_method(:bar) do
'original bar'
@@ -24,14 +22,31 @@ end
class ModelWithAttributes2
include ActiveModel::AttributeMethods
+ attr_accessor :attributes
+
attribute_method_suffix '_test'
+
+private
+ def attribute(name)
+ attributes[name.to_s]
+ end
+
+ alias attribute_test attribute
+
+ def private_method
+ "<3 <3"
+ end
+
+protected
+
+ def protected_method
+ "O_o O_o"
+ end
end
class ModelWithAttributesWithSpaces
include ActiveModel::AttributeMethods
- attribute_method_suffix ''
-
def attributes
{ :'foo bar' => 'value of foo bar'}
end
@@ -45,8 +60,6 @@ end
class ModelWithWeirdNamesAttributes
include ActiveModel::AttributeMethods
- attribute_method_suffix ''
-
class << self
define_method(:'c?d') do
'original c?d'
@@ -76,9 +89,31 @@ class AttributeMethodsTest < ActiveModel::TestCase
assert_equal "value of foo", ModelWithAttributes.new.foo
end
+ test '#define_attribute_method does not generate attribute method if already defined in attribute module' do
+ klass = Class.new(ModelWithAttributes)
+ klass.generated_attribute_methods.module_eval do
+ def foo
+ '<3'
+ end
+ end
+ klass.define_attribute_method(:foo)
+
+ assert_equal '<3', klass.new.foo
+ end
+
+ test '#define_attribute_method generates a method that is already defined on the host' do
+ klass = Class.new(ModelWithAttributes) do
+ def foo
+ super
+ end
+ end
+ klass.define_attribute_method(:foo)
+
+ assert_equal 'value of foo', klass.new.foo
+ end
+
test '#define_attribute_method generates attribute method with invalid identifier characters' do
ModelWithWeirdNamesAttributes.define_attribute_method(:'a?b')
- ModelWithWeirdNamesAttributes.define_attribute_method(:'a?b')
assert_respond_to ModelWithWeirdNamesAttributes.new, :'a?b'
assert_equal "value of a?b", ModelWithWeirdNamesAttributes.new.send('a?b')
@@ -130,4 +165,64 @@ class AttributeMethodsTest < ActiveModel::TestCase
assert !ModelWithAttributes.new.respond_to?(:foo)
assert_raises(NoMethodError) { ModelWithAttributes.new.foo }
end
+
+ test 'acessing a suffixed attribute' do
+ m = ModelWithAttributes2.new
+ m.attributes = { 'foo' => 'bar' }
+
+ assert_equal 'bar', m.foo
+ assert_equal 'bar', m.foo_test
+ end
+
+ test 'explicitly specifying an empty prefix/suffix is deprecated' do
+ klass = Class.new(ModelWithAttributes)
+
+ assert_deprecated { klass.attribute_method_suffix '' }
+ assert_deprecated { klass.attribute_method_prefix '' }
+
+ klass.define_attribute_methods([:foo])
+
+ assert_equal 'value of foo', klass.new.foo
+ end
+
+ test 'should not interfere with method_missing if the attr has a private/protected method' do
+ m = ModelWithAttributes2.new
+ m.attributes = { 'private_method' => '<3', 'protected_method' => 'O_o' }
+
+ # dispatches to the *method*, not the attribute
+ assert_equal '<3 <3', m.send(:private_method)
+ assert_equal 'O_o O_o', m.send(:protected_method)
+
+ # sees that a method is already defined, so doesn't intervene
+ assert_raises(NoMethodError) { m.private_method }
+ assert_raises(NoMethodError) { m.protected_method }
+ end
+
+ test 'should not interfere with respond_to? if the attribute has a private/protected method' do
+ m = ModelWithAttributes2.new
+ m.attributes = { 'private_method' => '<3', 'protected_method' => 'O_o' }
+
+ assert !m.respond_to?(:private_method)
+ assert m.respond_to?(:private_method, true)
+
+ # This is messed up, but it's how Ruby works at the moment. Apparently it will be changed
+ # in the future.
+ assert m.respond_to?(:protected_method)
+ assert m.respond_to?(:protected_method, true)
+ end
+
+ test 'should use attribute_missing to dispatch a missing attribute' do
+ m = ModelWithAttributes2.new
+ m.attributes = { 'foo' => 'bar' }
+
+ def m.attribute_missing(match, *args, &block)
+ match
+ end
+
+ match = m.foo_test
+
+ assert_equal 'foo', match.attr_name
+ assert_equal 'attribute_test', match.target
+ assert_equal 'foo_test', match.method_name
+ end
end
diff --git a/activemodel/test/cases/conversion_test.rb b/activemodel/test/cases/conversion_test.rb
index 7669bf5f65..24552bcaf2 100644
--- a/activemodel/test/cases/conversion_test.rb
+++ b/activemodel/test/cases/conversion_test.rb
@@ -1,5 +1,6 @@
require 'cases/helper'
require 'models/contact'
+require 'models/helicopter'
class ConversionTest < ActiveModel::TestCase
test "to_model default implementation returns self" do
@@ -22,4 +23,10 @@ class ConversionTest < ActiveModel::TestCase
test "to_param default implementation returns a string of ids for persisted records" do
assert_equal "1", Contact.new(:id => 1).to_param
end
-end \ No newline at end of file
+
+ test "to_path default implementation returns a string giving a relative path" do
+ assert_equal "contacts/contact", Contact.new.to_partial_path
+ assert_equal "helicopters/helicopter", Helicopter.new.to_partial_path,
+ "ActiveModel::Conversion#to_partial_path caching should be class-specific"
+ end
+end
diff --git a/activemodel/test/cases/dirty_test.rb b/activemodel/test/cases/dirty_test.rb
index 858ae9cb69..98244a6290 100644
--- a/activemodel/test/cases/dirty_test.rb
+++ b/activemodel/test/cases/dirty_test.rb
@@ -106,4 +106,13 @@ class DirtyTest < ActiveModel::TestCase
assert_equal [nil, "Jericho Cane"], @model.previous_changes['name']
end
+ test "changing the same attribute multiple times retains the correct original value" do
+ @model.name = "Otto"
+ @model.save
+ @model.name = "DudeFella ManGuy"
+ @model.name = "Mr. Manfredgensonton"
+ assert_equal ["Otto", "Mr. Manfredgensonton"], @model.name_change
+ assert_equal @model.name_was, "Otto"
+ end
+
end
diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb
index a24cac40ad..4c76bb43a8 100644
--- a/activemodel/test/cases/errors_test.rb
+++ b/activemodel/test/cases/errors_test.rb
@@ -33,11 +33,18 @@ class ErrorsTest < ActiveModel::TestCase
assert errors.include?(:foo), 'errors should include :foo'
end
+ def test_has_key?
+ errors = ActiveModel::Errors.new(self)
+ errors[:foo] = 'omg'
+ assert errors.has_key?(:foo), 'errors should have key :foo'
+ end
+
test "should return true if no errors" do
person = Person.new
person.errors[:foo]
assert person.errors.empty?
assert person.errors.blank?
+ assert !person.errors.include?(:foo)
end
test "method validate! should work" do
@@ -45,7 +52,6 @@ class ErrorsTest < ActiveModel::TestCase
person.validate!
assert_equal ["name can not be nil"], person.errors.full_messages
assert_equal ["can not be nil"], person.errors[:name]
-
end
test 'should be able to assign error' do
@@ -71,7 +77,6 @@ class ErrorsTest < ActiveModel::TestCase
person.errors.add(:name, "can not be blank")
person.errors.add(:name, "can not be nil")
assert_equal ["name can not be blank", "name can not be nil"], person.errors.to_a
-
end
test 'to_hash should return an ordered hash' do
@@ -79,4 +84,33 @@ class ErrorsTest < ActiveModel::TestCase
person.errors.add(:name, "can not be blank")
assert_instance_of ActiveSupport::OrderedHash, person.errors.to_hash
end
+
+ test 'full_messages should return an array of error messages, with the attribute name included' do
+ person = Person.new
+ person.errors.add(:name, "can not be blank")
+ person.errors.add(:name, "can not be nil")
+ assert_equal ["name can not be blank", "name can not be nil"], person.errors.to_a
+ end
+
+ test 'full_message should return the given message if attribute equals :base' do
+ person = Person.new
+ assert_equal "press the button", person.errors.full_message(:base, "press the button")
+ end
+
+ test 'full_message should return the given message with the attribute name included' do
+ person = Person.new
+ assert_equal "name can not be blank", person.errors.full_message(:name, "can not be blank")
+ end
+
+ test 'should return a JSON hash representation of the errors' do
+ person = Person.new
+ person.errors.add(:name, "can not be blank")
+ person.errors.add(:name, "can not be nil")
+ person.errors.add(:email, "is invalid")
+ hash = person.errors.as_json
+ assert_equal ["can not be blank", "can not be nil"], hash[:name]
+ assert_equal ["is invalid"], hash[:email]
+ end
+
end
+
diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb
index 01f0158678..2e860272a4 100644
--- a/activemodel/test/cases/helper.rb
+++ b/activemodel/test/cases/helper.rb
@@ -10,5 +10,4 @@ require 'active_support/core_ext/string/access'
# Show backtraces for deprecated behavior for quicker cleanup.
ActiveSupport::Deprecation.debug = true
-require 'rubygems'
require 'test/unit'
diff --git a/activemodel/test/cases/mass_assignment_security/black_list_test.rb b/activemodel/test/cases/mass_assignment_security/black_list_test.rb
index ed168bc016..0ec7f8719c 100644
--- a/activemodel/test/cases/mass_assignment_security/black_list_test.rb
+++ b/activemodel/test/cases/mass_assignment_security/black_list_test.rb
@@ -16,13 +16,5 @@ class BlackListTest < ActiveModel::TestCase
assert_equal false, @black_list.deny?('first_name')
end
- test "sanitize attributes" do
- original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied', 'admin(1)' => 'denied' }
- attributes = @black_list.sanitize(original_attributes)
-
- assert attributes.key?('first_name'), "Allowed key shouldn't be rejected"
- assert !attributes.key?('admin'), "Denied key should be rejected"
- assert !attributes.key?('admin(1)'), "Multi-parameter key should be detected"
- end
end
diff --git a/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb
index 9a73a5ad91..676937b5e1 100644
--- a/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb
+++ b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb
@@ -3,36 +3,49 @@ require 'logger'
require 'active_support/core_ext/object/inclusion'
class SanitizerTest < ActiveModel::TestCase
+ attr_accessor :logger
- class SanitizingAuthorizer
- include ActiveModel::MassAssignmentSecurity::Sanitizer
-
- attr_accessor :logger
-
+ class Authorizer < ActiveModel::MassAssignmentSecurity::PermissionSet
def deny?(key)
- key.in?(['admin'])
+ ['admin', 'id'].include?(key)
end
-
end
def setup
- @sanitizer = SanitizingAuthorizer.new
+ @logger_sanitizer = ActiveModel::MassAssignmentSecurity::LoggerSanitizer.new(self)
+ @strict_sanitizer = ActiveModel::MassAssignmentSecurity::StrictSanitizer.new(self)
+ @authorizer = Authorizer.new
end
test "sanitize attributes" do
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
- attributes = @sanitizer.sanitize(original_attributes)
+ attributes = @logger_sanitizer.sanitize(original_attributes, @authorizer)
assert attributes.key?('first_name'), "Allowed key shouldn't be rejected"
assert !attributes.key?('admin'), "Denied key should be rejected"
end
- test "debug mass assignment removal" do
+ test "debug mass assignment removal with LoggerSanitizer" do
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
log = StringIO.new
- @sanitizer.logger = Logger.new(log)
- @sanitizer.sanitize(original_attributes)
+ self.logger = Logger.new(log)
+ @logger_sanitizer.sanitize(original_attributes, @authorizer)
assert_match(/admin/, log.string, "Should log removed attributes: #{log.string}")
end
+ test "debug mass assignment removal with StrictSanitizer" do
+ original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
+ assert_raise ActiveModel::MassAssignmentSecurity::Error do
+ @strict_sanitizer.sanitize(original_attributes, @authorizer)
+ end
+ end
+
+ test "mass assignment insensitive attributes" do
+ original_attributes = {'id' => 1, 'first_name' => 'allowed'}
+
+ assert_nothing_raised do
+ @strict_sanitizer.sanitize(original_attributes, @authorizer)
+ end
+ end
+
end
diff --git a/activemodel/test/cases/mass_assignment_security/white_list_test.rb b/activemodel/test/cases/mass_assignment_security/white_list_test.rb
index aa3596ad2a..737b55492a 100644
--- a/activemodel/test/cases/mass_assignment_security/white_list_test.rb
+++ b/activemodel/test/cases/mass_assignment_security/white_list_test.rb
@@ -16,13 +16,4 @@ class WhiteListTest < ActiveModel::TestCase
assert_equal true, @white_list.deny?('admin')
end
- test "sanitize attributes" do
- original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied', 'admin(1)' => 'denied' }
- attributes = @white_list.sanitize(original_attributes)
-
- assert attributes.key?('first_name'), "Allowed key shouldn't be rejected"
- assert !attributes.key?('admin'), "Denied key should be rejected"
- assert !attributes.key?('admin(1)'), "Multi-parameter key should be detected"
- end
-
end
diff --git a/activemodel/test/cases/mass_assignment_security_test.rb b/activemodel/test/cases/mass_assignment_security_test.rb
index 43a12eed61..be07e59a2f 100644
--- a/activemodel/test/cases/mass_assignment_security_test.rb
+++ b/activemodel/test/cases/mass_assignment_security_test.rb
@@ -1,6 +1,15 @@
require "cases/helper"
require 'models/mass_assignment_specific'
+
+class CustomSanitizer < ActiveModel::MassAssignmentSecurity::Sanitizer
+
+ def process_removed_attributes(attrs)
+ raise StandardError
+ end
+
+end
+
class MassAssignmentSecurityTest < ActiveModel::TestCase
def test_attribute_protection
@@ -34,6 +43,20 @@ class MassAssignmentSecurityTest < ActiveModel::TestCase
assert_equal expected, sanitized
end
+ def test_attributes_accessible_with_roles_given_as_array
+ user = Account.new
+ expected = { "name" => "John Smith", "email" => "john@smith.com" }
+ sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true))
+ assert_equal expected, sanitized
+ end
+
+ def test_attributes_accessible_with_admin_role_when_roles_given_as_array
+ user = Account.new
+ expected = { "name" => "John Smith", "email" => "john@smith.com", "admin" => true }
+ sanitized = user.sanitize_for_mass_assignment(expected.merge("super_powers" => true), :admin)
+ assert_equal expected, sanitized
+ end
+
def test_attributes_protected_by_default
firm = Firm.new
expected = { }
@@ -76,4 +99,15 @@ class MassAssignmentSecurityTest < ActiveModel::TestCase
assert_equal sanitized, { }
end
+ def test_custom_sanitizer
+ user = User.new
+ User.mass_assignment_sanitizer = CustomSanitizer.new
+ assert_raise StandardError do
+ user.sanitize_for_mass_assignment("admin" => true)
+ end
+ ensure
+ User.mass_assignment_sanitizer = nil
+
+ end
+
end
diff --git a/activemodel/test/cases/naming_test.rb b/activemodel/test/cases/naming_test.rb
index a7dde2c433..5f943729dd 100644
--- a/activemodel/test/cases/naming_test.rb
+++ b/activemodel/test/cases/naming_test.rb
@@ -26,7 +26,9 @@ class NamingTest < ActiveModel::TestCase
end
def test_partial_path
- assert_equal 'post/track_backs/track_back', @model_name.partial_path
+ assert_deprecated(/#partial_path.*#to_partial_path/) do
+ assert_equal 'post/track_backs/track_back', @model_name.partial_path
+ end
end
def test_human
@@ -56,7 +58,9 @@ class NamingWithNamespacedModelInIsolatedNamespaceTest < ActiveModel::TestCase
end
def test_partial_path
- assert_equal 'blog/posts/post', @model_name.partial_path
+ assert_deprecated(/#partial_path.*#to_partial_path/) do
+ assert_equal 'blog/posts/post', @model_name.partial_path
+ end
end
def test_human
@@ -98,7 +102,9 @@ class NamingWithNamespacedModelInSharedNamespaceTest < ActiveModel::TestCase
end
def test_partial_path
- assert_equal 'blog/posts/post', @model_name.partial_path
+ assert_deprecated(/#partial_path.*#to_partial_path/) do
+ assert_equal 'blog/posts/post', @model_name.partial_path
+ end
end
def test_human
@@ -114,6 +120,46 @@ class NamingWithNamespacedModelInSharedNamespaceTest < ActiveModel::TestCase
end
end
+class NamingWithSuppliedModelNameTest < ActiveModel::TestCase
+ def setup
+ @model_name = ActiveModel::Name.new(Blog::Post, nil, 'Article')
+ end
+
+ def test_singular
+ assert_equal 'article', @model_name.singular
+ end
+
+ def test_plural
+ assert_equal 'articles', @model_name.plural
+ end
+
+ def test_element
+ assert_equal 'article', @model_name.element
+ end
+
+ def test_collection
+ assert_equal 'articles', @model_name.collection
+ end
+
+ def test_partial_path
+ assert_deprecated(/#partial_path.*#to_partial_path/) do
+ assert_equal 'articles/article', @model_name.partial_path
+ end
+ end
+
+ def test_human
+ assert_equal 'Article', @model_name.human
+ end
+
+ def test_route_key
+ assert_equal 'articles', @model_name.route_key
+ end
+
+ def test_param_key
+ assert_equal 'article', @model_name.param_key
+ end
+end
+
class NamingHelpersTest < Test::Unit::TestCase
def setup
@klass = Contact
@@ -171,4 +217,3 @@ class NamingHelpersTest < Test::Unit::TestCase
ActiveModel::Naming.send(method, *args)
end
end
-
diff --git a/activemodel/test/cases/observing_test.rb b/activemodel/test/cases/observing_test.rb
index 99b1f407ae..f6ec24ae57 100644
--- a/activemodel/test/cases/observing_test.rb
+++ b/activemodel/test/cases/observing_test.rb
@@ -17,6 +17,10 @@ class FooObserver < ActiveModel::Observer
def on_spec(record)
stub.event_with(record) if stub
end
+
+ def around_save(record)
+ yield :in_around_save
+ end
end
class Foo
@@ -133,4 +137,12 @@ class ObserverTest < ActiveModel::TestCase
foo = Foo.new
Foo.send(:notify_observers, :whatever, foo)
end
+
+ test "update passes a block on to the observer" do
+ yielded_value = nil
+ FooObserver.instance.update(:around_save, Foo.new) do |val|
+ yielded_value = val
+ end
+ assert_equal :in_around_save, yielded_value
+ end
end
diff --git a/activemodel/test/cases/serialization_test.rb b/activemodel/test/cases/serialization_test.rb
index 8cc1ccb1e7..1ec915d245 100644
--- a/activemodel/test/cases/serialization_test.rb
+++ b/activemodel/test/cases/serialization_test.rb
@@ -1,13 +1,19 @@
require "cases/helper"
+require 'active_support/core_ext/object/instance_variables'
class SerializationTest < ActiveModel::TestCase
class User
include ActiveModel::Serialization
- attr_accessor :name, :email, :gender
+ attr_accessor :name, :email, :gender, :address, :friends
+
+ def initialize(name, email, gender)
+ @name, @email, @gender = name, email, gender
+ @friends = []
+ end
def attributes
- @attributes ||= {'name' => 'nil', 'email' => 'nil', 'gender' => 'nil'}
+ instance_values.except("address", "friends")
end
def foo
@@ -15,11 +21,25 @@ class SerializationTest < ActiveModel::TestCase
end
end
+ class Address
+ include ActiveModel::Serialization
+
+ attr_accessor :street, :city, :state, :zip
+
+ def attributes
+ instance_values
+ end
+ end
+
setup do
- @user = User.new
- @user.name = 'David'
- @user.email = 'david@example.com'
- @user.gender = 'male'
+ @user = User.new('David', 'david@example.com', 'male')
+ @user.address = Address.new
+ @user.address.street = "123 Lane"
+ @user.address.city = "Springfield"
+ @user.address.state = "CA"
+ @user.address.zip = 11111
+ @user.friends = [User.new('Joe', 'joe@example.com', 'male'),
+ User.new('Sue', 'sue@example.com', 'female')]
end
def test_method_serializable_hash_should_work
@@ -42,4 +62,82 @@ class SerializationTest < ActiveModel::TestCase
assert_equal expected , @user.serializable_hash(:methods => [:foo])
end
+ def test_method_serializable_hash_should_work_with_only_and_methods
+ expected = {:foo=>"i_am_foo"}
+ assert_equal expected , @user.serializable_hash(:only => [], :methods => [:foo])
+ end
+
+ def test_method_serializable_hash_should_work_with_except_and_methods
+ expected = {"gender"=>"male", :foo=>"i_am_foo"}
+ assert_equal expected , @user.serializable_hash(:except => [:name, :email], :methods => [:foo])
+ end
+
+ def test_should_not_call_methods_that_dont_respond
+ expected = {"name"=>"David", "gender"=>"male", "email"=>"david@example.com"}
+ assert_equal expected , @user.serializable_hash(:methods => [:bar])
+ end
+
+ def test_should_use_read_attribute_for_serialization
+ def @user.read_attribute_for_serialization(n)
+ "Jon"
+ end
+
+ expected = { "name" => "Jon" }
+ assert_equal expected, @user.serializable_hash(:only => :name)
+ end
+
+ def test_include_option_with_singular_association
+ expected = {"name"=>"David", "gender"=>"male", "email"=>"david@example.com",
+ :address=>{"street"=>"123 Lane", "city"=>"Springfield", "state"=>"CA", "zip"=>11111}}
+ assert_equal expected , @user.serializable_hash(:include => :address)
+ end
+
+ def test_include_option_with_plural_association
+ expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David",
+ :friends=>[{"name"=>'Joe', "email"=>'joe@example.com', "gender"=>'male'},
+ {"name"=>'Sue', "email"=>'sue@example.com', "gender"=>'female'}]}
+ assert_equal expected , @user.serializable_hash(:include => :friends)
+ end
+
+ def test_include_option_with_empty_association
+ @user.friends = []
+ expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David", :friends=>[]}
+ assert_equal expected , @user.serializable_hash(:include => :friends)
+ end
+
+ def test_multiple_includes
+ expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David",
+ :address=>{"street"=>"123 Lane", "city"=>"Springfield", "state"=>"CA", "zip"=>11111},
+ :friends=>[{"name"=>'Joe', "email"=>'joe@example.com', "gender"=>'male'},
+ {"name"=>'Sue', "email"=>'sue@example.com', "gender"=>'female'}]}
+ assert_equal expected , @user.serializable_hash(:include => [:address, :friends])
+ end
+
+ def test_include_with_options
+ expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David",
+ :address=>{"street"=>"123 Lane"}}
+ assert_equal expected , @user.serializable_hash(:include => {:address => {:only => "street"}})
+ end
+
+ def test_nested_include
+ @user.friends.first.friends = [@user]
+ expected = {"email"=>"david@example.com", "gender"=>"male", "name"=>"David",
+ :friends=>[{"name"=>'Joe', "email"=>'joe@example.com', "gender"=>'male',
+ :friends => [{"email"=>"david@example.com", "gender"=>"male", "name"=>"David"}]},
+ {"name"=>'Sue', "email"=>'sue@example.com', "gender"=>'female', :friends => []}]}
+ assert_equal expected , @user.serializable_hash(:include => {:friends => {:include => :friends}})
+ end
+
+ def test_only_include
+ expected = {"name"=>"David", :friends => [{"name" => "Joe"}, {"name" => "Sue"}]}
+ assert_equal expected , @user.serializable_hash(:only => :name, :include => {:friends => {:only => :name}})
+ end
+
+ def test_except_include
+ expected = {"name"=>"David", "email"=>"david@example.com",
+ :friends => [{"name" => 'Joe', "email" => 'joe@example.com'},
+ {"name" => "Sue", "email" => 'sue@example.com'}]}
+ assert_equal expected , @user.serializable_hash(:except => :gender, :include => {:friends => {:except => :gender}})
+ end
+
end
diff --git a/activemodel/test/cases/serializers/json_serialization_test.rb b/activemodel/test/cases/serializers/json_serialization_test.rb
index 500a5c575f..a754d610b9 100644
--- a/activemodel/test/cases/serializers/json_serialization_test.rb
+++ b/activemodel/test/cases/serializers/json_serialization_test.rb
@@ -8,6 +8,12 @@ class Contact
include ActiveModel::Serializers::JSON
include ActiveModel::Validations
+ def attributes=(hash)
+ hash.each do |k, v|
+ instance_variable_set("@#{k}", v)
+ end
+ end
+
def attributes
instance_values
end unless method_defined?(:attributes)
@@ -34,7 +40,7 @@ class JsonSerializationTest < ActiveModel::TestCase
assert_match %r{"preferences":\{"shows":"anime"\}}, json
end
- test "should not include root in json" do
+ test "should not include root in json (class method)" do
begin
Contact.include_root_in_json = false
json = @contact.to_json
@@ -50,6 +56,23 @@ class JsonSerializationTest < ActiveModel::TestCase
end
end
+ test "should include root in json (option) even if the default is set to false" do
+ begin
+ Contact.include_root_in_json = false
+ json = @contact.to_json(:root => true)
+ assert_match %r{^\{"contact":\{}, json
+ ensure
+ Contact.include_root_in_json = true
+ end
+ end
+
+ test "should not include root in json (option)" do
+
+ json = @contact.to_json(:root => false)
+
+ assert_no_match %r{^\{"contact":\{}, json
+ end
+
test "should include custom root in json" do
json = @contact.to_json(:root => 'json_contact')
@@ -135,6 +158,44 @@ class JsonSerializationTest < ActiveModel::TestCase
end
end
+ test "from_json should set the object's attributes" do
+ json = @contact.to_json
+ result = Contact.new.from_json(json)
+
+ assert_equal result.name, @contact.name
+ assert_equal result.age, @contact.age
+ assert_equal Time.parse(result.created_at), @contact.created_at
+ assert_equal result.awesome, @contact.awesome
+ assert_equal result.preferences, @contact.preferences
+ end
+
+ test "from_json should work without a root (method parameter)" do
+ json = @contact.to_json(:root => false)
+ result = Contact.new.from_json(json, false)
+
+ assert_equal result.name, @contact.name
+ assert_equal result.age, @contact.age
+ assert_equal Time.parse(result.created_at), @contact.created_at
+ assert_equal result.awesome, @contact.awesome
+ assert_equal result.preferences, @contact.preferences
+ end
+
+ test "from_json should work without a root (class attribute)" do
+ begin
+ Contact.include_root_in_json = false
+ json = @contact.to_json
+ result = Contact.new.from_json(json)
+
+ assert_equal result.name, @contact.name
+ assert_equal result.age, @contact.age
+ assert_equal Time.parse(result.created_at), @contact.created_at
+ assert_equal result.awesome, @contact.awesome
+ assert_equal result.preferences, @contact.preferences
+ ensure
+ Contact.include_root_in_json = true
+ end
+ end
+
test "custom as_json should be honored when generating json" do
def @contact.as_json(options); { :name => name, :created_at => created_at }; end
json = @contact.to_json
@@ -145,4 +206,14 @@ class JsonSerializationTest < ActiveModel::TestCase
assert_no_match %r{"preferences":}, json
end
+ test "custom as_json options should be extendible" do
+ def @contact.as_json(options = {}); super(options.merge(:only => [:name])); end
+ json = @contact.to_json
+
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_no_match %r{"created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}}, json
+ assert_no_match %r{"awesome":}, json
+ assert_no_match %r{"preferences":}, json
+ end
+
end
diff --git a/activemodel/test/cases/serializers/xml_serialization_test.rb b/activemodel/test/cases/serializers/xml_serialization_test.rb
index 8f5c196850..fc73d9dcd8 100644
--- a/activemodel/test/cases/serializers/xml_serialization_test.rb
+++ b/activemodel/test/cases/serializers/xml_serialization_test.rb
@@ -7,9 +7,11 @@ class Contact
extend ActiveModel::Naming
include ActiveModel::Serializers::Xml
+ attr_accessor :address, :friends
+
def attributes
- instance_values
- end unless method_defined?(:attributes)
+ instance_values.except("address", "friends")
+ end
end
module Admin
@@ -20,6 +22,23 @@ end
class Customer < Struct.new(:name)
end
+class Address
+ extend ActiveModel::Naming
+ include ActiveModel::Serializers::Xml
+
+ attr_accessor :street, :city, :state, :zip
+
+ def attributes
+ instance_values
+ end
+end
+
+class SerializableContact < Contact
+ def serializable_hash(options={})
+ super(options.merge(:only => [:name, :age]))
+ end
+end
+
class XmlSerializationTest < ActiveModel::TestCase
def setup
@contact = Contact.new
@@ -30,6 +49,12 @@ class XmlSerializationTest < ActiveModel::TestCase
customer = Customer.new
customer.name = "John"
@contact.preferences = customer
+ @contact.address = Address.new
+ @contact.address.street = "123 Lane"
+ @contact.address.city = "Springfield"
+ @contact.address.state = "CA"
+ @contact.address.zip = 11111
+ @contact.friends = [Contact.new, Contact.new]
end
test "should serialize default root" do
@@ -77,6 +102,17 @@ class XmlSerializationTest < ActiveModel::TestCase
assert_match %r{<createdAt}, @xml
end
+ test "should use serialiable hash" do
+ @contact = SerializableContact.new
+ @contact.name = 'aaron stack'
+ @contact.age = 25
+
+ @xml = @contact.to_xml
+ assert_match %r{<name>aaron stack</name>}, @xml
+ assert_match %r{<age type="integer">25</age>}, @xml
+ assert_no_match %r{<awesome>}, @xml
+ end
+
test "should allow skipped types" do
@xml = @contact.to_xml :skip_types => true
assert_match %r{<age>25</age>}, @xml
@@ -92,7 +128,7 @@ class XmlSerializationTest < ActiveModel::TestCase
test "should serialize string" do
assert_match %r{<name>aaron stack</name>}, @contact.to_xml
end
-
+
test "should serialize nil" do
assert_match %r{<pseudonyms nil=\"true\"></pseudonyms>}, @contact.to_xml(:methods => :pseudonyms)
end
@@ -132,4 +168,39 @@ class XmlSerializationTest < ActiveModel::TestCase
xml = @contact.to_xml(:procs => [ proc ])
assert_match %r{<name-reverse>kcats noraa</name-reverse>}, xml
end
+
+ test "should serialize string correctly when type passed" do
+ xml = @contact.to_xml :type => 'Contact'
+ assert_match %r{<contact type="Contact">}, xml
+ assert_match %r{<name>aaron stack</name>}, xml
+ end
+
+ test "include option with singular association" do
+ xml = @contact.to_xml :include => :address, :indent => 0
+ assert xml.include?(@contact.address.to_xml(:indent => 0, :skip_instruct => true))
+ end
+
+ test "include option with plural association" do
+ xml = @contact.to_xml :include => :friends, :indent => 0
+ assert_match %r{<friends type="array">}, xml
+ assert_match %r{<friend type="Contact">}, xml
+ end
+
+ test "multiple includes" do
+ xml = @contact.to_xml :indent => 0, :skip_instruct => true, :include => [ :address, :friends ]
+ assert xml.include?(@contact.address.to_xml(:indent => 0, :skip_instruct => true))
+ assert_match %r{<friends type="array">}, xml
+ assert_match %r{<friend type="Contact">}, xml
+ end
+
+ test "include with options" do
+ xml = @contact.to_xml :indent => 0, :skip_instruct => true, :include => { :address => { :only => :city } }
+ assert xml.include?(%(><address><city>Springfield</city></address>))
+ end
+
+ test "propagates skip_types option to included associations" do
+ xml = @contact.to_xml :include => :friends, :indent => 0, :skip_types => true
+ assert_match %r{<friends>}, xml
+ assert_match %r{<friend>}, xml
+ end
end
diff --git a/activemodel/test/cases/validations/conditional_validation_test.rb b/activemodel/test/cases/validations/conditional_validation_test.rb
index 3cb95b4a00..e06b04af19 100644
--- a/activemodel/test/cases/validations/conditional_validation_test.rb
+++ b/activemodel/test/cases/validations/conditional_validation_test.rb
@@ -11,7 +11,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_if_validation_using_method_true
# When the method returns true
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :if => :condition_is_true )
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}", :if => :condition_is_true )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -20,7 +20,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_unless_validation_using_method_true
# When the method returns true
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :unless => :condition_is_true )
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}", :unless => :condition_is_true )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
assert t.errors[:title].empty?
@@ -28,7 +28,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_if_validation_using_method_false
# When the method returns false
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :if => :condition_is_true_but_its_not )
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}", :if => :condition_is_true_but_its_not )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
assert t.errors[:title].empty?
@@ -36,7 +36,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_unless_validation_using_method_false
# When the method returns false
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :unless => :condition_is_true_but_its_not )
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}", :unless => :condition_is_true_but_its_not )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -45,7 +45,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_if_validation_using_string_true
# When the evaluated string returns true
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :if => "a = 1; a == 1" )
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}", :if => "a = 1; a == 1" )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -54,7 +54,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_unless_validation_using_string_true
# When the evaluated string returns true
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :unless => "a = 1; a == 1" )
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}", :unless => "a = 1; a == 1" )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
assert t.errors[:title].empty?
@@ -62,7 +62,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_if_validation_using_string_false
# When the evaluated string returns false
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :if => "false")
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}", :if => "false")
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
assert t.errors[:title].empty?
@@ -70,7 +70,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_unless_validation_using_string_false
# When the evaluated string returns false
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :unless => "false")
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}", :unless => "false")
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -79,7 +79,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_if_validation_using_block_true
# When the block returns true
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}",
:if => Proc.new { |r| r.content.size > 4 } )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
@@ -89,7 +89,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_unless_validation_using_block_true
# When the block returns true
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}",
:unless => Proc.new { |r| r.content.size > 4 } )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
@@ -98,7 +98,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_if_validation_using_block_false
# When the block returns false
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}",
:if => Proc.new { |r| r.title != "uhohuhoh"} )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
@@ -107,7 +107,7 @@ class ConditionalValidationTest < ActiveModel::TestCase
def test_unless_validation_using_block_false
# When the block returns false
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}",
:unless => Proc.new { |r| r.title != "uhohuhoh"} )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
diff --git a/activemodel/test/cases/validations/format_validation_test.rb b/activemodel/test/cases/validations/format_validation_test.rb
index 73647efea5..2ce714fef0 100644
--- a/activemodel/test/cases/validations/format_validation_test.rb
+++ b/activemodel/test/cases/validations/format_validation_test.rb
@@ -27,7 +27,7 @@ class PresenceValidationTest < ActiveModel::TestCase
end
def test_validate_format_with_allow_blank
- Topic.validates_format_of(:title, :with => /^Validation\smacros \w+!$/, :allow_blank=>true)
+ Topic.validates_format_of(:title, :with => /^Validation\smacros \w+!$/, :allow_blank => true)
assert Topic.new("title" => "Shouldn't be valid").invalid?
assert Topic.new("title" => "").valid?
assert Topic.new("title" => nil).valid?
diff --git a/activemodel/test/cases/validations/inclusion_validation_test.rb b/activemodel/test/cases/validations/inclusion_validation_test.rb
index 92c473de0e..413da92de4 100644
--- a/activemodel/test/cases/validations/inclusion_validation_test.rb
+++ b/activemodel/test/cases/validations/inclusion_validation_test.rb
@@ -42,7 +42,7 @@ class InclusionValidationTest < ActiveModel::TestCase
end
def test_validates_inclusion_of_with_allow_nil
- Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ), :allow_nil=>true )
+ Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ), :allow_nil => true )
assert Topic.new("title" => "a!", "content" => "abc").invalid?
assert Topic.new("title" => "", "content" => "abc").invalid?
diff --git a/activemodel/test/cases/validations/length_validation_test.rb b/activemodel/test/cases/validations/length_validation_test.rb
index f02514639b..44048a9c1d 100644
--- a/activemodel/test/cases/validations/length_validation_test.rb
+++ b/activemodel/test/cases/validations/length_validation_test.rb
@@ -11,7 +11,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_with_allow_nil
- Topic.validates_length_of( :title, :is => 5, :allow_nil=>true )
+ Topic.validates_length_of( :title, :is => 5, :allow_nil => true )
assert Topic.new("title" => "ab").invalid?
assert Topic.new("title" => "").invalid?
@@ -20,7 +20,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_with_allow_blank
- Topic.validates_length_of( :title, :is => 5, :allow_blank=>true )
+ Topic.validates_length_of( :title, :is => 5, :allow_blank => true )
assert Topic.new("title" => "ab").invalid?
assert Topic.new("title" => "").valid?
@@ -176,16 +176,16 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_nasty_params
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :is=>-6) }
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6) }
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :minimum=>"a") }
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :maximum=>"a") }
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>"a") }
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :is=>"a") }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :is => -6) }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within => 6) }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :minimum => "a") }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :maximum => "a") }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within => "a") }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :is => "a") }
end
def test_validates_length_of_custom_errors_for_minimum_with_message
- Topic.validates_length_of( :title, :minimum=>5, :message=>"boo %{count}" )
+ Topic.validates_length_of( :title, :minimum => 5, :message => "boo %{count}" )
t = Topic.new("title" => "uhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -193,7 +193,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_custom_errors_for_minimum_with_too_short
- Topic.validates_length_of( :title, :minimum=>5, :too_short=>"hoo %{count}" )
+ Topic.validates_length_of( :title, :minimum => 5, :too_short => "hoo %{count}" )
t = Topic.new("title" => "uhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -201,7 +201,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_custom_errors_for_maximum_with_message
- Topic.validates_length_of( :title, :maximum=>5, :message=>"boo %{count}" )
+ Topic.validates_length_of( :title, :maximum => 5, :message => "boo %{count}" )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -222,7 +222,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_custom_errors_for_maximum_with_too_long
- Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}" )
+ Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}" )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -244,7 +244,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_custom_errors_for_is_with_message
- Topic.validates_length_of( :title, :is=>5, :message=>"boo %{count}" )
+ Topic.validates_length_of( :title, :is => 5, :message => "boo %{count}" )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -252,7 +252,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_custom_errors_for_is_with_wrong_length
- Topic.validates_length_of( :title, :is=>5, :wrong_length=>"hoo %{count}" )
+ Topic.validates_length_of( :title, :is => 5, :wrong_length => "hoo %{count}" )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -331,7 +331,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_with_block
- Topic.validates_length_of :content, :minimum => 5, :too_short=>"Your essay must be at least %{count} words.",
+ Topic.validates_length_of :content, :minimum => 5, :too_short => "Your essay must be at least %{count} words.",
:tokenizer => lambda {|str| str.scan(/\w+/) }
t = Topic.new(:content => "this content should be long enough")
assert t.valid?
diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb
index 0b50acf913..2f4376bd41 100644
--- a/activemodel/test/cases/validations_test.rb
+++ b/activemodel/test/cases/validations_test.rb
@@ -297,4 +297,37 @@ class ValidationsTest < ActiveModel::TestCase
assert auto.valid?
end
+
+ def test_strict_validation_in_validates
+ Topic.validates :title, :strict => true, :presence => true
+ assert_raises ActiveModel::StrictValidationFailed do
+ Topic.new.valid?
+ end
+ end
+
+ def test_strict_validation_not_fails
+ Topic.validates :title, :strict => true, :presence => true
+ assert Topic.new(:title => "hello").valid?
+ end
+
+ def test_strict_validation_particular_validator
+ Topic.validates :title, :presence => {:strict => true}
+ assert_raises ActiveModel::StrictValidationFailed do
+ Topic.new.valid?
+ end
+ end
+
+ def test_strict_validation_in_custom_validator_helper
+ Topic.validates_presence_of :title, :strict => true
+ assert_raises ActiveModel::StrictValidationFailed do
+ Topic.new.valid?
+ end
+ end
+
+ def test_validates_with_bang
+ Topic.validates! :title, :presence => true
+ assert_raises ActiveModel::StrictValidationFailed do
+ Topic.new.valid?
+ end
+ end
end