aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionmailer/CHANGELOG.md23
-rw-r--r--actionmailer/lib/action_mailer/base.rb2
-rw-r--r--actionmailer/test/base_test.rb27
-rw-r--r--actionmailer/test/fixtures/base_mailer/implicit_with_locale.de-AT.text.erb1
-rw-r--r--actionmailer/test/fixtures/base_mailer/implicit_with_locale.de.html.erb1
-rw-r--r--actionpack/CHANGELOG.md4
-rw-r--r--actionview/lib/action_view/lookup_context.rb9
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/lib/active_record/validations.rb1
-rw-r--r--activerecord/lib/active_record/validations/length.rb21
-rw-r--r--activerecord/test/cases/validations/length_validation_test.rb18
-rw-r--r--activerecord/test/models/owner.rb2
-rw-r--r--guides/source/testing.md107
13 files changed, 145 insertions, 78 deletions
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md
index 88b0962e8c..2f9c0dd7a3 100644
--- a/actionmailer/CHANGELOG.md
+++ b/actionmailer/CHANGELOG.md
@@ -1 +1,24 @@
+* Template lookup now respect default locale and I18n fallbacks.
+
+ Given the following templates:
+
+ mailer/demo.html.erb
+ mailer/demo.en.html.erb
+ mailer/demo.pt.html.erb
+
+ Before this change for a locale that doesn't have its related file the `mailer/demo.html.erb` will
+ be rendered even if `en` is the default locale.
+
+ Now `mailer/demo.en.html.erb` has precedence over the file without locale.
+
+ Also, it is possible to give a fallback.
+
+ mailer/demo.pt.html.erb
+ mailer/demo.pt-BR.html.erb
+
+ So if the locale is `pt-PT`, `mailer/demo.pt.html.erb` will be rendered given the right I18n
+ fallback configuration.
+
+ *Rafael Mendonça França*
+
Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/actionmailer/CHANGELOG.md) for previous changes.
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 021a758940..53cc1fdb31 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -586,8 +586,6 @@ module ActionMailer
}
ActiveSupport::Notifications.instrument("process.action_mailer", payload) do
- lookup_context.skip_default_locale!
-
super
@_message = NullMail.new unless @_mail_was_called
end
diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb
index 396d0a95b5..5d9eda2555 100644
--- a/actionmailer/test/base_test.rb
+++ b/actionmailer/test/base_test.rb
@@ -353,10 +353,35 @@ class BaseTest < ActiveSupport::TestCase
assert_equal("text/plain", email.parts[0].mime_type)
assert_equal("Implicit with locale PL TEXT", email.parts[0].body.encoded)
assert_equal("text/html", email.parts[1].mime_type)
- assert_equal("Implicit with locale HTML", email.parts[1].body.encoded)
+ assert_equal("Implicit with locale EN HTML", email.parts[1].body.encoded)
end
end
+ test "implicit multipart with fallback locale" do
+ fallback_backend = Class.new(I18n::Backend::Simple) do
+ include I18n::Backend::Fallbacks
+ end
+
+ begin
+ backend = I18n.backend
+ I18n.backend = fallback_backend.new
+ I18n.fallbacks[:"de-AT"] = [:de]
+
+ swap I18n, locale: 'de-AT' do
+ email = BaseMailer.implicit_with_locale
+ assert_equal(2, email.parts.size)
+ assert_equal("multipart/alternative", email.mime_type)
+ assert_equal("text/plain", email.parts[0].mime_type)
+ assert_equal("Implicit with locale DE-AT TEXT", email.parts[0].body.encoded)
+ assert_equal("text/html", email.parts[1].mime_type)
+ assert_equal("Implicit with locale DE HTML", email.parts[1].body.encoded)
+ end
+ ensure
+ I18n.backend = backend
+ end
+ end
+
+
test "implicit multipart with several view paths uses the first one with template" do
old = BaseMailer.view_paths
begin
diff --git a/actionmailer/test/fixtures/base_mailer/implicit_with_locale.de-AT.text.erb b/actionmailer/test/fixtures/base_mailer/implicit_with_locale.de-AT.text.erb
new file mode 100644
index 0000000000..e97505fad9
--- /dev/null
+++ b/actionmailer/test/fixtures/base_mailer/implicit_with_locale.de-AT.text.erb
@@ -0,0 +1 @@
+Implicit with locale DE-AT TEXT \ No newline at end of file
diff --git a/actionmailer/test/fixtures/base_mailer/implicit_with_locale.de.html.erb b/actionmailer/test/fixtures/base_mailer/implicit_with_locale.de.html.erb
new file mode 100644
index 0000000000..0536b5d3e2
--- /dev/null
+++ b/actionmailer/test/fixtures/base_mailer/implicit_with_locale.de.html.erb
@@ -0,0 +1 @@
+Implicit with locale DE HTML \ No newline at end of file
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 98b573e21e..839cbc76e7 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,7 @@
+* Fix how polymorphic routes works with objects that implement `to_model`.
+
+ *Travis Grathwell*
+
* Stop converting empty arrays in `params` to `nil`
This behaviour was introduced in response to CVE-2012-2660, CVE-2012-2694
diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb
index ea687d9cca..36855ec3d0 100644
--- a/actionview/lib/action_view/lookup_context.rb
+++ b/actionview/lib/action_view/lookup_context.rb
@@ -191,7 +191,6 @@ module ActionView
def initialize(view_paths, details = {}, prefixes = [])
@details, @details_key = {}, nil
- @skip_default_locale = false
@cache = true
@prefixes = prefixes
@rendered_format = nil
@@ -213,12 +212,6 @@ module ActionView
super(values)
end
- # Do not use the default locale on template lookup.
- def skip_default_locale!
- @skip_default_locale = true
- self.locale = nil
- end
-
# Override locale to return a symbol instead of array.
def locale
@details[:locale].first
@@ -233,7 +226,7 @@ module ActionView
config.locale = value
end
- super(@skip_default_locale ? I18n.locale : default_locale)
+ super(default_locale)
end
# Uses the first format in the formats array for layout lookup.
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 1c0e453fd8..53d5ec07a3 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,10 @@
+* `validates_size_of` / `validates_length_of` do not count records,
+ which are `marked_for_destruction?`.
+
+ Fixes #7247.
+
+ *Yves Senn*
+
* Ensure `first!` and friends work on loaded associations.
Fixes #18237.
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index a6c8ff7f3a..f27adc9c40 100644
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -88,3 +88,4 @@ end
require "active_record/validations/associated"
require "active_record/validations/uniqueness"
require "active_record/validations/presence"
+require "active_record/validations/length"
diff --git a/activerecord/lib/active_record/validations/length.rb b/activerecord/lib/active_record/validations/length.rb
new file mode 100644
index 0000000000..ef5a6cbbe7
--- /dev/null
+++ b/activerecord/lib/active_record/validations/length.rb
@@ -0,0 +1,21 @@
+module ActiveRecord
+ module Validations
+ class LengthValidator < ActiveModel::Validations::LengthValidator # :nodoc:
+ def validate_each(record, attribute, association_or_value)
+ if association_or_value.respond_to?(:loaded?) && association_or_value.loaded?
+ association_or_value = association_or_value.target.reject(&:marked_for_destruction?)
+ end
+ super
+ end
+ end
+
+ module ClassMethods
+ # See <tt>ActiveModel::Validation::LengthValidator</tt> for more information.
+ def validates_length_of(*attr_names)
+ validates_with LengthValidator, _merge_attributes(attr_names)
+ end
+
+ alias_method :validates_size_of, :validates_length_of
+ end
+ end
+end
diff --git a/activerecord/test/cases/validations/length_validation_test.rb b/activerecord/test/cases/validations/length_validation_test.rb
index 4a92da38ce..2c0e282761 100644
--- a/activerecord/test/cases/validations/length_validation_test.rb
+++ b/activerecord/test/cases/validations/length_validation_test.rb
@@ -2,6 +2,7 @@
require "cases/helper"
require 'models/owner'
require 'models/pet'
+require 'models/person'
class LengthValidationTest < ActiveRecord::TestCase
fixtures :owners
@@ -44,4 +45,21 @@ class LengthValidationTest < ActiveRecord::TestCase
assert o.valid?
end
end
+
+ def test_validates_size_of_reprects_records_marked_for_destruction
+ assert_nothing_raised { Owner.validates_size_of :pets, minimum: 1 }
+ owner = Owner.new
+ assert_not owner.save
+ assert owner.errors[:pets].any?
+ pet = owner.pets.build
+ assert owner.valid?
+ assert owner.save
+
+ pet_count = Pet.count
+ assert_not owner.update_attributes pets_attributes: [ {_destroy: 1, id: pet.id} ]
+ assert_not owner.valid?
+ assert owner.errors[:pets].any?
+ assert_equal pet_count, Pet.count
+ end
+
end
diff --git a/activerecord/test/models/owner.rb b/activerecord/test/models/owner.rb
index 2e3a9a3681..cedb774b10 100644
--- a/activerecord/test/models/owner.rb
+++ b/activerecord/test/models/owner.rb
@@ -17,6 +17,8 @@ class Owner < ActiveRecord::Base
after_commit :execute_blocks
+ accepts_nested_attributes_for :pets, allow_destroy: true
+
def blocks
@blocks ||= []
end
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 144a92df3e..829686b82e 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -141,6 +141,27 @@ users(:david).id
email(david.girlfriend.email, david.location_tonight)
```
+### Rake Tasks for Running your Tests
+
+Rails comes with a number of built-in rake tasks to help with testing. The
+table below lists the commands included in the default Rakefile when a Rails
+project is created.
+
+| Tasks | Description |
+| ----------------------- | ----------- |
+| `rake test` | Runs all tests in the `test` directory. You can also run `rake` and Rails will run all tests by default |
+| `rake test:controllers` | Runs all the controller tests from `test/controllers` |
+| `rake test:functionals` | Runs all the functional tests from `test/controllers`, `test/mailers`, and `test/functional` |
+| `rake test:helpers` | Runs all the helper tests from `test/helpers` |
+| `rake test:integration` | Runs all the integration tests from `test/integration` |
+| `rake test:jobs` | Runs all the job tests from `test/jobs` |
+| `rake test:mailers` | Runs all the mailer tests from `test/mailers` |
+| `rake test:models` | Runs all the model tests from `test/models` |
+| `rake test:units` | Runs all the unit tests from `test/models`, `test/helpers`, and `test/unit` |
+| `rake test:db` | Runs all tests in the `test` directory and resets the db |
+
+We will cover each of types Rails tests listed above in this guide.
+
Unit Testing your Models
------------------------
@@ -388,44 +409,9 @@ This test should now pass.
By now you've caught a glimpse of some of the assertions that are available. Assertions are the worker bees of testing. They are the ones that actually perform the checks to ensure that things are going as planned.
-There are a bunch of different types of assertions you can use.
-Here's an extract of the assertions you can use with [`Minitest`](https://github.com/seattlerb/minitest), the default testing library used by Rails. The `[msg]` parameter is an optional string message you can specify to make your test failure messages clearer. It's not required.
-
-| Assertion | Purpose |
-| ---------------------------------------------------------------- | ------- |
-| `assert( test, [msg] )` | Ensures that `test` is true.|
-| `assert_not( test, [msg] )` | Ensures that `test` is false.|
-| `assert_equal( expected, actual, [msg] )` | Ensures that `expected == actual` is true.|
-| `assert_not_equal( expected, actual, [msg] )` | Ensures that `expected != actual` is true.|
-| `assert_same( expected, actual, [msg] )` | Ensures that `expected.equal?(actual)` is true.|
-| `assert_not_same( expected, actual, [msg] )` | Ensures that `expected.equal?(actual)` is false.|
-| `assert_nil( obj, [msg] )` | Ensures that `obj.nil?` is true.|
-| `assert_not_nil( obj, [msg] )` | Ensures that `obj.nil?` is false.|
-| `assert_empty( obj, [msg] )` | Ensures that `obj` is `empty?`.|
-| `assert_not_empty( obj, [msg] )` | Ensures that `obj` is not `empty?`.|
-| `assert_match( regexp, string, [msg] )` | Ensures that a string matches the regular expression.|
-| `assert_no_match( regexp, string, [msg] )` | Ensures that a string doesn't match the regular expression.|
-| `assert_includes( collection, obj, [msg] )` | Ensures that `obj` is in `collection`.|
-| `assert_not_includes( collection, obj, [msg] )` | Ensures that `obj` is not in `collection`.|
-| `assert_in_delta( expecting, actual, [delta], [msg] )` | Ensures that the numbers `expected` and `actual` are within `delta` of each other.|
-| `assert_not_in_delta( expecting, actual, [delta], [msg] )` | Ensures that the numbers `expected` and `actual` are not within `delta` of each other.|
-| `assert_throws( symbol, [msg] ) { block }` | Ensures that the given block throws the symbol.|
-| `assert_raises( exception1, exception2, ... ) { block }` | Ensures that the given block raises one of the given exceptions.|
-| `assert_nothing_raised( exception1, exception2, ... ) { block }` | Ensures that the given block doesn't raise one of the given exceptions.|
-| `assert_instance_of( class, obj, [msg] )` | Ensures that `obj` is an instance of `class`.|
-| `assert_not_instance_of( class, obj, [msg] )` | Ensures that `obj` is not an instance of `class`.|
-| `assert_kind_of( class, obj, [msg] )` | Ensures that `obj` is or descends from `class`.|
-| `assert_not_kind_of( class, obj, [msg] )` | Ensures that `obj` is not an instance of `class` and is not descending from it.|
-| `assert_respond_to( obj, symbol, [msg] )` | Ensures that `obj` responds to `symbol`.|
-| `assert_not_respond_to( obj, symbol, [msg] )` | Ensures that `obj` does not respond to `symbol`.|
-| `assert_operator( obj1, operator, [obj2], [msg] )` | Ensures that `obj1.operator(obj2)` is true.|
-| `assert_not_operator( obj1, operator, [obj2], [msg] )` | Ensures that `obj1.operator(obj2)` is false.|
-| `assert_predicate ( obj, predicate, [msg] )` | Ensures that `obj.predicate` is true, e.g. `assert_predicate str, :empty?`|
-| `assert_not_predicate ( obj, predicate, [msg] )` | Ensures that `obj.predicate` is false, e.g. `assert_not_predicate str, :empty?`|
-| `assert_send( array, [msg] )` | Ensures that executing the method listed in `array[1]` on the object in `array[0]` with the parameters of `array[2 and up]` is true. This one is weird eh?|
-| `flunk( [msg] )` | Ensures failure. This is useful to explicitly mark a test that isn't finished yet.|
-
-The above are subset of assertions that minitest supports. For an exhaustive & more up-to-date list, please check [Minitest API documentation](http://docs.seattlerb.org/minitest/), specifically [`Minitest::Assertions`](http://docs.seattlerb.org/minitest/Minitest/Assertions.html)
+There are a bunch of different types of assertions you can use that come with [`Minitest`](https://github.com/seattlerb/minitest), the default testing library used by Rails.
+
+For a list of all available assertions please check the [Minitest API documentation](http://docs.seattlerb.org/minitest/), specifically [`Minitest::Assertions`](http://docs.seattlerb.org/minitest/Minitest/Assertions.html)
Because of the modular nature of the testing framework, it is possible to create your own assertions. In fact, that's exactly what Rails does. It includes some specialized assertions to make your life easier.
@@ -447,6 +433,22 @@ Rails adds some custom assertions of its own to the `minitest` framework:
You'll see the usage of some of these assertions in the next chapter.
+### A Brief Note About Minitest
+
+All the basic assertions such as `assert_equal` defined in `Minitest::Assertions` are also available in the classes we use in our own test cases. In fact, Rails provides the following classes for you to inherit from:
+
+* `ActiveSupport::TestCase`
+* `ActionController::TestCase`
+* `ActionMailer::TestCase`
+* `ActionView::TestCase`
+* `ActionDispatch::IntegrationTest`
+
+Each of these classes include `Minitest::Assertions`, allowing us to use all of the basic assertions in our tests.
+
+NOTE: For more information on `Minitest`, refer to [Minitest](http://ruby-doc.org/stdlib-2.1.0/libdoc/minitest/rdoc/MiniTest.html)
+
+There are many benefits to using Minitest, one of them is the addition of setup and teardown methods for all test classes that inherit from the Minitest family.
+
Functional Tests for Your Controllers
-------------------------------------
@@ -795,35 +797,6 @@ In addition to the standard testing helpers, there are some additional helpers a
| `delete_via_redirect(path, [parameters], [headers])` | Allows you to make an HTTP DELETE request and follow any subsequent redirects.|
| `open_session` | Opens a new session instance.|
-
-Rake Tasks for Running your Tests
----------------------------------
-
-Rails comes with a number of built-in rake tasks to help with testing. The
-table below lists the commands included in the default Rakefile when a Rails
-project is created.
-
-| Tasks | Description |
-| ----------------------- | ----------- |
-| `rake test` | Runs all tests in the `test` directory. You can also run `rake` and Rails will run all tests by default |
-| `rake test:controllers` | Runs all the controller tests from `test/controllers` |
-| `rake test:functionals` | Runs all the functional tests from `test/controllers`, `test/mailers`, and `test/functional` |
-| `rake test:helpers` | Runs all the helper tests from `test/helpers` |
-| `rake test:integration` | Runs all the integration tests from `test/integration` |
-| `rake test:jobs` | Runs all the job tests from `test/jobs` |
-| `rake test:mailers` | Runs all the mailer tests from `test/mailers` |
-| `rake test:models` | Runs all the model tests from `test/models` |
-| `rake test:units` | Runs all the unit tests from `test/models`, `test/helpers`, and `test/unit` |
-| `rake test:db` | Runs all tests in the `test` directory and resets the db |
-
-
-A Brief Note About Minitest
------------------------------
-
-Ruby ships with a vast Standard Library for all common use-cases including testing. Since version 1.9, Ruby provides `Minitest`, a framework for testing. All the basic assertions such as `assert_equal` discussed above are actually defined in `Minitest::Assertions`. The classes `ActiveSupport::TestCase`, `ActionController::TestCase`, `ActionMailer::TestCase`, `ActionView::TestCase` and `ActionDispatch::IntegrationTest` - which we have been inheriting in our test classes - include `Minitest::Assertions`, allowing us to use all of the basic assertions in our tests.
-
-NOTE: For more information on `Minitest`, refer to [Minitest](http://ruby-doc.org/stdlib-2.1.0/libdoc/minitest/rdoc/MiniTest.html)
-
Setup and Teardown
------------------