Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge remote branch 'rails/master'

  • Loading branch information...
commit e1a0d86fe0355ddff8c86db0f42f3824ffe14c02 2 parents 1ff3d95 + df508bd
@fxn fxn authored
Showing with 1,065 additions and 1,013 deletions.
  1. +1 −1  actionpack/lib/action_dispatch/middleware/params_parser.rb
  2. +13 −0 actionpack/test/dispatch/request/xml_params_parsing_test.rb
  3. +5 −0 activemodel/CHANGELOG
  4. +5 −1 activemodel/lib/active_model/serializers/json.rb
  5. +12 −5 activemodel/lib/active_model/validations.rb
  6. +1 −0  activemodel/test/cases/helper.rb
  7. +16 −0 activemodel/test/cases/serializeration/json_serialization_test.rb
  8. +0 −35 activemodel/test/cases/tests_database.rb
  9. +15 −18 activemodel/test/cases/validations/acceptance_validation_test.rb
  10. +21 −23 activemodel/test/cases/validations/conditional_validation_test.rb
  11. +4 −7 activemodel/test/cases/validations/confirmation_validation_test.rb
  12. +5 −7 activemodel/test/cases/validations/exclusion_validation_test.rb
  13. +17 −20 activemodel/test/cases/validations/format_validation_test.rb
  14. +0 −1  activemodel/test/cases/validations/i18n_generate_message_validation_test.rb
  15. +1 −3 activemodel/test/cases/validations/i18n_validation_test.rb
  16. +11 −14 activemodel/test/cases/validations/inclusion_validation_test.rb
  17. +53 −143 activemodel/test/cases/validations/length_validation_test.rb
  18. +5 −8 activemodel/test/cases/validations/numericality_validation_test.rb
  19. +6 −9 activemodel/test/cases/validations/presence_validation_test.rb
  20. +39 −0 activemodel/test/cases/validations/validations_context_test.rb
  21. +10 −25 activemodel/test/cases/validations/with_validation_test.rb
  22. +44 −45 activemodel/test/cases/validations_test.rb
  23. +0 −41 activemodel/test/fixtures/topics.yml
  24. +0 −6 activemodel/test/models/developer.rb
  25. +7 −9 activemodel/test/models/reply.rb
  26. +11 −1 activemodel/test/models/topic.rb
  27. +0 −14 activemodel/test/schema.rb
  28. +2 −0  activerecord/CHANGELOG
  29. +2 −0  activerecord/lib/active_record.rb
  30. +1 −0  activerecord/lib/active_record/aggregations.rb
  31. +8 −8 activerecord/lib/active_record/associations.rb
  32. +1 −1  activerecord/lib/active_record/associations/association_proxy.rb
  33. +10 −1 activerecord/lib/active_record/attribute_methods.rb
  34. +50 −50 activerecord/lib/active_record/attribute_methods/dirty.rb
  35. +2 −4 activerecord/lib/active_record/autosave_association.rb
  36. +2 −329 activerecord/lib/active_record/base.rb
  37. +16 −32 activerecord/lib/active_record/callbacks.rb
  38. +1 −1  activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
  39. +10 −17 activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb
  40. +107 −0 activerecord/lib/active_record/counter_cache.rb
  41. +8 −19 activerecord/lib/active_record/locking/optimistic.rb
  42. +1 −1  activerecord/lib/active_record/nested_attributes.rb
  43. +230 −0 activerecord/lib/active_record/persistence.rb
  44. +10 −6 activerecord/lib/active_record/relation/calculations.rb
  45. +13 −9 activerecord/lib/active_record/relation/finder_methods.rb
  46. +2 −6 activerecord/lib/active_record/relation/query_methods.rb
  47. +6 −1 activerecord/lib/active_record/relation/spawn_methods.rb
  48. +22 −26 activerecord/lib/active_record/timestamp.rb
  49. +10 −12 activerecord/lib/active_record/transactions.rb
  50. +31 −38 activerecord/lib/active_record/validations.rb
  51. +10 −0 activerecord/test/cases/base_test.rb
  52. +17 −1 activerecord/test/cases/finder_test.rb
  53. +6 −3 activerecord/test/cases/locking_test.rb
  54. +25 −0 activerecord/test/cases/nested_attributes_test.rb
  55. +1 −1  activerecord/test/cases/validations_test.rb
  56. +6 −0 activesupport/CHANGELOG
  57. +19 −0 activesupport/lib/active_support/core_ext/date/calculations.rb
  58. +6 −0 activesupport/lib/active_support/core_ext/date_time/conversions.rb
  59. +5 −3 activesupport/lib/active_support/core_ext/time/calculations.rb
  60. +55 −1 activesupport/test/core_ext/date_ext_test.rb
  61. +5 −0 activesupport/test/core_ext/date_time_ext_test.rb
  62. +7 −0 activesupport/test/core_ext/time_ext_test.rb
  63. +2 −2 railties/lib/rails/commands/dbconsole.rb
  64. +42 −4 railties/lib/rails/generators.rb
  65. +4 −1 railties/lib/rails/generators/rails/app/app_generator.rb
  66. +8 −0 railties/test/generators/app_generator_test.rb
