aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionmailer/CHANGELOG.md4
-rw-r--r--actionpack/CHANGELOG.md22
-rw-r--r--actionpack/lib/action_controller/log_subscriber.rb5
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb3
-rw-r--r--actionpack/lib/action_view/helpers/capture_helper.rb2
-rw-r--r--activerecord/CHANGELOG.md53
-rw-r--r--activerecord/lib/active_record/associations.rb6
-rw-r--r--activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb2
-rw-r--r--activerecord/lib/active_record/core.rb1
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb4
-rw-r--r--activerecord/lib/active_record/persistence.rb2
-rw-r--r--activerecord/lib/active_record/validations/uniqueness.rb10
-rw-r--r--activerecord/test/cases/fixtures_test.rb5
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb8
-rw-r--r--activerecord/test/cases/validations/uniqueness_validation_test.rb8
-rw-r--r--guides/source/4_0_release_notes.md6
-rw-r--r--guides/source/action_controller_overview.md14
-rw-r--r--guides/source/action_mailer_basics.md15
-rw-r--r--guides/source/active_record_querying.md57
-rw-r--r--guides/source/active_support_instrumentation.md2
-rw-r--r--guides/source/association_basics.md4
-rw-r--r--guides/source/upgrading_ruby_on_rails.md6
-rw-r--r--railties/CHANGELOG.md14
-rw-r--r--railties/test/application/console_test.rb4
25 files changed, 185 insertions, 78 deletions
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md
index 8f74ac0928..487e57be7b 100644
--- a/actionmailer/CHANGELOG.md
+++ b/actionmailer/CHANGELOG.md
@@ -21,7 +21,7 @@
*Olek Janiszewski*
* Eager loading made to use relation's `in_clause_length` instead of host's one.
- Fix #8474
+ Fixes #8474.
*Boris Staal*
@@ -29,7 +29,7 @@
*Nate Berkopec*
* Do not render views when mail() isn't called.
- Fix #7761
+ Fixes #7761.
*Yves Senn*
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index f757911c23..157a038b7c 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -252,12 +252,12 @@
Client-IP and Remote-Addr headers, in that order. Document the rationale
for that decision, and describe the options that can be passed to the
RemoteIp middleware to change it.
- Fix #7979
+ Fixes #7979.
*André Arko*, *Steve Klabnik*, *Alexey Gaziev*
* Do not append second slash to `root_url` when using `trailing_slash: true`
- Fix #8700
+ Fixes #8700.
Before:
@@ -285,7 +285,7 @@
* Do not append `charset=` parameter when `head` is called with a
`:content_type` option.
- Fix #8661.
+ Fixes #8661.
*Yves Senn*
@@ -443,7 +443,7 @@
* Render every partial with a new `ActionView::PartialRenderer`. This resolves
issues when rendering nested partials.
- Fix #8197.
+ Fixes #8197.
*Yves Senn*
@@ -451,7 +451,7 @@
of mime types where template text is not html escaped by default. It prevents `Jack & Joe`
from rendering as `Jack & Joe` for the whitelisted mime types. The default whitelist
contains `text/plain`.
- Fix #7976.
+ Fixes #7976.
*Joost Baaij*
@@ -467,7 +467,7 @@
check_box("post", "comment_ids", { multiple: true, index: "foo" }, 1)
# => <input name=\"post[foo][comment_ids][]\" type=\"hidden\" value=\"0\" /><input id=\"post_foo_comment_ids_1\" name=\"post[foo][comment_ids][]\" type=\"checkbox\" value=\"1\" />
- Fix #8108.
+ Fixes #8108.
*Daniel Fox, Grant Hutchins & Trace Wax*
@@ -490,7 +490,7 @@
*Josh Peek*
* `assert_template` can be used to assert on the same template with different locals
- Fix #3675.
+ Fixes #3675.
*Yves Senn*
@@ -501,7 +501,7 @@
* Accept `:remote` as symbolic option for `link_to` helper. *Riley Lynch*
* Warn when the `:locals` option is passed to `assert_template` outside of a view test case
- Fix #3415.
+ Fixes #3415.
*Yves Senn*
@@ -525,12 +525,12 @@
* Rename internal variables on `ActionController::TemplateAssertions` to prevent
naming collisions. `@partials`, `@templates` and `@layouts` are now prefixed with an underscore.
- Fix #7459.
+ Fixes #7459.
*Yves Senn*
* `resource` and `resources` don't modify the passed options hash.
- Fix #7777.
+ Fixes #7777.
*Yves Senn*
@@ -594,7 +594,7 @@
*Guillermo Iguaran*
* Log now displays the correct status code when an exception is raised.
- Fix #7646.
+ Fixes #7646.
*Yves Senn*
diff --git a/actionpack/lib/action_controller/log_subscriber.rb b/actionpack/lib/action_controller/log_subscriber.rb
index 3d274e7dd7..7318c8b7ec 100644
--- a/actionpack/lib/action_controller/log_subscriber.rb
+++ b/actionpack/lib/action_controller/log_subscriber.rb
@@ -48,6 +48,11 @@ module ActionController
info("Sent data #{event.payload[:filename]} (#{event.duration.round(1)}ms)")
end
+ def unpermitted_parameters(event)
+ unpermitted_keys = event.payload[:keys]
+ debug("Unpermitted parameters: #{unpermitted_keys.join(", ")}")
+ end
+
%w(write_fragment read_fragment exist_fragment?
expire_fragment expire_page write_page).each do |method|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index e4dcd3213f..acad8a0799 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -339,7 +339,8 @@ module ActionController
if unpermitted_keys.any?
case self.class.action_on_unpermitted_parameters
when :log
- ActionController::Base.logger.debug "Unpermitted parameters: #{unpermitted_keys.join(", ")}"
+ name = "unpermitted_parameters.action_controller"
+ ActiveSupport::Notifications.instrument(name, keys: unpermitted_keys)
when :raise
raise ActionController::UnpermittedParameters.new(unpermitted_keys)
end
diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb
index 1bad82159a..5afe435459 100644
--- a/actionpack/lib/action_view/helpers/capture_helper.rb
+++ b/actionpack/lib/action_view/helpers/capture_helper.rb
@@ -180,7 +180,7 @@ module ActionView
# <title>My Website</title>
# <%= yield :script %>
# </head>
- # <body class="<%= content_for?(:right_col) ? 'one-column' : 'two-column' %>">
+ # <body class="<%= content_for?(:right_col) ? 'two-column' : 'one-column' %>">
# <%= yield %>
# <%= yield :right_col %>
# </body>
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 49f7b03464..33ba77bca2 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,12 +1,26 @@
## Rails 4.0.0 (unreleased) ##
+* Uniqueness validation allows you to pass `:conditions` to limit
+ the constraint lookup.
+
+ Example:
+
+ validates_uniqueness_of :title, conditions: -> { where('approved = ?', true) }
+
+ *Mattias Pfeiffer + Yves Senn*
+
+* `connection` is deprecated as an instance method.
+ This allows end-users to have a `connection` method on their models
+ without clashing with Active Record internals.
+
+ *Ben Moss*
+
* When copying migrations, preserve their magic comments and content encoding.
*OZAWA Sakuro*
-* Fix ActiveRecord `subclass_from_attrs` when `eager_load` is false.
- It cannot find subclass because all classes are loaded automatically
- when it needs.
+* Fix `subclass_from_attrs` when `eager_load` is false. It cannot find
+ subclass because all classes are loaded automatically when it needs.
*Dmitry Vorotilin*
@@ -120,7 +134,7 @@
*Yves Senn*
* Assigning "0.0" to a nullable numeric column does not make it dirty.
- Fix #9034.
+ Fixes #9034.
Example:
@@ -555,17 +569,17 @@
*Marc-André Lafortune*
* Serialized attributes can be serialized in integer columns.
- Fix #8575.
+ Fixes #8575.
*Rafael Mendonça França*
* Keep index names when using `alter_table` with sqlite3.
- Fix #3489.
+ Fixes #3489.
*Yves Senn*
* Add ability for postgresql adapter to disable user triggers in `disable_referential_integrity`.
- Fix #5523.
+ Fixes #5523.
*Gary S. Weaver*
@@ -588,7 +602,7 @@
*Matthew Robertson*
* Recognize migrations placed in directories containing numbers and 'rb'.
- Fix #8492
+ Fixes #8492.
*Yves Senn*
@@ -646,13 +660,13 @@
* Fix performance problem with `primary_key` method in PostgreSQL adapter when having many schemas.
Uses `pg_constraint` table instead of `pg_depend` table which has many records in general.
- Fix #8414
+ Fixes #8414.
*kennyj*
* Do not instantiate intermediate Active Record objects when eager loading.
These records caused `after_find` to run more than expected.
- Fix #3313
+ Fixes #3313.
*Yves Senn*
@@ -673,12 +687,13 @@
* Fix dirty attribute checks for `TimeZoneConversion` with nil and blank
datetime attributes. Setting a nil datetime to a blank string should not
- result in a change being flagged. Fix #8310
+ result in a change being flagged.
+ Fixes #8310.
*Alisdair McDiarmid*
* Prevent mass assignment to the type column of polymorphic associations when using `build`
- Fix #8265
+ Fixes #8265.
*Yves Senn*
@@ -731,7 +746,7 @@
*Bogdan Gusiev*
* `:counter_cache` option for `has_many` associations to support custom named counter caches.
- Fix #7993
+ Fixes #7993.
*Yves Senn*
@@ -755,7 +770,7 @@
*Nikita Afanasenko*
* Use query cache/uncache when using `DATABASE_URL`.
- Fix #6951.
+ Fixes #6951.
*kennyj*
@@ -764,7 +779,7 @@
*Henrik Nyh*
* The `create_table` method raises an `ArgumentError` when the primary key column is redefined.
- Fix #6378
+ Fixes #6378.
*Yves Senn*
@@ -874,7 +889,7 @@
*Alexey Muranov*
* The postgres adapter now supports tables with capital letters.
- Fix #5920
+ Fixes #5920.
*Yves Senn*
@@ -896,7 +911,7 @@
*Francesco Rodriguez*
* Fix `reset_counters` crashing on `has_many :through` associations.
- Fix #7822.
+ Fixes #7822.
*lulalala*
@@ -971,7 +986,7 @@
*Guillermo Iguaran*
* Fix the return of querying with an empty hash.
- Fix #6971.
+ Fixes #6971.
User.where(token: {})
@@ -987,7 +1002,7 @@
* Fix creation of through association models when using `collection=[]`
on a `has_many :through` association from an unsaved model.
- Fix #7661.
+ Fixes #7661.
*Ernie Miller*
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 35e4eb19a4..519e9112b8 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1024,7 +1024,7 @@ module ActiveRecord
# [collection<<(object, ...)]
# Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
# Note that this operation instantly fires update sql without waiting for the save or update call on the
- # parent object.
+ # parent object, unless the parent object is a new record.
# [collection.delete(object, ...)]
# Removes one or more objects from the collection by setting their foreign keys to +NULL+.
# Objects will be in addition destroyed if they're associated with <tt>dependent: :destroy</tt>,
@@ -1231,7 +1231,7 @@ module ActiveRecord
# its owner is destroyed:
#
# * <tt>:destroy</tt> causes the associated object to also be destroyed
- # * <tt>:delete</tt> causes the asssociated object to be deleted directly from the database (so callbacks will not execute)
+ # * <tt>:delete</tt> causes the associated object to be deleted directly from the database (so callbacks will not execute)
# * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Callbacks are not executed.
# * <tt>:restrict_with_exception</tt> causes an exception to be raised if there is an associated record
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
@@ -1433,7 +1433,7 @@ module ActiveRecord
# Adds one or more objects to the collection by creating associations in the join table
# (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
# Note that this operation instantly fires update sql without waiting for the save or update call on the
- # parent object.
+ # parent object, unless the parent object is a new record.
# [collection.delete(object, ...)]
# Removes one or more objects from the collection by removing their associations from the join table.
# This does not destroy the objects.
diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
index 93618721bb..bb3e3db379 100644
--- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
@@ -26,7 +26,7 @@ module ActiveRecord
join_table[reflection.association_foreign_key] => record.id
)
- owner.connection.insert stmt
+ owner.class.connection.insert stmt
end
record
@@ -41,7 +41,7 @@ module ActiveRecord
def delete_records(records, method)
if sql = options[:delete_sql]
records = load_target if records == :all
- records.each { |record| owner.connection.delete(interpolate(sql, record)) }
+ records.each { |record| owner.class.connection.delete(interpolate(sql, record)) }
else
relation = join_table
condition = relation[reflection.foreign_key].eq(owner.id)
@@ -53,7 +53,7 @@ module ActiveRecord
)
end
- owner.connection.delete(relation.where(condition).compile_delete)
+ owner.class.connection.delete(relation.where(condition).compile_delete)
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 691b2ab37f..cfcc783904 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -594,7 +594,7 @@ module ActiveRecord
end
def enable_extension(name)
- exec_query("CREATE EXTENSION IF NOT EXISTS #{name}").tap {
+ exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\"").tap {
reload_type_map
}
end
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 899fe7d7c7..72371be657 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -324,6 +324,7 @@ module ActiveRecord
# also be used to "borrow" the connection to do database work that isn't
# easily done without going straight to SQL.
def connection
+ ActiveSupport::Deprecation.warn("#connection is deprecated in favour of accessing it via the class")
self.class.connection
end
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index 701949e57b..209de78898 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -86,7 +86,7 @@ module ActiveRecord
)
).arel.compile_update(arel_attributes_with_values_for_update(attribute_names))
- affected_rows = connection.update stmt
+ affected_rows = self.class.connection.update stmt
unless affected_rows == 1
raise ActiveRecord::StaleObjectError.new(self, "update")
@@ -117,7 +117,7 @@ module ActiveRecord
if locking_enabled?
column_name = self.class.locking_column
column = self.class.columns_hash[column_name]
- substitute = connection.substitute_at(column, relation.bind_values.length)
+ substitute = self.class.connection.substitute_at(column, relation.bind_values.length)
relation = relation.where(self.class.arel_table[column_name].eq(substitute))
relation.bind_values << [column, self[column_name].to_i]
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 347f023793..b25d0601cb 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -410,7 +410,7 @@ module ActiveRecord
def relation_for_destroy
pk = self.class.primary_key
column = self.class.columns_hash[pk]
- substitute = connection.substitute_at(column, 0)
+ substitute = self.class.connection.substitute_at(column, 0)
relation = self.class.unscoped.where(
self.class.arel_table[pk].eq(substitute))
diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb
index 1427189851..bf2aa2e959 100644
--- a/activerecord/lib/active_record/validations/uniqueness.rb
+++ b/activerecord/lib/active_record/validations/uniqueness.rb
@@ -2,6 +2,10 @@ module ActiveRecord
module Validations
class UniquenessValidator < ActiveModel::EachValidator # :nodoc:
def initialize(options)
+ if options[:conditions] && !options[:conditions].respond_to?(:call)
+ raise ArgumentError, "#{options[:conditions]} was passed as :conditions but is not callable. " \
+ "Pass a callable instead: `conditions: -> { where('approved = ?', true) }`"
+ end
super({ case_sensitive: true }.merge!(options))
end
@@ -19,7 +23,7 @@ module ActiveRecord
relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id)) if record.persisted?
relation = scope_relation(record, table, relation)
relation = finder_class.unscoped.where(relation)
- relation.merge!(options[:conditions]) if options[:conditions]
+ relation = relation.merge(options[:conditions]) if options[:conditions]
if relation.exists?
error_options = options.except(:case_sensitive, :scope, :conditions)
@@ -116,7 +120,7 @@ module ActiveRecord
# of the title attribute:
#
# class Article < ActiveRecord::Base
- # validates_uniqueness_of :title, conditions: where('status != ?', 'archived')
+ # validates_uniqueness_of :title, conditions: -> { where('status != ?', 'archived') }
# end
#
# When the record is created, a check is performed to make sure that no
@@ -132,7 +136,7 @@ module ActiveRecord
# the uniqueness constraint.
# * <tt>:conditions</tt> - Specify the conditions to be included as a
# <tt>WHERE</tt> SQL fragment to limit the uniqueness constraint lookup
- # (e.g. <tt>conditions: where('status = ?', 'active')</tt>).
+ # (e.g. <tt>conditions: -> { where('status = ?', 'active') }</tt>).
# * <tt>:case_sensitive</tt> - Looks for an exact match. Ignored by
# non-text columns (+true+ by default).
# * <tt>:allow_nil</tt> - If set to +true+, skips this validation if the
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index b0b29f5f42..8ad40ec3f4 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -477,9 +477,8 @@ class CustomConnectionFixturesTest < ActiveRecord::TestCase
fixtures :courses
self.use_transactional_fixtures = false
- def test_connection
- assert_kind_of Course, courses(:ruby)
- assert_equal Course.connection, courses(:ruby).connection
+ def test_connection_instance_method_deprecation
+ assert_deprecated { courses(:ruby).connection }
end
def test_leaky_destroy
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
index eb4ffd4498..766a5c0c90 100644
--- a/activerecord/test/cases/transaction_callbacks_test.rb
+++ b/activerecord/test/cases/transaction_callbacks_test.rb
@@ -182,9 +182,9 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
end
def test_call_after_rollback_when_commit_fails
- @first.connection.class.send(:alias_method, :real_method_commit_db_transaction, :commit_db_transaction)
+ @first.class.connection.class.send(:alias_method, :real_method_commit_db_transaction, :commit_db_transaction)
begin
- @first.connection.class.class_eval do
+ @first.class.connection.class.class_eval do
def commit_db_transaction; raise "boom!"; end
end
@@ -194,8 +194,8 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
assert !@first.save rescue nil
assert_equal [:after_rollback], @first.history
ensure
- @first.connection.class.send(:remove_method, :commit_db_transaction)
- @first.connection.class.send(:alias_method, :commit_db_transaction, :real_method_commit_db_transaction)
+ @first.class.connection.class.send(:remove_method, :commit_db_transaction)
+ @first.class.connection.class.send(:alias_method, :commit_db_transaction, :real_method_commit_db_transaction)
end
end
diff --git a/activerecord/test/cases/validations/uniqueness_validation_test.rb b/activerecord/test/cases/validations/uniqueness_validation_test.rb
index 46e767af1a..150e3c5461 100644
--- a/activerecord/test/cases/validations/uniqueness_validation_test.rb
+++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb
@@ -348,7 +348,7 @@ class UniquenessValidationTest < ActiveRecord::TestCase
end
def test_validate_uniqueness_with_conditions
- Topic.validates_uniqueness_of(:title, :conditions => Topic.where('approved = ?', true))
+ Topic.validates_uniqueness_of :title, conditions: -> { where('approved = ?', true) }
Topic.create("title" => "I'm a topic", "approved" => true)
Topic.create("title" => "I'm an unapproved topic", "approved" => false)
@@ -359,6 +359,12 @@ class UniquenessValidationTest < ActiveRecord::TestCase
assert t4.valid?, "t4 should be valid"
end
+ def test_validate_uniqueness_with_non_callable_conditions_is_not_supported
+ assert_raises(ArgumentError) {
+ Topic.validates_uniqueness_of :title, conditions: Topic.where('approved = ?', true)
+ }
+ end
+
def test_validate_uniqueness_with_array_column
return skip "Uniqueness on arrays has only been tested in PostgreSQL so far." if !current_adapter? :PostgreSQLAdapter
diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md
index 463da488f2..37afb25181 100644
--- a/guides/source/4_0_release_notes.md
+++ b/guides/source/4_0_release_notes.md
@@ -178,12 +178,6 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/master/activ
If migrating down, the given migration / block is run normally.
See the [Guide on Migration](https://github.com/rails/rails/blob/master/guides/source/migrations.md#reverting-previous-migrations)
-* Adds some metadata columns to `schema_migrations` table.
-
- * `migrated_at`
- * `fingerprint` - an md5 hash of the migration.
- * `name` - the filename minus version and extension.
-
* Adds PostgreSQL array type support. Any datatype can be used to create an array column, with full migration and schema dumper support.
* Add `Relation#load` to explicitly load the record and return `self`.
diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md
index 5861fc3d54..7e0a8a43d4 100644
--- a/guides/source/action_controller_overview.md
+++ b/guides/source/action_controller_overview.md
@@ -290,6 +290,20 @@ parameters:
params.require(:author).permit(:name, books_attributes: [:title, :id, :_destroy])
```
+Hashes with integer keys are treated differently and you can declare
+the attributes as if they were direct children. You get this kind of
+parameters when you use `accepts_nested_attributes_for` in combination
+with a `has_many` association:
+
+```ruby
+# To whitelist the following data:
+# {"book" => {"title" => "Some Book",
+# "chapters_attributes" => { "1" => {"title" => "First Chapter"},
+# "2" => {"title" => "Second Chapter"}}}}
+
+params.require(:book).permit(:title, chapters_attributes: [:title])
+```
+
#### Outside the Scope of Strong Parameters
The strong parameter API was designed with the most common use cases
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md
index 8720aae169..31182e9aed 100644
--- a/guides/source/action_mailer_basics.md
+++ b/guides/source/action_mailer_basics.md
@@ -403,7 +403,7 @@ If you wish to override the default delivery options (e.g. SMTP credentials) whi
```ruby
class UserMailer < ActionMailer::Base
- def welcome_email(user,company)
+ def welcome_email(user, company)
@user = user
@url = user_url(@user)
delivery_options = { user_name: company.smtp_user, password: company.smtp_password, address: company.smtp_host }
@@ -412,6 +412,19 @@ class UserMailer < ActionMailer::Base
end
```
+### Sending Emails without Template Rendering
+
+There may be cases in which you want to skip the template rendering step and supply the email body as a string. You can achieve this using the `:body` option.
+In such cases don't forget to add the `:content_type` option. Rails will default to `text/plain` otherwise.
+
+```ruby
+class UserMailer < ActionMailer::Base
+ def welcome_email(user, email_body)
+ mail(to: user.email, body: email_body, content_type: "text/html", subject: "Already rendered!")
+ end
+end
+```
+
Receiving Emails
----------------
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 0d0813c56a..4a4f814917 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -1196,6 +1196,61 @@ Using a class method is the preferred way to accept arguments for scopes. These
category.posts.created_before(time)
```
+### Merging of scopes
+
+Just like `where` clauses scopes are merged using `AND` conditions.
+
+```ruby
+class User < ActiveRecord::Base
+ scope :active, -> { where state: 'active' }
+ scope :inactive, -> { where state: 'inactive' }
+end
+
+```ruby
+User.active.inactive
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'inactive'
+```
+
+We can mix and match `scope` and `where` conditions and the final sql
+will have all conditions joined with `AND` .
+
+```ruby
+User.active.where(state: 'finished')
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'finished'
+```
+
+If we do want the `last where clause` to win then `Relation#merge` can
+be used .
+
+```ruby
+User.active.merge(User.inactive)
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
+```
+
+One important caveat is that `default_scope` will be overridden by
+`scope` and `where` conditions.
+
+```ruby
+class User < ActiveRecord::Base
+ default_scope { where state: 'pending' }
+ scope :active, -> { where state: 'active' }
+ scope :inactive, -> { where state: 'inactive' }
+end
+
+User.all
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
+
+User.active
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'active'
+
+User.where(state: 'inactive')
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
+```
+
+As you can see above the `default_scope` is being overridden by both
+`scope` and `where` conditions.
+
+
### Applying a default scope
If we wish for a scope to be applied across all queries to the model we can use the
@@ -1399,7 +1454,7 @@ Client.select(:id).map { |c| c.id }
# or
Client.select(:id).map(&:id)
# or
-Client.select(:id).map { |c| [c.id, c.name] }
+Client.select(:id, :name).map { |c| [c.id, c.name] }
```
with
diff --git a/guides/source/active_support_instrumentation.md b/guides/source/active_support_instrumentation.md
index 6b3be69942..d08000eb69 100644
--- a/guides/source/active_support_instrumentation.md
+++ b/guides/source/active_support_instrumentation.md
@@ -450,7 +450,7 @@ ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*a
data # { extra: :information }
```
-You may also subscribe to events matching a regular expresssion. This enables you to subscribe to
+You may also subscribe to events matching a regular expression. This enables you to subscribe to
multiple events at once. Here's you could subscribe to everything from `ActionController`.
```ruby
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index cb0a7c8026..65c8154064 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -1109,7 +1109,7 @@ end
Controls what happens to the associated object when its owner is destroyed:
* `:destroy` causes the associated object to also be destroyed
-* `:delete` causes the asssociated object to be deleted directly from the database (so callbacks will not execute)
+* `:delete` causes the associated object to be deleted directly from the database (so callbacks will not execute)
* `:nullify` causes the foreign key to be set to `NULL`. Callbacks are not executed.
* `:restrict_with_exception` causes an exception to be raised if there is an associated record
* `:restrict_with_error` causes an error to be added to the owner if there is an associated object
@@ -1463,7 +1463,7 @@ end
Controls what happens to the associated objects when their owner is destroyed:
* `:destroy` causes all the associated objects to also be destroyed
-* `:delete_all` causes all the asssociated objects to be deleted directly from the database (so callbacks will not execute)
+* `:delete_all` causes all the associated objects to be deleted directly from the database (so callbacks will not execute)
* `:nullify` causes the foreign keys to be set to `NULL`. Callbacks are not executed.
* `:restrict_with_exception` causes an exception to be raised if there are any associated records
* `:restrict_with_error` causes an error to be added to the owner if there are any associated objects
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index 57945a256b..cb43781f52 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -43,7 +43,7 @@ Rails 4.0 no longer supports loading plugins from `vendor/plugins`. You must rep
* Rails 4.0 has changed how orders get stacked in `ActiveRecord::Relation`. In previous versions of Rails, the new order was applied after the previously defined order. But this is no longer true. Check [Active Record Query guide](active_record_querying.html#ordering) for more information.
-* Rails 4.0 has changed `serialized_attributes` and `attr_readonly` to class methods only. Now you shouldn't use instance methods, it's deprecated. You must change them, e.g. `self.serialized_attributes` to `self.class.serialized_attributes`.
+* Rails 4.0 has changed `serialized_attributes` and `attr_readonly` to class methods only. You shouldn't use instance methods since it's now deprecated. You should change them to use class methods, e.g. `self.serialized_attributes` to `self.class.serialized_attributes`.
* Rails 4.0 has removed `attr_accessible` and `attr_protected` feature in favor of Strong Parameters. You can use the [Protected Attributes gem](https://github.com/rails/protected_attributes) to a smoothly upgrade path.
@@ -65,7 +65,7 @@ Rails 4.0 extracted Active Resource to its own gem. If you still need the featur
### Active Model
-* Rails 4.0 has changed how errors attach with the `ActiveModel::Validations::ConfirmationValidator`. Now when confirmation validations fail the error will be attached to `:#{attribute}_confirmation` instead of `attribute`.
+* Rails 4.0 has changed how errors attach with the `ActiveModel::Validations::ConfirmationValidator`. Now when confirmation validations fail, the error will be attached to `:#{attribute}_confirmation` instead of `attribute`.
* Rails 4.0 has changed `ActiveModel::Serializers::JSON.include_root_in_json` default value to `false`. Now, Active Model Serializers and Active Record objects have the same default behaviour. This means that you can comment or remove the following option in the `config/initializers/wrap_parameters.rb` file:
@@ -128,7 +128,7 @@ get 'こんにちは', controller: 'welcome', action: 'index'
get "/" => "root#index"
```
-* Rails 4.0 has removed ActionDispatch::BestStandardsSupport middleware, !DOCTYPE html already triggers standards mode per http://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx and ChromeFrame header has been moved to `config.action_dispatch.default_headers`
+* Rails 4.0 has removed `ActionDispatch::BestStandardsSupport` middleware, `<!DOCTYPE html>` already triggers standards mode per http://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx and ChromeFrame header has been moved to `config.action_dispatch.default_headers`.
Remember you must also remove any references to the middleware from your application code, for example:
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 4f7cb8254f..420ed476b2 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -39,13 +39,13 @@
*Amparo Luna*
* Fixes database.yml when creating a new rails application with '.'
- Fix #8304
+ Fixes #8304.
*Jeremy W. Rowe*
* Restore Rails::Engine::Railties#engines with deprecation to ensure
compatibility with gems such as Thinking Sphinx
- Fix #8551
+ Fixes #8551.
*Tim Raymond*
@@ -119,7 +119,7 @@
* Environment name can be a start substring of the default environment names
(production, development, test). For example: tes, pro, prod, dev, devel.
- Fix #8628.
+ Fixes #8628.
*Mykola Kyryk*
@@ -129,7 +129,7 @@
* Quote column names in generates fixture files. This prevents
conflicts with reserved YAML keywords such as 'yes' and 'no'
- Fix #8612.
+ Fixes #8612.
*Yves Senn*
@@ -162,19 +162,19 @@
* Add `db` to list of folders included by `rake notes` and `rake notes:custom`. *Antonio Cangiano*
* Engines with a dummy app include the rake tasks of dependencies in the app namespace.
- Fix #8229
+ Fixes #8229.
*Yves Senn*
* Add `sqlserver.yml` template file to satisfy `-d sqlserver` being passed to `rails new`.
- Fix #6882
+ Fixes #6882.
*Robert Nesius*
* Rake test:uncommitted finds git directory in ancestors *Nicolas Despres*
* Add dummy app Rake tasks when `--skip-test-unit` and `--dummy-path` is passed to the plugin generator.
- Fix #8121
+ Fixes #8121.
*Yves Senn*
diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb
index f4450c8a3c..af495bb450 100644
--- a/railties/test/application/console_test.rb
+++ b/railties/test/application/console_test.rb
@@ -106,13 +106,13 @@ class FullStackConsoleTest < ActiveSupport::TestCase
teardown_app
end
- def assert_output(expected, timeout = 5)
+ def assert_output(expected, timeout = 1)
timeout = Time.now + timeout
output = ""
until output.include?(expected) || Time.now > timeout
if IO.select([@master], [], [], 0.1)
- output << @master.readpartial(100)
+ output << @master.read(1)
end
end