View
2  actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -38,7 +38,7 @@ def parse_formatted_parameters(env)
when Proc
strategy.call(request.raw_post)
when :xml_simple, :xml_node
- data = Hash.from_xml(request.body) || {}
+ data = Hash.from_xml(request.body.read) || {}
request.body.rewind if request.body.respond_to?(:rewind)
data.with_indifferent_access
when :yaml
View
13 actionpack/test/dispatch/request/xml_params_parsing_test.rb
@@ -16,6 +16,19 @@ def teardown
TestController.last_request_parameters = nil
end
+ test "parses a strict rack.input" do
+ class Linted
+ def call(env)
+ bar = env['action_dispatch.request.request_parameters']['foo']
+ result = "<ok>#{bar}</ok>"
+ [200, {"Content-Type" => "application/xml", "Content-Length" => result.length.to_s}, result]
+ end
+ end
+ req = Rack::MockRequest.new(ActionDispatch::ParamsParser.new(Linted.new))
+ resp = req.post('/', "CONTENT_TYPE" => "application/xml", :input => "<foo>bar</foo>", :lint => true)
+ assert_equal "<ok>bar</ok>", resp.body
+ end
+
test "parses hash params" do
with_test_routing do
xml = "<person><name>David</name></person>"
View
5 activemodel/CHANGELOG
@@ -1,3 +1,8 @@
+*Rails 3.0.0 [beta 4/release candidate] (unreleased)*
+
+* JSON supports a custom root option: to_json(:root => 'custom') #4515 [Jatinder Singh]
+
+
*Rails 3.0.0 [beta 3] (April 13th, 2010)*
* No changes
View
6 activemodel/lib/active_model/serializers/json.rb
@@ -79,7 +79,11 @@ module JSON
# "title": "So I was thinking"}]}
def encode_json(encoder)
hash = serializable_hash(encoder.options)
- hash = { self.class.model_name.element => hash } if include_root_in_json
+ if include_root_in_json
+ custom_root = encoder.options && encoder.options[:root]
+ hash = { custom_root || self.class.model_name.element => hash }
+ end
+
ActiveSupport::JSON.encode(hash)
end
View
17 activemodel/lib/active_model/validations.rb
@@ -29,7 +29,7 @@ module ActiveModel
# person.invalid?
# #=> false
# person.first_name = 'zoolander'
- # person.valid?
+ # person.valid?
# #=> false
# person.invalid?
# #=> true
@@ -48,6 +48,8 @@ module Validations
extend ActiveModel::Translation
define_callbacks :validate, :scope => :name
+ attr_accessor :validation_context
+
class_attribute :_validators
self._validators = Hash.new { |h,k| h[k] = [] }
end
@@ -117,7 +119,7 @@ def validate(*args, &block)
options = args.last
if options.is_a?(Hash) && options.key?(:on)
options[:if] = Array.wrap(options[:if])
- options[:if] << "@_on_validate == :#{options[:on]}"
+ options[:if] << "validation_context == :#{options[:on]}"
end
set_callback(:validate, *args, &block)
end
@@ -150,15 +152,20 @@ def errors
end
# Runs all the specified validations and returns true if no errors were added otherwise false.
- def valid?
+ # Context can optionally be supplied to define which callbacks to test against (the context is
+ # defined on the validations using :on).
+ def valid?(context = nil)
+ current_context, self.validation_context = validation_context, context
errors.clear
_run_validate_callbacks
errors.empty?
+ ensure
+ self.validation_context = current_context
end
# Performs the opposite of <tt>valid?</tt>. Returns true if errors were added, false otherwise.
- def invalid?
- !valid?
+ def invalid?(context = nil)
+ !valid?(context)
end
# Hook method defining how an attribute value should be retieved. By default this is assumed
View
1  activemodel/test/cases/helper.rb
@@ -5,6 +5,7 @@
require 'config'
require 'active_model'
+require 'active_support/core_ext/string/access'
# Show backtraces for deprecated behavior for quicker cleanup.
ActiveSupport::Deprecation.debug = true
View
16 activemodel/test/cases/serializeration/json_serialization_test.rb
@@ -37,6 +37,22 @@ def setup
end
end
+ test "should include custom root in json" do
+ begin
+ Contact.include_root_in_json = true
+ json = @contact.to_json(:root => 'json_contact')
+
+ assert_match %r{^\{"json_contact":\{}, json
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_match %r{"age":16}, json
+ assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_match %r{"awesome":true}, json
+ assert_match %r{"preferences":\{"shows":"anime"\}}, json
+ ensure
+ Contact.include_root_in_json = false
+ end
+ end
+
test "should encode all encodable attributes" do
json = @contact.to_json
View
35 activemodel/test/cases/tests_database.rb
@@ -1,35 +0,0 @@
-require 'logger'
-
-$:.unshift(File.dirname(__FILE__) + '/../../../activerecord/lib')
-require 'active_record'
-
-module ActiveModel
- module TestsDatabase
- mattr_accessor :connected
-
- def self.included(base)
- unless self.connected
- setup_connection
- setup_schema
- end
-
- base.send :include, ActiveRecord::TestFixtures
- end
-
- def self.setup_schema
- original, $stdout = $stdout, StringIO.new
- load(SCHEMA_FILE)
- ensure
- $stdout = original
- self.connected = true
- end
-
- def self.setup_connection
- defaults = { :database => ':memory:' }
-
- adapter = defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'
- options = defaults.merge :adapter => adapter, :timeout => 500
- ActiveRecord::Base.establish_connection(options)
- end
- end
-end
View
33 activemodel/test/cases/validations/acceptance_validation_test.rb
@@ -1,57 +1,54 @@
# encoding: utf-8
require 'cases/helper'
-require 'cases/tests_database'
require 'models/topic'
require 'models/reply'
-require 'models/developer'
require 'models/person'
class AcceptanceValidationTest < ActiveModel::TestCase
- include ActiveModel::TestsDatabase
def teardown
Topic.reset_callbacks(:validate)
end
def test_terms_of_service_agreement_no_acceptance
- Topic.validates_acceptance_of(:terms_of_service, :on => :create)
+ Topic.validates_acceptance_of(:terms_of_service)
- t = Topic.create("title" => "We should not be confirmed")
- assert t.save
+ t = Topic.new("title" => "We should not be confirmed")
+ assert t.valid?
end
def test_terms_of_service_agreement
- Topic.validates_acceptance_of(:terms_of_service, :on => :create)
+ Topic.validates_acceptance_of(:terms_of_service)
- t = Topic.create("title" => "We should be confirmed","terms_of_service" => "")
- assert !t.save
+ t = Topic.new("title" => "We should be confirmed","terms_of_service" => "")
+ assert t.invalid?
assert_equal ["must be accepted"], t.errors[:terms_of_service]
t.terms_of_service = "1"
- assert t.save
+ assert t.valid?
end
def test_eula
- Topic.validates_acceptance_of(:eula, :message => "must be abided", :on => :create)
+ Topic.validates_acceptance_of(:eula, :message => "must be abided")
- t = Topic.create("title" => "We should be confirmed","eula" => "")
- assert !t.save
+ t = Topic.new("title" => "We should be confirmed","eula" => "")
+ assert t.invalid?
assert_equal ["must be abided"], t.errors[:eula]
t.eula = "1"
- assert t.save
+ assert t.valid?
end
def test_terms_of_service_agreement_with_accept_value
- Topic.validates_acceptance_of(:terms_of_service, :on => :create, :accept => "I agree.")
+ Topic.validates_acceptance_of(:terms_of_service, :accept => "I agree.")
- t = Topic.create("title" => "We should be confirmed", "terms_of_service" => "")
- assert !t.save
+ t = Topic.new("title" => "We should be confirmed", "terms_of_service" => "")
+ assert t.invalid?
assert_equal ["must be accepted"], t.errors[:terms_of_service]
t.terms_of_service = "I agree."
- assert t.save
+ assert t.valid?
end
def test_validates_acceptance_of_for_ruby_class
View
44 activemodel/test/cases/validations/conditional_validation_test.rb
@@ -1,21 +1,19 @@
# encoding: utf-8
require 'cases/helper'
-require 'cases/tests_database'
require 'models/topic'
class ConditionalValidationTest < ActiveModel::TestCase
- include ActiveModel::TestsDatabase
def teardown
Topic.reset_callbacks(:validate)
end
-
+
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 )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["hoo 5"], t.errors["title"]
end
@@ -23,15 +21,15 @@ def test_if_validation_using_method_true
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 )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
- assert !t.errors[:title].any?
+ assert t.errors[:title].empty?
end
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 )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
assert t.errors[:title].empty?
end
@@ -39,8 +37,8 @@ def test_if_validation_using_method_false
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 )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["hoo 5"], t.errors["title"]
end
@@ -48,8 +46,8 @@ def test_unless_validation_using_method_false
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" )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["hoo 5"], t.errors["title"]
end
@@ -57,7 +55,7 @@ def test_if_validation_using_string_true
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" )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
assert t.errors[:title].empty?
end
@@ -65,7 +63,7 @@ def test_unless_validation_using_string_true
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")
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
assert t.errors[:title].empty?
end
@@ -73,8 +71,8 @@ def test_if_validation_using_string_false
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")
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["hoo 5"], t.errors["title"]
end
@@ -83,8 +81,8 @@ def test_if_validation_using_block_true
# When the block returns true
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
:if => Proc.new { |r| r.content.size > 4 } )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["hoo 5"], t.errors["title"]
end
@@ -93,7 +91,7 @@ def test_unless_validation_using_block_true
# When the block returns true
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
:unless => Proc.new { |r| r.content.size > 4 } )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
assert t.errors[:title].empty?
end
@@ -102,7 +100,7 @@ def test_if_validation_using_block_false
# When the block returns false
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
:if => Proc.new { |r| r.title != "uhohuhoh"} )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.valid?
assert t.errors[:title].empty?
end
@@ -111,8 +109,8 @@ def test_unless_validation_using_block_false
# When the block returns false
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
:unless => Proc.new { |r| r.title != "uhohuhoh"} )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["hoo 5"], t.errors["title"]
end
@@ -132,7 +130,7 @@ def test_validation_with_if_as_string
assert t.valid?, "A topic with a basic title should be valid"
t.title = "A very important title"
- assert !t.valid?, "A topic with an important title, but without an author, should not be valid"
+ assert t.invalid?, "A topic with an important title, but without an author, should not be valid"
assert t.errors[:author_name].any?, "A topic with an 'important' title should require an author"
t.author_name = "Hubert J. Farnsworth"
View
11 activemodel/test/cases/validations/confirmation_validation_test.rb
@@ -1,13 +1,10 @@
# encoding: utf-8
require 'cases/helper'
-require 'cases/tests_database'
require 'models/topic'
-require 'models/developer'
require 'models/person'
class ConfirmationValidationTest < ActiveModel::TestCase
- include ActiveModel::TestsDatabase
def teardown
Topic.reset_callbacks(:validate)
@@ -20,7 +17,7 @@ def test_no_title_confirmation
assert t.valid?
t.title_confirmation = "Parallel Lives"
- assert !t.valid?
+ assert t.invalid?
t.title_confirmation = nil
t.title = "Parallel Lives"
@@ -33,11 +30,11 @@ def test_no_title_confirmation
def test_title_confirmation
Topic.validates_confirmation_of(:title)
- t = Topic.create("title" => "We should be confirmed","title_confirmation" => "")
- assert !t.save
+ t = Topic.new("title" => "We should be confirmed","title_confirmation" => "")
+ assert t.invalid?
t.title_confirmation = "We should be confirmed"
- assert t.save
+ assert t.valid?
end
def test_validates_confirmation_of_for_ruby_class
View
12 activemodel/test/cases/validations/exclusion_validation_test.rb
@@ -1,12 +1,10 @@
# encoding: utf-8
require 'cases/helper'
-require 'cases/tests_database'
require 'models/topic'
require 'models/person'
class ExclusionValidationTest < ActiveModel::TestCase
- include ActiveModel::TestsDatabase
def teardown
Topic.reset_callbacks(:validate)
@@ -15,17 +13,17 @@ def teardown
def test_validates_exclusion_of
Topic.validates_exclusion_of( :title, :in => %w( abe monkey ) )
- assert Topic.create("title" => "something", "content" => "abc").valid?
- assert !Topic.create("title" => "monkey", "content" => "abc").valid?
+ assert Topic.new("title" => "something", "content" => "abc").valid?
+ assert Topic.new("title" => "monkey", "content" => "abc").invalid?
end
def test_validates_exclusion_of_with_formatted_message
Topic.validates_exclusion_of( :title, :in => %w( abe monkey ), :message => "option %{value} is restricted" )
- assert Topic.create("title" => "something", "content" => "abc")
+ assert Topic.new("title" => "something", "content" => "abc")
- t = Topic.create("title" => "monkey")
- assert !t.valid?
+ t = Topic.new("title" => "monkey")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["option monkey is restricted"], t.errors[:title]
end
View
37 activemodel/test/cases/validations/format_validation_test.rb
@@ -1,13 +1,10 @@
# encoding: utf-8
require 'cases/helper'
-require 'cases/tests_database'
require 'models/topic'
-require 'models/developer'
require 'models/person'
class PresenceValidationTest < ActiveModel::TestCase
- include ActiveModel::TestsDatabase
def teardown
Topic.reset_callbacks(:validate)
@@ -16,15 +13,14 @@ def teardown
def test_validate_format
Topic.validates_format_of(:title, :content, :with => /^Validation\smacros \w+!$/, :message => "is bad data")
- t = Topic.create("title" => "i'm incorrect", "content" => "Validation macros rule!")
- assert !t.valid?, "Shouldn't be valid"
- assert !t.save, "Shouldn't save because it's invalid"
+ t = Topic.new("title" => "i'm incorrect", "content" => "Validation macros rule!")
+ assert t.invalid?, "Shouldn't be valid"
assert_equal ["is bad data"], t.errors[:title]
assert t.errors[:content].empty?
t.title = "Validation macros rule!"
- assert t.save
+ assert t.valid?
assert t.errors[:title].empty?
assert_raise(ArgumentError) { Topic.validates_format_of(:title, :content) }
@@ -32,43 +28,44 @@ def test_validate_format
def test_validate_format_with_allow_blank
Topic.validates_format_of(:title, :with => /^Validation\smacros \w+!$/, :allow_blank=>true)
- assert !Topic.create("title" => "Shouldn't be valid").valid?
- assert Topic.create("title" => "").valid?
- assert Topic.create("title" => nil).valid?
- assert Topic.create("title" => "Validation macros rule!").valid?
+ assert Topic.new("title" => "Shouldn't be valid").invalid?
+ assert Topic.new("title" => "").valid?
+ assert Topic.new("title" => nil).valid?
+ assert Topic.new("title" => "Validation macros rule!").valid?
end
# testing ticket #3142
def test_validate_format_numeric
Topic.validates_format_of(:title, :content, :with => /^[1-9][0-9]*$/, :message => "is bad data")
- t = Topic.create("title" => "72x", "content" => "6789")
- assert !t.valid?, "Shouldn't be valid"
- assert !t.save, "Shouldn't save because it's invalid"
+ t = Topic.new("title" => "72x", "content" => "6789")
+ assert t.invalid?, "Shouldn't be valid"
+
assert_equal ["is bad data"], t.errors[:title]
assert t.errors[:content].empty?
t.title = "-11"
- assert !t.valid?, "Shouldn't be valid"
+ assert t.invalid?, "Shouldn't be valid"
t.title = "03"
- assert !t.valid?, "Shouldn't be valid"
+ assert t.invalid?, "Shouldn't be valid"
t.title = "z44"
- assert !t.valid?, "Shouldn't be valid"
+ assert t.invalid?, "Shouldn't be valid"
t.title = "5v7"
- assert !t.valid?, "Shouldn't be valid"
+ assert t.invalid?, "Shouldn't be valid"
t.title = "1"
- assert t.save
+ assert t.valid?
assert t.errors[:title].empty?
end
def test_validate_format_with_formatted_message
Topic.validates_format_of(:title, :with => /^Valid Title$/, :message => "can't be %{value}")
- t = Topic.create(:title => 'Invalid title')
+ t = Topic.new(:title => 'Invalid title')
+ assert t.invalid?
assert_equal ["can't be Invalid title"], t.errors[:title]
end
View
1  activemodel/test/cases/validations/i18n_generate_message_validation_test.rb
@@ -1,5 +1,4 @@
require "cases/helper"
-require 'cases/tests_database'
require 'models/person'
View
4 activemodel/test/cases/validations/i18n_validation_test.rb
@@ -1,11 +1,9 @@
# -*- coding: utf-8 -*-
require "cases/helper"
-require 'cases/tests_database'
require 'models/person'
class I18nValidationTest < ActiveModel::TestCase
- include ActiveModel::TestsDatabase
def setup
Person.reset_callbacks(:validate)
@@ -63,7 +61,7 @@ def test_errors_full_messages_uses_format
assert_equal ["Field Name empty"], @person.errors.full_messages
end
- # ActiveRecord::Validations
+ # ActiveModel::Validations
# validates_confirmation_of w/ mocha
def test_validates_confirmation_of_generates_message
Person.validates_confirmation_of :title
View
25 activemodel/test/cases/validations/inclusion_validation_test.rb
@@ -1,13 +1,10 @@
# encoding: utf-8
require 'cases/helper'
-require 'cases/tests_database'
require 'models/topic'
-require 'models/developer'
require 'models/person'
class InclusionValidationTest < ActiveModel::TestCase
- include ActiveModel::TestsDatabase
def teardown
Topic.reset_callbacks(:validate)
@@ -16,14 +13,14 @@ def teardown
def test_validates_inclusion_of
Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ) )
- assert !Topic.create("title" => "a!", "content" => "abc").valid?
- assert !Topic.create("title" => "a b", "content" => "abc").valid?
- assert !Topic.create("title" => nil, "content" => "def").valid?
+ assert Topic.new("title" => "a!", "content" => "abc").invalid?
+ assert Topic.new("title" => "a b", "content" => "abc").invalid?
+ assert Topic.new("title" => nil, "content" => "def").invalid?
- t = Topic.create("title" => "a", "content" => "I know you are but what am I?")
+ t = Topic.new("title" => "a", "content" => "I know you are but what am I?")
assert t.valid?
t.title = "uhoh"
- assert !t.valid?
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["is not included in the list"], t.errors[:title]
@@ -38,18 +35,18 @@ def test_validates_inclusion_of
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 )
- assert !Topic.create("title" => "a!", "content" => "abc").valid?
- assert !Topic.create("title" => "", "content" => "abc").valid?
- assert Topic.create("title" => nil, "content" => "abc").valid?
+ assert Topic.new("title" => "a!", "content" => "abc").invalid?
+ assert Topic.new("title" => "", "content" => "abc").invalid?
+ assert Topic.new("title" => nil, "content" => "abc").valid?
end
def test_validates_inclusion_of_with_formatted_message
Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ), :message => "option %{value} is not in the list" )
- assert Topic.create("title" => "a", "content" => "abc").valid?
+ assert Topic.new("title" => "a", "content" => "abc").valid?
- t = Topic.create("title" => "uhoh", "content" => "abc")
- assert !t.valid?
+ t = Topic.new("title" => "uhoh", "content" => "abc")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["option uhoh is not in the list"], t.errors[:title]
end
View
196 activemodel/test/cases/validations/length_validation_test.rb
@@ -1,13 +1,10 @@
# encoding: utf-8
require 'cases/helper'
-require 'cases/tests_database'
require 'models/topic'
-require 'models/developer'
require 'models/person'
class LengthValidationTest < ActiveModel::TestCase
- include ActiveModel::TestsDatabase
def teardown
Topic.reset_callbacks(:validate)
@@ -16,53 +13,53 @@ def teardown
def test_validates_length_of_with_allow_nil
Topic.validates_length_of( :title, :is => 5, :allow_nil=>true )
- assert !Topic.create("title" => "ab").valid?
- assert !Topic.create("title" => "").valid?
- assert Topic.create("title" => nil).valid?
- assert Topic.create("title" => "abcde").valid?
+ assert Topic.new("title" => "ab").invalid?
+ assert Topic.new("title" => "").invalid?
+ assert Topic.new("title" => nil).valid?
+ assert Topic.new("title" => "abcde").valid?
end
def test_validates_length_of_with_allow_blank
Topic.validates_length_of( :title, :is => 5, :allow_blank=>true )
- assert !Topic.create("title" => "ab").valid?
- assert Topic.create("title" => "").valid?
- assert Topic.create("title" => nil).valid?
- assert Topic.create("title" => "abcde").valid?
+ assert Topic.new("title" => "ab").invalid?
+ assert Topic.new("title" => "").valid?
+ assert Topic.new("title" => nil).valid?
+ assert Topic.new("title" => "abcde").valid?
end
def test_validates_length_of_using_minimum
Topic.validates_length_of :title, :minimum => 5
- t = Topic.create("title" => "valid", "content" => "whatever")
+ t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
t.title = "not"
- assert !t.valid?
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["is too short (minimum is 5 characters)"], t.errors[:title]
t.title = ""
- assert !t.valid?
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["is too short (minimum is 5 characters)"], t.errors[:title]
t.title = nil
- assert !t.valid?
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["is too short (minimum is 5 characters)"], t.errors["title"]
end
def test_validates_length_of_using_maximum_should_allow_nil
Topic.validates_length_of :title, :maximum => 10
- t = Topic.create
+ t = Topic.new
assert t.valid?
end
def test_optionally_validates_length_of_using_minimum
Topic.validates_length_of :title, :minimum => 5, :allow_nil => true
- t = Topic.create("title" => "valid", "content" => "whatever")
+ t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
t.title = nil
@@ -72,11 +69,11 @@ def test_optionally_validates_length_of_using_minimum
def test_validates_length_of_using_maximum
Topic.validates_length_of :title, :maximum => 5
- t = Topic.create("title" => "valid", "content" => "whatever")
+ t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
t.title = "notvalid"
- assert !t.valid?
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["is too long (maximum is 5 characters)"], t.errors[:title]
@@ -87,7 +84,7 @@ def test_validates_length_of_using_maximum
def test_optionally_validates_length_of_using_maximum
Topic.validates_length_of :title, :maximum => 5, :allow_nil => true
- t = Topic.create("title" => "valid", "content" => "whatever")
+ t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
t.title = nil
@@ -98,13 +95,13 @@ def test_validates_length_of_using_within
Topic.validates_length_of(:title, :content, :within => 3..5)
t = Topic.new("title" => "a!", "content" => "I'm ooooooooh so very long")
- assert !t.valid?
+ assert t.invalid?
assert_equal ["is too short (minimum is 3 characters)"], t.errors[:title]
assert_equal ["is too long (maximum is 5 characters)"], t.errors[:content]
t.title = nil
t.content = nil
- assert !t.valid?
+ assert t.invalid?
assert_equal ["is too short (minimum is 3 characters)"], t.errors[:title]
assert_equal ["is too short (minimum is 3 characters)"], t.errors[:content]
@@ -120,7 +117,7 @@ def test_validates_length_of_using_within_with_exclusive_range
assert t.valid?
t.title = "Now I'm 10"
- assert !t.valid?
+ assert t.invalid?
assert_equal ["is too long (maximum is 9 characters)"], t.errors[:title]
t.title = "Four"
@@ -130,77 +127,35 @@ def test_validates_length_of_using_within_with_exclusive_range
def test_optionally_validates_length_of_using_within
Topic.validates_length_of :title, :content, :within => 3..5, :allow_nil => true
- t = Topic.create('title' => 'abc', 'content' => 'abcd')
+ t = Topic.new('title' => 'abc', 'content' => 'abcd')
assert t.valid?
t.title = nil
assert t.valid?
end
- def test_optionally_validates_length_of_using_within_on_create
- Topic.validates_length_of :title, :content, :within => 5..10, :on => :create, :too_long => "my string is too long: %{count}"
-
- t = Topic.create("title" => "thisisnotvalid", "content" => "whatever")
- assert !t.save
- assert t.errors[:title].any?
- assert_equal ["my string is too long: 10"], t.errors[:title]
-
- t.title = "butthisis"
- assert t.save
-
- t.title = "few"
- assert t.save
-
- t.content = "andthisislong"
- assert t.save
-
- t.content = t.title = "iamfine"
- assert t.save
- end
-
- def test_optionally_validates_length_of_using_within_on_update
- Topic.validates_length_of :title, :content, :within => 5..10, :on => :update, :too_short => "my string is too short: %{count}"
-
- t = Topic.create("title" => "vali", "content" => "whatever")
- assert !t.save
- assert t.errors[:title].any?
-
- t.title = "not"
- assert !t.save
- assert t.errors[:title].any?
- assert_equal ["my string is too short: 5"], t.errors[:title]
-
- t.title = "valid"
- t.content = "andthisistoolong"
- assert !t.save
- assert t.errors[:content].any?
-
- t.content = "iamfine"
- assert t.save
- end
-
def test_validates_length_of_using_is
Topic.validates_length_of :title, :is => 5
- t = Topic.create("title" => "valid", "content" => "whatever")
+ t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
t.title = "notvalid"
- assert !t.valid?
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["is the wrong length (should be 5 characters)"], t.errors[:title]
t.title = ""
- assert !t.valid?
+ assert t.invalid?
t.title = nil
- assert !t.valid?
+ assert t.invalid?
end
def test_optionally_validates_length_of_using_is
Topic.validates_length_of :title, :is => 5, :allow_nil => true
- t = Topic.create("title" => "valid", "content" => "whatever")
+ t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
t.title = nil
@@ -231,61 +186,61 @@ def test_validates_length_of_nasty_params
def test_validates_length_of_custom_errors_for_minimum_with_message
Topic.validates_length_of( :title, :minimum=>5, :message=>"boo %{count}" )
- t = Topic.create("title" => "uhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["boo 5"], t.errors[:title]
end
def test_validates_length_of_custom_errors_for_minimum_with_too_short
Topic.validates_length_of( :title, :minimum=>5, :too_short=>"hoo %{count}" )
- t = Topic.create("title" => "uhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["hoo 5"], t.errors[:title]
end
def test_validates_length_of_custom_errors_for_maximum_with_message
Topic.validates_length_of( :title, :maximum=>5, :message=>"boo %{count}" )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["boo 5"], t.errors[:title]
end
def test_validates_length_of_custom_errors_for_in
Topic.validates_length_of(:title, :in => 10..20, :message => "hoo %{count}")
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["hoo 10"], t.errors["title"]
- t = Topic.create("title" => "uhohuhohuhohuhohuhohuhohuhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhohuhohuhohuhohuhohuhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["hoo 20"], t.errors["title"]
end
def test_validates_length_of_custom_errors_for_maximum_with_too_long
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}" )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["hoo 5"], t.errors["title"]
end
def test_validates_length_of_custom_errors_for_is_with_message
Topic.validates_length_of( :title, :is=>5, :message=>"boo %{count}" )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["boo 5"], t.errors["title"]
end
def test_validates_length_of_custom_errors_for_is_with_wrong_length
Topic.validates_length_of( :title, :is=>5, :wrong_length=>"hoo %{count}" )
- t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["hoo 5"], t.errors["title"]
end
@@ -294,11 +249,11 @@ def test_validates_length_of_using_minimum_utf8
with_kcode('UTF8') do
Topic.validates_length_of :title, :minimum => 5
- t = Topic.create("title" => "一二三四五", "content" => "whatever")
+ t = Topic.new("title" => "一二三四五", "content" => "whatever")
assert t.valid?
t.title = "一二三四"
- assert !t.valid?
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["is too short (minimum is 5 characters)"], t.errors["title"]
end
@@ -308,11 +263,11 @@ def test_validates_length_of_using_maximum_utf8
with_kcode('UTF8') do
Topic.validates_length_of :title, :maximum => 5
- t = Topic.create("title" => "一二三四五", "content" => "whatever")
+ t = Topic.new("title" => "一二三四五", "content" => "whatever")
assert t.valid?
t.title = "一二34五六"
- assert !t.valid?
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["is too long (maximum is 5 characters)"], t.errors["title"]
end
@@ -323,7 +278,7 @@ def test_validates_length_of_using_within_utf8
Topic.validates_length_of(:title, :content, :within => 3..5)
t = Topic.new("title" => "一二", "content" => "12三四五六七")
- assert !t.valid?
+ assert t.invalid?
assert_equal ["is too short (minimum is 3 characters)"], t.errors[:title]
assert_equal ["is too long (maximum is 5 characters)"], t.errors[:content]
t.title = "一二三"
@@ -336,10 +291,10 @@ def test_optionally_validates_length_of_using_within_utf8
with_kcode('UTF8') do
Topic.validates_length_of :title, :within => 3..5, :allow_nil => true
- t = Topic.create(:title => "一二三四五")
+ t = Topic.new(:title => "一二三四五")
assert t.valid?, t.errors.inspect
- t = Topic.create(:title => "一二三")
+ t = Topic.new(:title => "一二三")
assert t.valid?, t.errors.inspect
t.title = nil
@@ -347,60 +302,15 @@ def test_optionally_validates_length_of_using_within_utf8
end
end
- def test_optionally_validates_length_of_using_within_on_create_utf8
- with_kcode('UTF8') do
- Topic.validates_length_of :title, :within => 5..10, :on => :create, :too_long => "長すぎます: %{count}"
-
- t = Topic.create("title" => "一二三四五六七八九十A", "content" => "whatever")
- assert !t.save
- assert t.errors[:title].any?
- assert_equal "長すぎます: 10", t.errors[:title].first
-
- t.title = "一二三四五六七八九"
- assert t.save
-
- t.title = "一二3"
- assert t.save
-
- t.content = "一二三四五六七八九十"
- assert t.save
-
- t.content = t.title = "一二三四五六"
- assert t.save
- end
- end
-
- def test_optionally_validates_length_of_using_within_on_update_utf8
- with_kcode('UTF8') do
- Topic.validates_length_of :title, :within => 5..10, :on => :update, :too_short => "短すぎます: %{count}"
-
- t = Topic.create("title" => "一二三4", "content" => "whatever")
- assert !t.save
- assert t.errors[:title].any?
-
- t.title = "1二三4"
- assert !t.save
- assert t.errors[:title].any?
- assert_equal ["短すぎます: 5"], t.errors[:title]
-
- t.title = "一二三四五六七八九十A"
- assert !t.save
- assert t.errors[:title].any?
-
- t.title = "一二345"
- assert t.save
- end
- end
-
def test_validates_length_of_using_is_utf8
with_kcode('UTF8') do
Topic.validates_length_of :title, :is => 5
- t = Topic.create("title" => "一二345", "content" => "whatever")
+ t = Topic.new("title" => "一二345", "content" => "whatever")
assert t.valid?
t.title = "一二345六"
- assert !t.valid?
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["is the wrong length (should be 5 characters)"], t.errors["title"]
end
@@ -409,11 +319,11 @@ def test_validates_length_of_using_is_utf8
def test_validates_length_of_with_block
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.create!(:content => "this content should be long enough")
+ t = Topic.new(:content => "this content should be long enough")
assert t.valid?
t.content = "not long enough"
- assert !t.valid?
+ assert t.invalid?
assert t.errors[:content].any?
assert_equal ["Your essay must be at least 5 words."], t.errors[:content]
end
View
13 activemodel/test/cases/validations/numericality_validation_test.rb
@@ -1,13 +1,10 @@
# encoding: utf-8
require 'cases/helper'
-require 'cases/tests_database'
require 'models/topic'
-require 'models/developer'
require 'models/person'
class NumericalityValidationTest < ActiveModel::TestCase
- include ActiveModel::TestsDatabase
def teardown
Topic.reset_callbacks(:validate)
@@ -33,8 +30,8 @@ def test_default_validates_numericality_of
def test_validates_numericality_of_with_nil_allowed
Topic.validates_numericality_of :approved, :allow_nil => true
- invalid!(JUNK)
- valid!(NIL + BLANK + FLOATS + INTEGERS + BIGDECIMAL + INFINITY)
+ invalid!(JUNK + BLANK)
+ valid!(NIL + FLOATS + INTEGERS + BIGDECIMAL + INFINITY)
end
def test_validates_numericality_of_with_integer_only
@@ -47,8 +44,8 @@ def test_validates_numericality_of_with_integer_only
def test_validates_numericality_of_with_integer_only_and_nil_allowed
Topic.validates_numericality_of :approved, :only_integer => true, :allow_nil => true
- invalid!(JUNK + FLOATS + BIGDECIMAL + INFINITY)
- valid!(NIL + BLANK + INTEGERS)
+ invalid!(JUNK + BLANK + FLOATS + BIGDECIMAL + INFINITY)
+ valid!(NIL + INTEGERS)
end
def test_validates_numericality_with_greater_than
@@ -166,7 +163,7 @@ def test_validates_numericality_with_invalid_args
def invalid!(values, error = nil)
with_each_topic_approved_value(values) do |topic, value|
- assert !topic.valid?, "#{value.inspect} not rejected as a number"
+ assert topic.invalid?, "#{value.inspect} not rejected as a number"
assert topic.errors[:approved].any?, "FAILED for #{value.inspect}"
assert_equal error, topic.errors[:approved].first if error
end
View
15 activemodel/test/cases/validations/presence_validation_test.rb
@@ -1,14 +1,11 @@
# encoding: utf-8
require 'cases/helper'
-require 'cases/tests_database'
require 'models/topic'
-require 'models/developer'
require 'models/person'
require 'models/custom_reader'
class PresenceValidationTest < ActiveModel::TestCase
- include ActiveModel::TestsDatabase
teardown do
Topic.reset_callbacks(:validate)
@@ -19,26 +16,26 @@ class PresenceValidationTest < ActiveModel::TestCase
def test_validate_presences
Topic.validates_presence_of(:title, :content)
- t = Topic.create
- assert !t.save
+ t = Topic.new
+ assert t.invalid?
assert_equal ["can't be blank"], t.errors[:title]
assert_equal ["can't be blank"], t.errors[:content]
t.title = "something"
t.content = " "
- assert !t.save
+ assert t.invalid?
assert_equal ["can't be blank"], t.errors[:content]
t.content = "like stuff"
- assert t.save
+ assert t.valid?
end
test 'accepts array arguments' do
Topic.validates_presence_of %w(title content)
t = Topic.new
- assert !t.valid?
+ assert t.invalid?
assert_equal ["can't be blank"], t.errors[:title]
assert_equal ["can't be blank"], t.errors[:content]
end
@@ -46,7 +43,7 @@ def test_validate_presences
def test_validates_acceptance_of_with_custom_error_using_quotes
Person.validates_presence_of :karma, :message => "This string contains 'single' and \"double\" quotes"
p = Person.new
- assert !p.valid?
+ assert p.invalid?
assert_equal "This string contains 'single' and \"double\" quotes", p.errors[:karma].last
end
View
39 activemodel/test/cases/validations/validations_context_test.rb
@@ -0,0 +1,39 @@
+# encoding: utf-8
+require 'cases/helper'
+
+require 'models/topic'
+
+class ValidationsContextTest < ActiveModel::TestCase
+
+ def teardown
+ Topic.reset_callbacks(:validate)
+ Topic._validators.clear
+ end
+
+ ERROR_MESSAGE = "Validation error from validator"
+
+ class ValidatorThatAddsErrors < ActiveModel::Validator
+ def validate(record)
+ record.errors[:base] << ERROR_MESSAGE
+ end
+ end
+
+ test "with a class that adds errors on update and validating a new model with no arguments" do
+ Topic.validates_with(ValidatorThatAddsErrors, :on => :create)
+ topic = Topic.new
+ assert topic.valid?, "Validation doesn't run on create if 'on' is set to update"
+ end
+
+ test "with a class that adds errors on update and validating a new model" do
+ Topic.validates_with(ValidatorThatAddsErrors, :on => :update)
+ topic = Topic.new
+ assert topic.valid?(:create), "Validation doesn't run on create if 'on' is set to update"
+ end
+
+ test "with a class that adds errors on create and validating a new model" do
+ Topic.validates_with(ValidatorThatAddsErrors, :on => :create)
+ topic = Topic.new
+ assert topic.invalid?(:create), "Validation does run on create if 'on' is set to create"
+ assert topic.errors[:base].include?(ERROR_MESSAGE)
+ end
+end
View
35 activemodel/test/cases/validations/with_validation_test.rb
@@ -1,11 +1,9 @@
# encoding: utf-8
require 'cases/helper'
-require 'cases/tests_database'
require 'models/topic'
-class ValidatesWithTest < ActiveRecord::TestCase
- include ActiveModel::TestsDatabase
+class ValidatesWithTest < ActiveModel::TestCase
def teardown
Topic.reset_callbacks(:validate)
@@ -55,7 +53,7 @@ def check_validity!
test "vaidation with class that adds errors" do
Topic.validates_with(ValidatorThatAddsErrors)
topic = Topic.new
- assert !topic.valid?, "A class that adds errors causes the record to be invalid"
+ assert topic.invalid?, "A class that adds errors causes the record to be invalid"
assert topic.errors[:base].include?(ERROR_MESSAGE)
end
@@ -65,23 +63,10 @@ def check_validity!
assert topic.valid?, "A class that does not add errors does not cause the record to be invalid"
end
- test "with a class that adds errors on update and a new record" do
- Topic.validates_with(ValidatorThatAddsErrors, :on => :update)
- topic = Topic.new
- assert topic.valid?, "Validation doesn't run on create if 'on' is set to update"
- end
-
- test "with a class that adds errors on create and a new record" do
- Topic.validates_with(ValidatorThatAddsErrors, :on => :create)
- topic = Topic.new
- assert !topic.valid?, "Validation does run on create if 'on' is set to create"
- assert topic.errors[:base].include?(ERROR_MESSAGE)
- end
-
test "with multiple classes" do
Topic.validates_with(ValidatorThatAddsErrors, OtherValidatorThatAddsErrors)
topic = Topic.new
- assert !topic.valid?
+ assert topic.invalid?
assert topic.errors[:base].include?(ERROR_MESSAGE)
assert topic.errors[:base].include?(OTHER_ERROR_MESSAGE)
end
@@ -95,7 +80,7 @@ def check_validity!
test "with if statements that return true" do
Topic.validates_with(ValidatorThatAddsErrors, :if => "1 == 1")
topic = Topic.new
- assert !topic.valid?
+ assert topic.invalid?
assert topic.errors[:base].include?(ERROR_MESSAGE)
end
@@ -108,7 +93,7 @@ def check_validity!
test "with unless statements that returns false" do
Topic.validates_with(ValidatorThatAddsErrors, :unless => "1 == 2")
topic = Topic.new
- assert !topic.valid?
+ assert topic.invalid?
assert topic.errors[:base].include?(ERROR_MESSAGE)
end
@@ -121,7 +106,7 @@ def check_validity!
Topic.validates_with(validator, :if => "1 == 1", :foo => :bar)
assert topic.valid?
end
-
+
test "calls setup method of validator passing in self when validator has setup method" do
topic = Topic.new
validator = stub_everything
@@ -132,7 +117,7 @@ def check_validity!
Topic.validates_with(validator)
assert topic.valid?
end
-
+
test "doesn't call setup method of validator when validator has no setup method" do
topic = Topic.new
validator = stub_everything
@@ -147,14 +132,14 @@ def check_validity!
test "validates_with with options" do
Topic.validates_with(ValidatorThatValidatesOptions, :field => :first_name)
topic = Topic.new
- assert !topic.valid?
+ assert topic.invalid?
assert topic.errors[:base].include?(ERROR_MESSAGE)
end
test "validates_with each validator" do
Topic.validates_with(ValidatorPerEachAttribute, :attributes => [:title, :content])
topic = Topic.new :title => "Title", :content => "Content"
- assert !topic.valid?
+ assert topic.invalid?
assert_equal ["Value is Title"], topic.errors[:title]
assert_equal ["Value is Content"], topic.errors[:content]
end
@@ -174,7 +159,7 @@ def check_validity!
test "each validator skip nil values if :allow_nil is set to true" do
Topic.validates_with(ValidatorPerEachAttribute, :attributes => [:title, :content], :allow_nil => true)
topic = Topic.new :content => ""
- assert !topic.valid?
+ assert topic.invalid?
assert topic.errors[:title].empty?
assert_equal ["Value is "], topic.errors[:content]
end
View
89 activemodel/test/cases/validations_test.rb
@@ -1,14 +1,11 @@
# encoding: utf-8
require 'cases/helper'
-require 'cases/tests_database'
require 'models/topic'
require 'models/reply'
-require 'models/developer'
require 'models/custom_reader'
class ValidationsTest < ActiveModel::TestCase
- include ActiveModel::TestsDatabase
def setup
Topic._validators.clear
@@ -23,7 +20,7 @@ def teardown
def test_single_field_validation
r = Reply.new
r.title = "There's no content!"
- assert !r.valid?, "A reply without content shouldn't be saveable"
+ assert r.invalid?, "A reply without content shouldn't be saveable"
r.content = "Messa content!"
assert r.valid?, "A reply with content should be saveable"
@@ -32,46 +29,46 @@ def test_single_field_validation
def test_single_attr_validation_and_error_msg
r = Reply.new
r.title = "There's no content!"
- assert !r.valid?
+ assert r.invalid?
assert r.errors[:content].any?, "A reply without content should mark that attribute as invalid"
- assert_equal ["Empty"], r.errors["content"], "A reply without content should contain an error"
+ assert_equal ["is Empty"], r.errors["content"], "A reply without content should contain an error"
assert_equal 1, r.errors.count
end
def test_double_attr_validation_and_error_msg
r = Reply.new
- assert !r.valid?
+ assert r.invalid?
assert r.errors[:title].any?, "A reply without title should mark that attribute as invalid"
- assert_equal ["Empty"], r.errors["title"], "A reply without title should contain an error"
+ assert_equal ["is Empty"], r.errors["title"], "A reply without title should contain an error"
assert r.errors[:content].any?, "A reply without content should mark that attribute as invalid"
- assert_equal ["Empty"], r.errors["content"], "A reply without content should contain an error"
+ assert_equal ["is Empty"], r.errors["content"], "A reply without content should contain an error"
assert_equal 2, r.errors.count
end
def test_single_error_per_attr_iteration
r = Reply.new
- r.save
+ r.valid?
errors = []
r.errors.each {|attr, messages| errors << [attr.to_s, messages] }
- assert errors.include?(["title", "Empty"])
- assert errors.include?(["content", "Empty"])
+ assert errors.include?(["title", "is Empty"])
+ assert errors.include?(["content", "is Empty"])
end
def test_multiple_errors_per_attr_iteration_with_full_error_composition
r = Reply.new
- r.title = "Wrong Create"
- r.content = "Mismatch"
- r.save
+ r.title = ""
+ r.content = ""
+ r.valid?
errors = r.errors.to_a
- assert_equal "Title is Wrong Create", errors[0]
- assert_equal "Title is Content Mismatch", errors[1]
+ assert_equal "Content is Empty", errors[0]
+ assert_equal "Title is Empty", errors[1]
assert_equal 2, r.errors.count
end
@@ -84,7 +81,7 @@ def test_errors_on_nested_attributes_expands_name
def test_errors_on_base
r = Reply.new
r.content = "Mismatch"
- r.save
+ r.valid?
r.errors[:base] << "Reply is not dignifying"
errors = []
@@ -92,7 +89,7 @@ def test_errors_on_base
assert_equal ["Reply is not dignifying"], r.errors[:base]
- assert errors.include?("Title Empty")
+ assert errors.include?("Title is Empty")
assert errors.include?("Reply is not dignifying")
assert_equal 2, r.errors.count
end
@@ -110,12 +107,12 @@ def test_validates_each
hits += 1
end
t = Topic.new("title" => "valid", "content" => "whatever")
- assert !t.save
+ assert t.invalid?
assert_equal 4, hits
assert_equal %w(gotcha gotcha), t.errors[:title]
assert_equal %w(gotcha gotcha), t.errors[:content]
end
-
+
def test_validates_each_custom_reader
hits = 0
CustomReader.validates_each(:title, :content, [:title, :content]) do |record, attr|
@@ -123,7 +120,7 @@ def test_validates_each_custom_reader
hits += 1
end
t = CustomReader.new("title" => "valid", "content" => "whatever")
- assert !t.valid?
+ assert t.invalid?
assert_equal 4, hits
assert_equal %w(gotcha gotcha), t.errors[:title]
assert_equal %w(gotcha gotcha), t.errors[:content]
@@ -131,49 +128,51 @@ def test_validates_each_custom_reader
def test_validate_block
Topic.validate { |topic| topic.errors.add("title", "will never be valid") }
- t = Topic.create("title" => "Title", "content" => "whatever")
- assert !t.valid?
+ t = Topic.new("title" => "Title", "content" => "whatever")
+ assert t.invalid?
assert t.errors[:title].any?
assert_equal ["will never be valid"], t.errors["title"]
end
def test_invalid_validator
Topic.validate :i_dont_exist
- assert_raise(NameError) { t = Topic.create }
+ assert_raise(NameError) do
+ t = Topic.new
+ t.valid?
+ end
end
def test_errors_to_xml
r = Reply.new :title => "Wrong Create"
- assert !r.valid?
+ assert r.invalid?
xml = r.errors.to_xml(:skip_instruct => true)
assert_equal "<errors>", xml.first(8)
- assert xml.include?("<error>Title is Wrong Create</error>")
- assert xml.include?("<error>Content Empty</error>")
+ assert xml.include?("<error>Content is Empty</error>")
end
def test_validation_order
- Topic.validates_presence_of :title
- Topic.validates_length_of :title, :minimum => 2
+ Topic.validates_presence_of :title
+ Topic.validates_length_of :title, :minimum => 2
- t = Topic.new("title" => "")
- assert !t.valid?
- assert_equal "can't be blank", t.errors["title"].first
+ t = Topic.new("title" => "")
+ assert t.invalid?
+ assert_equal "can't be blank", t.errors["title"].first
Topic.validates_presence_of :title, :author_name
Topic.validate {|topic| topic.errors.add('author_email_address', 'will never be valid')}
Topic.validates_length_of :title, :content, :minimum => 2
t = Topic.new :title => ''
- assert !t.valid?
-
- assert_equal :title, key = t.errors.keys.first
- assert_equal "can't be blank", t.errors[key].first
- assert_equal 'is too short (minimum is 2 characters)', t.errors[key].second
- assert_equal :author_name, key = t.errors.keys.second
- assert_equal "can't be blank", t.errors[key].first
- assert_equal :author_email_address, key = t.errors.keys.third
- assert_equal 'will never be valid', t.errors[key].first
- assert_equal :content, key = t.errors.keys.fourth
- assert_equal 'is too short (minimum is 2 characters)', t.errors[key].first
+ assert t.invalid?
+
+ assert_equal :title, key = t.errors.keys[0]
+ assert_equal "can't be blank", t.errors[key][0]
+ assert_equal 'is too short (minimum is 2 characters)', t.errors[key][1]
+ assert_equal :author_name, key = t.errors.keys[1]
+ assert_equal "can't be blank", t.errors[key][0]
+ assert_equal :author_email_address, key = t.errors.keys[2]
+ assert_equal 'will never be valid', t.errors[key][0]
+ assert_equal :content, key = t.errors.keys[3]
+ assert_equal 'is too short (minimum is 2 characters)', t.errors[key][0]
end
def test_invalid_should_be_the_opposite_of_valid
@@ -227,7 +226,7 @@ def test_validation_with_message_as_proc
Topic.validates_presence_of(:title, :message => proc { "no blanks here".upcase })
t = Topic.new
- assert !t.valid?
+ assert t.invalid?
assert ["NO BLANKS HERE"], t.errors[:title]
end
View
41 activemodel/test/fixtures/topics.yml
@@ -1,41 +0,0 @@
-first:
- id: 1
- title: The First Topic
- author_name: David
- author_email_address: david@loudthinking.com
- written_on: 2003-07-16t15:28:11.2233+01:00
- last_read: 2004-04-15
- bonus_time: 2005-01-30t15:28:00.00+01:00
- content: Have a nice day
- approved: false
- replies_count: 1
-
-second:
- id: 2
- title: The Second Topic of the day
- author_name: Mary
- written_on: 2004-07-15t15:28:00.0099+01:00
- content: Have a nice day
- approved: true
- replies_count: 0
- parent_id: 1
- type: Reply
-
-third:
- id: 3
- title: The Third Topic of the day
- author_name: Nick
- written_on: 2005-07-15t15:28:00.0099+01:00
- content: I'm a troll
- approved: true
- replies_count: 1
-
-fourth:
- id: 4
- title: The Fourth Topic of the day
- author_name: Carl
- written_on: 2006-07-15t15:28:00.0099+01:00
- content: Why not?
- approved: true
- type: Reply
- parent_id: 3
View
6 activemodel/test/models/developer.rb
@@ -1,6 +0,0 @@
-class Developer < ActiveRecord::Base
- validates_inclusion_of :salary, :in => 50000..200000
- validates_length_of :name, :within => 3..20
-
- attr_accessor :name_confirmation
-end
View
16 activemodel/test/models/reply.rb
@@ -2,33 +2,31 @@
class Reply < Topic
validate :errors_on_empty_content
- validate :title_is_wrong_create, :on => :create
+ validate :title_is_wrong_create, :on => :create
validate :check_empty_title
validate :check_content_mismatch, :on => :create
- validate :check_wrong_update, :on => :update
-
- attr_accessible :title, :author_name, :author_email_address, :written_on, :content, :last_read
+ validate :check_wrong_update, :on => :update
def check_empty_title
- errors[:title] << "Empty" unless attribute_present?("title")
+ errors[:title] << "is Empty" unless title && title.size > 0
end
def errors_on_empty_content
- errors[:content] << "Empty" unless attribute_present?("content")
+ errors[:content] << "is Empty" unless content && content.size > 0
end
def check_content_mismatch
- if attribute_present?("title") && attribute_present?("content") && content == "Mismatch"
+ if title && content && content == "Mismatch"
errors[:title] << "is Content Mismatch"
end
end
def title_is_wrong_create
- errors[:title] << "is Wrong Create" if attribute_present?("title") && title == "Wrong Create"
+ errors[:title] << "is Wrong Create" if title && title == "Wrong Create"
end
def check_wrong_update
- errors[:title] << "is Wrong Update" if attribute_present?("title") && title == "Wrong Update"
+ errors[:title] << "is Wrong Update" if title && title == "Wrong Update"
end
end
View
12 activemodel/test/models/topic.rb
@@ -1,4 +1,14 @@
-class Topic < ActiveRecord::Base
+class Topic
+ include ActiveModel::Validations
+
+ attr_accessor :title, :author_name, :content, :approved
+
+ def initialize(attributes = {})
+ attributes.each do |key, value|
+ send "#{key}=", value
+ end
+ end
+
def condition_is_true
true
end
View
14 activemodel/test/schema.rb
@@ -1,14 +0,0 @@
-ActiveRecord::Schema.define do
- create_table :topics, :force => true do |t|
- t.string :title
- t.string :author_name
- t.text :content
- t.boolean :approved, :default => true
- t.string :type
- end
-
- create_table :developers, :force => true do |t|
- t.string :name
- t.float :salary
- end
-end
View
2  activerecord/CHANGELOG
@@ -1,5 +1,7 @@
*Rails 3.0.0 [beta 4/release candidate] (unreleased)*
+* find_or_create_by_attr(value, ...) works when attr is protected. #4457 [Santiago Pastorino, Marc-André Lafortune]
+
* New callbacks: after_commit and after_rollback. Do expensive operations like image thumbnailing after_commit instead of after_save. #2991 [Brian Durand]
* Serialized attributes are not converted to YAML if they are any of the formats that can be serialized to XML (like Hash, Array and Strings). [José Valim]
View
2  activerecord/lib/active_record.rb
@@ -61,6 +61,7 @@ module ActiveRecord
autoload :Base
autoload :Callbacks
+ autoload :CounterCache
autoload :DynamicFinderMatch
autoload :DynamicScopeMatch
autoload :Migration
@@ -68,6 +69,7 @@ module ActiveRecord
autoload :NamedScope
autoload :NestedAttributes
autoload :Observer
+ autoload :Persistence
autoload :QueryCache
autoload :Reflection
autoload :Schema
View
1  activerecord/lib/active_record/aggregations.rb
@@ -253,6 +253,7 @@ def writer_method(name, class_name, mapping, allow_nil, converter)
raise ArgumentError, 'Converter must be a symbol denoting the converter method to call or a Proc to be invoked.'
end
end
+
mapping.each { |pair| self[pair.first] = part.send(pair.last) }
instance_variable_set("@#{name}", part.freeze)
end
View
16 activerecord/lib/active_record/associations.rb
@@ -1304,14 +1304,14 @@ def has_and_belongs_to_many(association_id, options = {}, &extension)
# Don't use a before_destroy callback since users' before_destroy
# callbacks will be executed after the association is wiped out.
- old_method = "destroy_without_habtm_shim_for_#{reflection.name}"
- class_eval <<-end_eval unless method_defined?(old_method)
- alias_method :#{old_method}, :destroy_without_callbacks # alias_method :destroy_without_habtm_shim_for_posts, :destroy_without_callbacks
- def destroy_without_callbacks # def destroy_without_callbacks
- #{reflection.name}.clear # posts.clear
- #{old_method} # destroy_without_habtm_shim_for_posts
- end # end
- end_eval
+ include Module.new {
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def destroy # def destroy
+ super # super
+ #{reflection.name}.clear # posts.clear
+ end # end
+ RUBY
+ }
add_association_callbacks(reflection.name, options)
end
View
2  activerecord/lib/active_record/associations/association_proxy.rb
@@ -51,7 +51,7 @@ class AssociationProxy #:nodoc:
alias_method :proxy_respond_to?, :respond_to?
alias_method :proxy_extend, :extend
delegate :to_param, :to => :proxy_target
- instance_methods.each { |m| undef_method m unless m =~ /^(?:nil\?|send|object_id|to_a)$|^__|proxy_/ }
+ instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|proxy_/ }
def initialize(owner, reflection)
@owner, @reflection = owner, reflection
View
11 activerecord/lib/active_record/attribute_methods.rb
@@ -18,10 +18,19 @@ def define_attribute_methods
def instance_method_already_implemented?(method_name)
method_name = method_name.to_s
@_defined_class_methods ||= ancestors.first(ancestors.index(ActiveRecord::Base)).sum([]) { |m| m.public_instance_methods(false) | m.private_instance_methods(false) | m.protected_instance_methods(false) }.map {|m| m.to_s }.to_set
- @@_defined_activerecord_methods ||= (ActiveRecord::Base.public_instance_methods(false) | ActiveRecord::Base.private_instance_methods(false) | ActiveRecord::Base.protected_instance_methods(false)).map{|m| m.to_s }.to_set
+ @@_defined_activerecord_methods ||= defined_activerecord_methods
raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord" if @@_defined_activerecord_methods.include?(method_name)
@_defined_class_methods.include?(method_name)
end
+
+ def defined_activerecord_methods
+ active_record = ActiveRecord::Base
+ super_klass = ActiveRecord::Base.superclass
+ methods = active_record.public_instance_methods - super_klass.public_instance_methods
+ methods += active_record.private_instance_methods - super_klass.private_instance_methods
+ methods += active_record.protected_instance_methods - super_klass.protected_instance_methods
+ methods.map {|m| m.to_s }.to_set
+ end
end
def method_missing(method_id, *args, &block)
View
100 activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -5,20 +5,20 @@ module AttributeMethods
module Dirty
extend ActiveSupport::Concern
include ActiveModel::Dirty
+ include AttributeMethods::Write
included do
- alias_method_chain :save, :dirty
- alias_method_chain :save!, :dirty
- alias_method_chain :update, :dirty
- alias_method_chain :reload, :dirty
+ if self < Timestamp
+ raise "You cannot include Dirty after Timestamp"
+ end
superclass_delegating_accessor :partial_updates
self.partial_updates = true
end
# Attempts to +save+ the record and clears changed attributes if successful.