aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile2
-rw-r--r--RAILS_VERSION2
-rw-r--r--actionmailer/CHANGELOG.md9
-rw-r--r--actionmailer/lib/action_mailer/version.rb2
-rw-r--r--actionpack/CHANGELOG.md21
-rw-r--r--actionpack/lib/action_controller/metal.rb4
-rw-r--r--actionpack/lib/action_controller/metal/compatibility.rb32
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb2
-rw-r--r--actionpack/lib/action_dispatch/railtie.rb3
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb21
-rw-r--r--actionpack/lib/action_pack/version.rb2
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb8
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb3
-rw-r--r--actionpack/lib/action_view/helpers/number_helper.rb3
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb2
-rw-r--r--actionpack/lib/sprockets/railtie.rb5
-rw-r--r--actionpack/test/controller/base_test.rb22
-rw-r--r--actionpack/test/controller/caching_test.rb2
-rw-r--r--actionpack/test/controller/content_type_test.rb32
-rw-r--r--actionpack/test/controller/render_test.rb12
-rw-r--r--actionpack/test/controller/routing_test.rb62
-rw-r--r--actionpack/test/controller/view_paths_test.rb7
-rw-r--r--actionpack/test/dispatch/debug_exceptions_test.rb4
-rw-r--r--actionpack/test/dispatch/routing_test.rb24
-rw-r--r--actionpack/test/dispatch/show_exceptions_test.rb2
-rw-r--r--actionpack/test/template/date_helper_test.rb48
-rw-r--r--actionpack/test/template/form_options_helper_test.rb16
-rw-r--r--activemodel/CHANGELOG.md6
-rw-r--r--activemodel/lib/active_model/errors.rb20
-rw-r--r--activemodel/lib/active_model/naming.rb2
-rw-r--r--activemodel/lib/active_model/version.rb2
-rw-r--r--activemodel/test/cases/errors_test.rb15
-rw-r--r--activerecord/CHANGELOG.md36
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb3
-rw-r--r--activerecord/lib/active_record/base.rb13
-rw-r--r--activerecord/lib/active_record/counter_cache.rb3
-rw-r--r--activerecord/lib/active_record/locking/pessimistic.rb22
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb4
-rw-r--r--activerecord/lib/active_record/version.rb2
-rw-r--r--activerecord/test/cases/attribute_methods/read_test.rb8
-rw-r--r--activerecord/test/cases/counter_cache_test.rb20
-rw-r--r--activerecord/test/cases/locking_test.rb20
-rw-r--r--activerecord/test/fixtures/dog_lovers.yml4
-rw-r--r--activerecord/test/fixtures/dogs.yml3
-rw-r--r--activerecord/test/models/dog.rb4
-rw-r--r--activerecord/test/models/dog_lover.rb4
-rw-r--r--activerecord/test/schema/schema.rb10
-rw-r--r--activeresource/CHANGELOG.md2
-rw-r--r--activeresource/lib/active_resource/version.rb2
-rw-r--r--activesupport/CHANGELOG.md2
-rw-r--r--activesupport/lib/active_support/base64.rb2
-rw-r--r--activesupport/lib/active_support/callbacks.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/calculations.rb2
-rw-r--r--activesupport/lib/active_support/tagged_logging.rb2
-rw-r--r--activesupport/lib/active_support/version.rb2
-rw-r--r--activesupport/test/callbacks_test.rb65
-rw-r--r--activesupport/test/core_ext/base64_ext_test.rb9
-rw-r--r--activesupport/test/tagged_logging_test.rb6
-rw-r--r--railties/CHANGELOG.md2
-rw-r--r--railties/guides/code/getting_started/Gemfile23
-rw-r--r--railties/guides/code/getting_started/app/assets/javascripts/application.js12
-rw-r--r--railties/guides/code/getting_started/app/assets/stylesheets/application.css16
-rw-r--r--railties/guides/code/getting_started/app/views/layouts/application.html.erb2
-rw-r--r--railties/guides/code/getting_started/config/application.rb8
-rw-r--r--railties/guides/code/getting_started/config/environments/test.rb6
-rw-r--r--railties/guides/code/getting_started/config/initializers/inflections.rb5
-rw-r--r--railties/guides/code/getting_started/config/routes.rb8
-rw-r--r--railties/guides/code/getting_started/public/500.html1
-rw-r--r--railties/guides/source/3_2_release_notes.textile66
-rw-r--r--railties/guides/source/active_record_querying.textile11
-rw-r--r--railties/guides/source/asset_pipeline.textile60
-rw-r--r--railties/guides/source/configuring.textile1
-rw-r--r--railties/guides/source/form_helpers.textile4
-rw-r--r--railties/guides/source/getting_started.textile30
-rw-r--r--railties/lib/rails/application/configuration.rb1
-rw-r--r--railties/lib/rails/application/finisher.rb3
-rw-r--r--railties/lib/rails/generators/actions.rb1
-rw-r--r--railties/lib/rails/generators/generated_attribute.rb4
-rw-r--r--railties/lib/rails/version.rb2
-rw-r--r--railties/test/application/configuration_test.rb8
-rw-r--r--railties/test/generators/migration_generator_test.rb6
-rw-r--r--version.rb2
82 files changed, 773 insertions, 158 deletions
diff --git a/Gemfile b/Gemfile
index 307ba8f0b8..103dd1bd6c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -14,7 +14,7 @@ gem 'jquery-rails'
if ENV['JOURNEY']
gem 'journey', :path => ENV['JOURNEY']
else
- gem 'journey'
+ gem 'journey', :git => 'git://github.com/rails/journey.git', :branch => '1-0-stable'
end
# This needs to be with require false to avoid
diff --git a/RAILS_VERSION b/RAILS_VERSION
index df38341606..944880fa15 100644
--- a/RAILS_VERSION
+++ b/RAILS_VERSION
@@ -1 +1 @@
-3.2.0.rc2
+3.2.0
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md
index 57af4ee6a4..ca712d42d8 100644
--- a/actionmailer/CHANGELOG.md
+++ b/actionmailer/CHANGELOG.md
@@ -1,3 +1,10 @@
+## Rails 3.2.0 (January 20, 2012) ##
+
+* Upgrade mail version to 2.4.0 *ML*
+
+* Remove Old ActionMailer API *Josh Kalderimis*
+
+
## Rails 3.1.0 (August 30, 2011) ##
* No changes
@@ -8,7 +15,7 @@
* remove AM delegating register_observer and register_interceptor to Mail *Josh Kalderimis*
-* Rails 3.0.6 (April 5, 2011)
+## Rails 3.0.6 (April 5, 2011) ##
* Don't allow i18n to change the minor version, version now set to ~> 0.5.0 *Santiago Pastorino*
diff --git a/actionmailer/lib/action_mailer/version.rb b/actionmailer/lib/action_mailer/version.rb
index 0afdab8672..f72520cb8c 100644
--- a/actionmailer/lib/action_mailer/version.rb
+++ b/actionmailer/lib/action_mailer/version.rb
@@ -3,7 +3,7 @@ module ActionMailer
MAJOR = 3
MINOR = 2
TINY = 0
- PRE = "rc2"
+ PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 8a4be5667e..8445c3ffaa 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,4 +1,21 @@
-## Rails 3.2.0 (unreleased) ##
+## Rails 3.2.0 (January 20, 2012) ##
+
+* Setting config.assets.logger to false turn off Sprockets logger *Guillermo Iguaran*
+
+* Add `config.action_dispatch.default_charset` to configure default charset for ActionDispatch::Response. *Carlos Antonio da Silva*
+
+* Deprecate setting default charset at controller level, use the new `config.action_dispatch.default_charset` instead. *Carlos Antonio da Silva*
+
+* Deprecate ActionController::UnknownAction in favour of AbstractController::ActionNotFound. *Carlos Antonio da Silva*
+
+* Deprecate ActionController::DoubleRenderError in favour of AbstractController::DoubleRenderError. *Carlos Antonio da Silva*
+
+* Deprecate method_missing handling for not found actions, use action_missing instead. *Carlos Antonio da Silva*
+
+* Deprecate ActionController#rescue_action, ActionController#initialize_template_class, and ActionController#assign_shortcuts.
+ These methods were not being used internally anymore and are going to be removed in Rails 4. *Carlos Antonio da Silva*
+
+* Add config.assets.logger to configure Sprockets logger *Rafael França*
* Use a BodyProxy instead of including a Module that responds to
close. Closes #4441 if Active Record is disabled assets are delivered
@@ -24,7 +41,7 @@
<%= f.button %>
<% end %>
-* Date helpers accept a new option, `:use_two_digit_numbers = true`, that renders select boxes for months and days with a leading zero without changing the respective values.
+* Date helpers accept a new option, `:use_two_digit_numbers = true`, that renders select boxes for months and days with a leading zero without changing the respective values.
For example, this is useful for displaying ISO8601-style dates such as '2011-08-01'. *Lennart Fridén and Kim Persson*
* Make ActiveSupport::Benchmarkable a default module for ActionController::Base, so the #benchmark method is once again available in the controller context like it used to be *DHH*
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 125dbf6bb5..9b0c8e0ce3 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -192,6 +192,10 @@ module ActionController
super body
end
+ def performed?
+ response_body
+ end
+
def dispatch(name, request) #:nodoc:
@_request = request
@_env = request.env
diff --git a/actionpack/lib/action_controller/metal/compatibility.rb b/actionpack/lib/action_controller/metal/compatibility.rb
index 05dca445a4..de3354d4f9 100644
--- a/actionpack/lib/action_controller/metal/compatibility.rb
+++ b/actionpack/lib/action_controller/metal/compatibility.rb
@@ -1,21 +1,22 @@
+require 'active_support/deprecation'
+
module ActionController
module Compatibility
extend ActiveSupport::Concern
- class ::ActionController::ActionControllerError < StandardError #:nodoc:
- end
-
# Temporary hax
included do
- ::ActionController::UnknownAction = ::AbstractController::ActionNotFound
- ::ActionController::DoubleRenderError = ::AbstractController::DoubleRenderError
+ ::ActionController::UnknownAction = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActionController::UnknownAction', '::AbstractController::ActionNotFound')
+ ::ActionController::DoubleRenderError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActionController::DoubleRenderError', '::AbstractController::DoubleRenderError')
# ROUTES TODO: This should be handled by a middleware and route generation
# should be able to handle SCRIPT_NAME
self.config.relative_url_root = ENV['RAILS_RELATIVE_URL_ROOT']
- class << self
- delegate :default_charset=, :to => "ActionDispatch::Response"
+ def self.default_charset=(new_charset)
+ ActiveSupport::Deprecation.warn "Setting default charset at controller level" \
+ " is deprecated, please use `config.action_dispatch.default_charset` instead", caller
+ ActionDispatch::Response.default_charset = new_charset
end
self.protected_instance_variables = %w(
@@ -24,13 +25,19 @@ module ActionController
)
def rescue_action(env)
+ ActiveSupport::Deprecation.warn "Calling `rescue_action` is deprecated and will be removed in Rails 4.0.", caller
raise env["action_dispatch.rescue.exception"]
end
end
# For old tests
- def initialize_template_class(*) end
- def assign_shortcuts(*) end
+ def initialize_template_class(*)
+ ActiveSupport::Deprecation.warn "Calling `initialize_template_class` is deprecated and has no effect anymore.", caller
+ end
+
+ def assign_shortcuts(*)
+ ActiveSupport::Deprecation.warn "Calling `assign_shortcuts` is deprecated and has no effect anymore.", caller
+ end
def _normalize_options(options)
options[:text] = nil if options.delete(:nothing) == true
@@ -44,15 +51,14 @@ module ActionController
end
def _handle_method_missing
+ ActiveSupport::Deprecation.warn "Using `method_missing` to handle non" \
+ " existing actions is deprecated and will be removed in Rails 4.0, " \
+ " please use `action_missing` instead.", caller
method_missing(@_action_name.to_sym)
end
def method_for_action(action_name)
super || (respond_to?(:method_missing) && "_handle_method_missing")
end
-
- def performed?
- response_body
- end
end
end
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index fcb21907a3..9f2f5476fa 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -67,7 +67,7 @@ module ActionController
# class PostsController < ApplicationController
# REALM = "SuperSecret"
# USERS = {"dhh" => "secret", #plain text password
- # "dap" => Digest::MD5.hexdigest(["dap",REALM,"secret"].join(":")) #ha1 digest password
+ # "dap" => Digest::MD5.hexdigest(["dap",REALM,"secret"].join(":"))} #ha1 digest password
#
# before_filter :authenticate, :except => [:index]
#
diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb
index a4f4825f92..2bfeeb348f 100644
--- a/actionpack/lib/action_dispatch/railtie.rb
+++ b/actionpack/lib/action_dispatch/railtie.rb
@@ -11,6 +11,7 @@ module ActionDispatch
config.action_dispatch.ignore_accept_header = false
config.action_dispatch.rescue_templates = { }
config.action_dispatch.rescue_responses = { }
+ config.action_dispatch.default_charset = nil
config.action_dispatch.rack_cache = {
:metastore => "rails:/",
@@ -21,7 +22,7 @@ module ActionDispatch
initializer "action_dispatch.configure" do |app|
ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length
ActionDispatch::Request.ignore_accept_header = app.config.action_dispatch.ignore_accept_header
- ActionDispatch::Response.default_charset = app.config.encoding
+ ActionDispatch::Response.default_charset = app.config.action_dispatch.default_charset || app.config.encoding
ActionDispatch::ExceptionWrapper.rescue_responses.merge!(config.action_dispatch.rescue_responses)
ActionDispatch::ExceptionWrapper.rescue_templates.merge!(config.action_dispatch.rescue_templates)
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 4760887456..b67a2d01b9 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -367,7 +367,26 @@ module ActionDispatch
SEPARATORS,
anchor)
- Journey::Path::Pattern.new(strexp)
+ pattern = Journey::Path::Pattern.new(strexp)
+
+ builder = Journey::GTG::Builder.new pattern.spec
+
+ # Get all the symbol nodes followed by literals that are not the
+ # dummy node.
+ symbols = pattern.spec.grep(Journey::Nodes::Symbol).find_all { |n|
+ builder.followpos(n).first.literal?
+ }
+
+ # Get all the symbol nodes preceded by literals.
+ symbols.concat pattern.spec.find_all(&:literal?).map { |n|
+ builder.followpos(n).first
+ }.find_all(&:symbol?)
+
+ symbols.each { |x|
+ x.regexp = /(?:#{Regexp.union(x.regexp, '-')})+/
+ }
+
+ pattern
end
private :build_path
diff --git a/actionpack/lib/action_pack/version.rb b/actionpack/lib/action_pack/version.rb
index 5cc7ea0331..3c86150afd 100644
--- a/actionpack/lib/action_pack/version.rb
+++ b/actionpack/lib/action_pack/version.rb
@@ -3,7 +3,7 @@ module ActionPack
MAJOR = 3
MINOR = 2
TINY = 0
- PRE = "rc2"
+ PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 2806348337..2b128e8445 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -734,7 +734,7 @@ module ActionView
def select_day
if @options[:use_hidden] || @options[:discard_day]
- build_hidden(:day, day)
+ build_hidden(:day, day || 1)
else
build_options_and_select(:day, day, :start => 1, :end => 31, :leading_zeros => false, :use_two_digit_numbers => @options[:use_two_digit_numbers])
end
@@ -742,7 +742,7 @@ module ActionView
def select_month
if @options[:use_hidden] || @options[:discard_month]
- build_hidden(:month, month)
+ build_hidden(:month, month || 1)
else
month_options = []
1.upto(12) do |month_number|
@@ -756,7 +756,7 @@ module ActionView
def select_year
if !@datetime || @datetime == 0
- val = ''
+ val = '1'
middle_year = Date.today.year
else
val = middle_year = year
@@ -783,7 +783,7 @@ module ActionView
private
%w( sec min hour day month year ).each do |method|
define_method(method) do
- @datetime.kind_of?(Fixnum) ? @datetime : @datetime.send(method) if @datetime
+ @datetime.kind_of?(Numeric) ? @datetime : @datetime.send(method) if @datetime
end
end
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index 3ee0d8ebc5..e00ac8f3f2 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -336,7 +336,7 @@ module ActionView
end
- # Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning the
+ # Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning
# the result of a call to the +value_method+ as the option value and the +text_method+ as the option text.
# Example:
# options_from_collection_for_select(@people, 'id', 'name')
@@ -578,6 +578,7 @@ module ActionView
def to_select_tag(choices, options, html_options)
selected_value = options.has_key?(:selected) ? options[:selected] : value(object)
+ choices = choices.to_a if choices.is_a?(Range)
# Grouped choices look like this:
#
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index a325eb59dc..eda16903b0 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -265,6 +265,7 @@ module ActionView
# * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator
# (defaults to +false+).
+ # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid.
#
# ==== Examples
# number_with_precision(111.2345) # => 111.235
@@ -344,6 +345,7 @@ module ActionView
# * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +true+)
# * <tt>:prefix</tt> - If +:si+ formats the number using the SI prefix (defaults to :binary)
+ # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid.
# ==== Examples
# number_to_human_size(123) # => 123 Bytes
# number_to_human_size(1234) # => 1.21 KB
@@ -425,6 +427,7 @@ module ActionView
# * *integers*: <tt>:unit</tt>, <tt>:ten</tt>, <tt>:hundred</tt>, <tt>:thousand</tt>, <tt>:million</tt>, <tt>:billion</tt>, <tt>:trillion</tt>, <tt>:quadrillion</tt>
# * *fractionals*: <tt>:deci</tt>, <tt>:centi</tt>, <tt>:mili</tt>, <tt>:micro</tt>, <tt>:nano</tt>, <tt>:pico</tt>, <tt>:femto</tt>
# * <tt>:format</tt> - Sets the format of the output string (defaults to "%n %u"). The field types are:
+ # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid.
#
# %u The quantifier (ex.: 'thousand')
# %n The number
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 0c2e1aa3a9..1f1cd3cee3 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -476,7 +476,7 @@ module ActionView
# string given as the value.
# * <tt>:subject</tt> - Preset the subject line of the email.
# * <tt>:body</tt> - Preset the body of the email.
- # * <tt>:cc</tt> - Carbon Copy addition recipients on the email.
+ # * <tt>:cc</tt> - Carbon Copy additional recipients on the email.
# * <tt>:bcc</tt> - Blind Carbon Copy additional recipients on the email.
#
# ==== Examples
diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb
index a7eb03acaf..44ddab0950 100644
--- a/actionpack/lib/sprockets/railtie.rb
+++ b/actionpack/lib/sprockets/railtie.rb
@@ -21,9 +21,12 @@ module Sprockets
require 'sprockets'
app.assets = Sprockets::Environment.new(app.root.to_s) do |env|
- env.logger = ::Rails.logger
env.version = ::Rails.env + "-#{config.assets.version}"
+ if config.assets.logger != false
+ env.logger = config.assets.logger || ::Rails.logger
+ end
+
if config.assets.cache_store != false
env.cache = ActiveSupport::Cache.lookup_store(config.assets.cache_store) || ::Rails.cache
end
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index f2b054c849..6e13aab518 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -116,6 +116,12 @@ class ControllerInstanceTests < Test::Unit::TestCase
Submodule::ContainedNonEmptyController.new]
end
+ def test_performed?
+ assert !@empty.performed?
+ @empty.response_body = ["sweet"]
+ assert @empty.performed?
+ end
+
def test_action_methods
@empty_controllers.each do |c|
assert_equal Set.new, c.class.action_methods, "#{c.controller_path} should be empty!"
@@ -161,7 +167,9 @@ class PerformActionTest < ActionController::TestCase
def test_get_on_priv_should_show_selector
use_controller MethodMissingController
- get :shouldnt_be_called
+ assert_deprecated /Using `method_missing` to handle .* use `action_missing` instead/ do
+ get :shouldnt_be_called
+ end
assert_response :success
assert_equal 'shouldnt_be_called', @response.body
end
@@ -170,21 +178,25 @@ class PerformActionTest < ActionController::TestCase
use_controller MethodMissingController
assert !@controller.__send__(:action_method?, 'method_missing')
- get :method_missing
+ assert_deprecated /Using `method_missing` to handle .* use `action_missing` instead/ do
+ get :method_missing
+ end
assert_response :success
assert_equal 'method_missing', @response.body
end
def test_method_missing_should_recieve_symbol
use_controller AnotherMethodMissingController
- get :some_action
+ assert_deprecated /Using `method_missing` to handle .* use `action_missing` instead/ do
+ get :some_action
+ end
assert_kind_of NameError, @controller._exception
end
def test_get_on_hidden_should_fail
use_controller NonEmptyController
- assert_raise(ActionController::UnknownAction) { get :hidden_action }
- assert_raise(ActionController::UnknownAction) { get :another_hidden_action }
+ assert_raise(AbstractController::ActionNotFound) { get :hidden_action }
+ assert_raise(AbstractController::ActionNotFound) { get :another_hidden_action }
end
end
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index 34a38a5567..443b56830a 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -686,8 +686,6 @@ class FragmentCachingTest < ActionController::TestCase
@controller.params = @params
@controller.request = @request
@controller.response = @response
- @controller.send(:initialize_template_class, @response)
- @controller.send(:assign_shortcuts, @request, @response)
end
def test_fragment_cache_key
diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb
index d51882066d..d0dabb29ca 100644
--- a/actionpack/test/controller/content_type_test.rb
+++ b/actionpack/test/controller/content_type_test.rb
@@ -70,12 +70,16 @@ class ContentTypeTest < ActionController::TestCase
end
def test_render_changed_charset_default
- OldContentTypeController.default_charset = "utf-16"
- get :render_defaults
- assert_equal "utf-16", @response.charset
- assert_equal Mime::HTML, @response.content_type
- ensure
- OldContentTypeController.default_charset = "utf-8"
+ assert_deprecated /Setting default charset at controller.*config\.action_dispatch\.default_charset/ do
+ begin
+ OldContentTypeController.default_charset = "utf-16"
+ get :render_defaults
+ assert_equal "utf-16", @response.charset
+ assert_equal Mime::HTML, @response.content_type
+ ensure
+ OldContentTypeController.default_charset = "utf-8"
+ end
+ end
end
# :ported:
@@ -107,12 +111,16 @@ class ContentTypeTest < ActionController::TestCase
end
def test_nil_default_for_erb
- OldContentTypeController.default_charset = nil
- get :render_default_for_erb
- assert_equal Mime::HTML, @response.content_type
- assert_nil @response.charset, @response.headers.inspect
- ensure
- OldContentTypeController.default_charset = "utf-8"
+ assert_deprecated /Setting default charset at controller.*config\.action_dispatch\.default_charset/ do
+ begin
+ OldContentTypeController.default_charset = nil
+ get :render_default_for_erb
+ assert_equal Mime::HTML, @response.content_type
+ assert_nil @response.charset, @response.headers.inspect
+ ensure
+ OldContentTypeController.default_charset = "utf-8"
+ end
+ end
end
def test_default_for_erb
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index f42a04d670..28f6bc88e0 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -54,7 +54,7 @@ class TestController < ActionController::Base
def conditional_hello_with_record
record = Struct.new(:updated_at, :cache_key).new(Time.now.utc.beginning_of_day, "foo/123")
-
+
if stale?(record)
render :action => 'hello_world'
end
@@ -893,12 +893,12 @@ class RenderTest < ActionController::TestCase
# :ported:
def test_attempt_to_access_object_method
- assert_raise(ActionController::UnknownAction, "No action responded to [clone]") { get :clone }
+ assert_raise(AbstractController::ActionNotFound, "No action responded to [clone]") { get :clone }
end
# :ported:
def test_private_methods
- assert_raise(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout }
+ assert_raise(AbstractController::ActionNotFound, "No action responded to [determine_layout]") { get :determine_layout }
end
# :ported:
@@ -1098,15 +1098,15 @@ class RenderTest < ActionController::TestCase
# :ported:
def test_double_render
- assert_raise(ActionController::DoubleRenderError) { get :double_render }
+ assert_raise(AbstractController::DoubleRenderError) { get :double_render }
end
def test_double_redirect
- assert_raise(ActionController::DoubleRenderError) { get :double_redirect }
+ assert_raise(AbstractController::DoubleRenderError) { get :double_redirect }
end
def test_render_and_redirect
- assert_raise(ActionController::DoubleRenderError) { get :render_and_redirect }
+ assert_raise(AbstractController::DoubleRenderError) { get :render_and_redirect }
end
# specify the one exception to double render rule - render_to_string followed by render
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index 8cefa16ad7..222497d311 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -93,6 +93,68 @@ class LegacyRouteSetTests < Test::Unit::TestCase
@rs.call(params)[2].join
end
+ def test_symbols_with_dashes
+ rs.draw do
+ match '/:artist/:song-omg', :to => lambda { |env|
+ resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
+ [200, {}, [resp]]
+ }
+ end
+
+ hash = JSON.load get(URI('http://example.org/journey/faithfully-omg'))
+ assert_equal({"artist"=>"journey", "song"=>"faithfully"}, hash)
+ end
+
+ def test_id_with_dash
+ rs.draw do
+ match '/journey/:id', :to => lambda { |env|
+ resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
+ [200, {}, [resp]]
+ }
+ end
+
+ hash = JSON.load get(URI('http://example.org/journey/faithfully-omg'))
+ assert_equal({"id"=>"faithfully-omg"}, hash)
+ end
+
+ def test_dash_with_custom_regexp
+ rs.draw do
+ match '/:artist/:song-omg', :constraints => { :song => /\d+/ }, :to => lambda { |env|
+ resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
+ [200, {}, [resp]]
+ }
+ end
+
+ hash = JSON.load get(URI('http://example.org/journey/123-omg'))
+ assert_equal({"artist"=>"journey", "song"=>"123"}, hash)
+ assert_equal 'Not Found', get(URI('http://example.org/journey/faithfully-omg'))
+ end
+
+ def test_pre_dash
+ rs.draw do
+ match '/:artist/omg-:song', :to => lambda { |env|
+ resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
+ [200, {}, [resp]]
+ }
+ end
+
+ hash = JSON.load get(URI('http://example.org/journey/omg-faithfully'))
+ assert_equal({"artist"=>"journey", "song"=>"faithfully"}, hash)
+ end
+
+ def test_pre_dash_with_custom_regexp
+ rs.draw do
+ match '/:artist/omg-:song', :constraints => { :song => /\d+/ }, :to => lambda { |env|
+ resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
+ [200, {}, [resp]]
+ }
+ end
+
+ hash = JSON.load get(URI('http://example.org/journey/omg-123'))
+ assert_equal({"artist"=>"journey", "song"=>"123"}, hash)
+ assert_equal 'Not Found', get(URI('http://example.org/journey/omg-faithfully'))
+ end
+
def test_regexp_precidence
@rs.draw do
match '/whois/:domain', :constraints => {
diff --git a/actionpack/test/controller/view_paths_test.rb b/actionpack/test/controller/view_paths_test.rb
index f5ac886c20..04f550ae1e 100644
--- a/actionpack/test/controller/view_paths_test.rb
+++ b/actionpack/test/controller/view_paths_test.rb
@@ -22,16 +22,9 @@ class ViewLoadPathsTest < ActionController::TestCase
end
def setup
- # TestController.view_paths = nil
-
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
-
@controller = TestController.new
- # Following is needed in order to setup @controller.template object properly
- @controller.send :assign_shortcuts, @request, @response
- @controller.send :initialize_template_class, @response
-
@paths = TestController.view_paths
end
diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb
index f3dc160d7d..c3a565990e 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -24,7 +24,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
when "/pass"
[404, { "X-Cascade" => "pass" }, self]
when "/not_found"
- raise ActionController::UnknownAction
+ raise AbstractController::ActionNotFound
when "/runtime_error"
raise RuntimeError
when "/method_not_allowed"
@@ -83,7 +83,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
get "/not_found", {}, {'action_dispatch.show_exceptions' => true}
assert_response 404
- assert_match(/#{ActionController::UnknownAction.name}/, body)
+ assert_match(/#{AbstractController::ActionNotFound.name}/, body)
get "/method_not_allowed", {}, {'action_dispatch.show_exceptions' => true}
assert_response 405
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 67556e5253..207a439a0a 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -1,3 +1,4 @@
+# encoding: UTF-8
require 'erb'
require 'abstract_unit'
require 'controller/fake_controllers'
@@ -524,6 +525,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
"GET"
end
+ def ip
+ "127.0.0.1"
+ end
+
def x_header
@env["HTTP_X_HEADER"] || ""
end
@@ -2538,3 +2543,22 @@ class TestUriPathEscaping < ActionDispatch::IntegrationTest
assert_equal 'a b/c+d', @response.body
end
end
+
+class TestUnicodePaths < ActionDispatch::IntegrationTest
+ Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
+ app.draw do
+ match "/#{Rack::Utils.escape("ほげ")}" => lambda { |env|
+ path_params = env['action_dispatch.request.path_parameters']
+ [200, { 'Content-Type' => 'text/plain' }, []]
+ }, :as => :unicode_path
+ end
+ end
+
+ include Routes.url_helpers
+ def app; Routes end
+
+ test 'recognizes unicode path' do
+ get "/#{Rack::Utils.escape("ほげ")}"
+ assert_equal "200", @response.code
+ end
+end
diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb
index e9504f3524..4a6d5ddbf7 100644
--- a/actionpack/test/dispatch/show_exceptions_test.rb
+++ b/actionpack/test/dispatch/show_exceptions_test.rb
@@ -7,7 +7,7 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest
req = ActionDispatch::Request.new(env)
case req.path
when "/not_found"
- raise ActionController::UnknownAction
+ raise AbstractController::ActionNotFound
when "/method_not_allowed"
raise ActionController::MethodNotAllowed
when "/not_found_original_exception"
diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb
index fadfb59572..584d1830eb 100644
--- a/actionpack/test/template/date_helper_test.rb
+++ b/actionpack/test/template/date_helper_test.rb
@@ -1587,7 +1587,7 @@ class DateHelperTest < ActionView::TestCase
start_year = Time.now.year-5
end_year = Time.now.year+5
- expected = '<input name="post[written_on(3i)]" type="hidden" id="post_written_on_3i"/>' + "\n"
+ expected = '<input name="post[written_on(3i)]" type="hidden" id="post_written_on_3i" value="1"/>' + "\n"
expected << %{<select id="post_written_on_1i" name="post[written_on(1i)]">\n}
expected << "<option value=\"\"></option>\n"
start_year.upto(end_year) { |i| expected << %(<option value="#{i}">#{i}</option>\n) }
@@ -1601,6 +1601,40 @@ class DateHelperTest < ActionView::TestCase
assert_dom_equal expected, date_select("post", "written_on", :order=>[:year, :month], :include_blank=>true)
end
+ def test_date_select_with_nil_and_blank_and_discard_month
+ @post = Post.new
+
+ start_year = Time.now.year-5
+ end_year = Time.now.year+5
+
+ expected = %{<select id="post_written_on_1i" name="post[written_on(1i)]">\n}
+ expected << "<option value=\"\"></option>\n"
+ start_year.upto(end_year) { |i| expected << %(<option value="#{i}">#{i}</option>\n) }
+ expected << "</select>\n"
+ expected << '<input name="post[written_on(2i)]" type="hidden" id="post_written_on_2i" value="1"/>' + "\n"
+ expected << '<input name="post[written_on(3i)]" type="hidden" id="post_written_on_3i" value="1"/>' + "\n"
+
+ assert_dom_equal expected, date_select("post", "written_on", :discard_month => true, :include_blank=>true)
+ end
+
+ def test_date_select_with_nil_and_blank_and_discard_year
+ @post = Post.new
+
+ expected = '<input id="post_written_on_1i" name="post[written_on(1i)]" type="hidden" value="1" />' + "\n"
+
+ expected << %{<select id="post_written_on_2i" name="post[written_on(2i)]">\n}
+ expected << "<option value=\"\"></option>\n"
+ 1.upto(12) { |i| expected << %(<option value="#{i}">#{Date::MONTHNAMES[i]}</option>\n) }
+ expected << "</select>\n"
+
+ expected << %{<select id="post_written_on_3i" name="post[written_on(3i)]">\n}
+ expected << "<option value=\"\"></option>\n"
+ 1.upto(31) { |i| expected << %(<option value="#{i}">#{i}</option>\n) }
+ expected << "</select>\n"
+
+ assert_dom_equal expected, date_select("post", "written_on", :discard_year => true, :include_blank=>true)
+ end
+
def test_date_select_cant_override_discard_hour
@post = Post.new
@post.written_on = Date.new(2004, 6, 15)
@@ -2084,6 +2118,18 @@ class DateHelperTest < ActionView::TestCase
assert_dom_equal expected, datetime_select("post", "updated_at", { :date_separator => " / ", :datetime_separator => " , ", :time_separator => " - ", :include_seconds => true })
end
+ def test_datetime_select_with_integer
+ @post = Post.new
+ @post.updated_at = 3
+ datetime_select("post", "updated_at")
+ end
+
+ def test_datetime_select_with_infinity # Float
+ @post = Post.new
+ @post.updated_at = (-1.0/0)
+ datetime_select("post", "updated_at")
+ end
+
def test_datetime_select_with_default_prompt
@post = Post.new
@post.updated_at = nil
diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb
index 4a889beadd..62ab208c2e 100644
--- a/actionpack/test/template/form_options_helper_test.rb
+++ b/actionpack/test/template/form_options_helper_test.rb
@@ -159,6 +159,13 @@ class FormOptionsHelperTest < ActionView::TestCase
)
end
+ def test_range_options_for_select
+ assert_dom_equal(
+ "<option value=\"1\">1</option>\n<option value=\"2\">2</option>\n<option value=\"3\">3</option>",
+ options_for_select(1..3)
+ )
+ end
+
def test_hash_options_for_select
assert_dom_equal(
"<option value=\"&lt;Kroner&gt;\">&lt;DKR&gt;</option>\n<option value=\"Dollar\">$</option>",
@@ -671,6 +678,15 @@ class FormOptionsHelperTest < ActionView::TestCase
)
end
+ def test_select_with_range
+ @post = Post.new
+ @post.category = 0
+ assert_dom_equal(
+ "<select id=\"post_category\" name=\"post[category]\"><option value=\"1\">1</option>\n<option value=\"2\">2</option>\n<option value=\"3\">3</option></select>",
+ select("post", "category", 1..3)
+ )
+ end
+
def test_collection_select
@post = Post.new
@post.author_name = "Babe"
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index bd9ed996fe..b722e70450 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,9 +1,7 @@
-## Rails 3.2.0 (unreleased) ##
+## Rails 3.2.0 (January 20, 2012) ##
* Deprecated `define_attr_method` in `ActiveModel::AttributeMethods`, because this only existed to
- support methods like `set_table_name` in Active Record, which are themselves being deprecated.
-
- *Jon Leighton*
+ support methods like `set_table_name` in Active Record, which are themselves being deprecated. *Jon Leighton*
* Add ActiveModel::Errors#added? to check if a specific error has been added *Martin Svalin*
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index aafd1c8a74..80621cd7da 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -79,6 +79,19 @@ module ActiveModel
@messages = ActiveSupport::OrderedHash.new
end
+ def initialize_dup(other)
+ @messages = other.messages.dup
+ end
+
+ # Backport dup from 1.9 so that #initialize_dup gets called
+ unless Object.respond_to?(:initialize_dup)
+ def dup # :nodoc:
+ copy = super
+ copy.initialize_dup(self)
+ copy
+ end
+ end
+
# Clear the messages
def clear
messages.clear
@@ -100,6 +113,11 @@ module ActiveModel
messages[key] = value
end
+ # Delete messages for +key+
+ def delete(key)
+ messages.delete(key)
+ end
+
# When passed a symbol or a name of a method, returns an array of errors
# for the method.
#
@@ -114,7 +132,7 @@ module ActiveModel
# p.errors[:name] = "must be set"
# p.errors[:name] # => ['must be set']
def []=(attribute, error)
- self[attribute.to_sym] << error
+ self[attribute] << error
end
# Iterates through each error key, value pair in the error messages hash.
diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb
index 755e54efcd..a253be6765 100644
--- a/activemodel/lib/active_model/naming.rb
+++ b/activemodel/lib/active_model/naming.rb
@@ -1,7 +1,7 @@
require 'active_support/inflector'
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/module/introspection'
-require 'active_support/core_ext/module/deprecation'
+require 'active_support/deprecation'
module ActiveModel
class Name < String
diff --git a/activemodel/lib/active_model/version.rb b/activemodel/lib/active_model/version.rb
index 7c0530bad8..67d2460321 100644
--- a/activemodel/lib/active_model/version.rb
+++ b/activemodel/lib/active_model/version.rb
@@ -3,7 +3,7 @@ module ActiveModel
MAJOR = 3
MINOR = 2
TINY = 0
- PRE = "rc2"
+ PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb
index 8ddedb160a..e2dea12589 100644
--- a/activemodel/test/cases/errors_test.rb
+++ b/activemodel/test/cases/errors_test.rb
@@ -27,6 +27,13 @@ class ErrorsTest < ActiveModel::TestCase
end
end
+ def test_delete
+ errors = ActiveModel::Errors.new(self)
+ errors[:foo] = 'omg'
+ errors.delete(:foo)
+ assert errors[:foo].empty?
+ end
+
def test_include?
errors = ActiveModel::Errors.new(self)
errors[:foo] = 'omg'
@@ -39,6 +46,14 @@ class ErrorsTest < ActiveModel::TestCase
assert errors.has_key?(:foo), 'errors should have key :foo'
end
+ def test_dup
+ errors = ActiveModel::Errors.new(self)
+ errors[:foo] = 'bar'
+ errors_dup = errors.dup
+ errors_dup[:bar] = 'omg'
+ assert_not_same errors_dup.messages, errors.messages
+ end
+
test "should return true if no errors" do
person = Person.new
person.errors[:foo]
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 9551987de1..05c32ecf86 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,4 +1,36 @@
-## Rails 3.2.0 (unreleased) ##
+## Rails 3.2.1 (unreleased) ##
+
+* Fix possible race condition when two threads try to define attribute
+ methods for the same class.
+
+## Rails 3.2.0 (January 20, 2012) ##
+
+* Added a `with_lock` method to ActiveRecord objects, which starts
+ a transaction, locks the object (pessimistically) and yields to the block.
+ The method takes one (optional) parameter and passes it to `lock!`.
+
+ Before:
+
+ class Order < ActiveRecord::Base
+ def cancel!
+ transaction do
+ lock!
+ # ... cancelling logic
+ end
+ end
+ end
+
+ After:
+
+ class Order < ActiveRecord::Base
+ def cancel!
+ with_lock do
+ # ... cancelling logic
+ end
+ end
+ end
+
+ *Olek Janiszewski*
* 'on' and 'ON' boolean columns values are type casted to true
*Santiago Pastorino*
@@ -10,7 +42,7 @@
Example:
rake db:migrate SCOPE=blog
- *Piotr Sarnacki*
+ *Piotr Sarnacki*
* Migrations copied from engines are now scoped with engine's name,
for example 01_create_posts.blog.rb. *Piotr Sarnacki*
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index 31cd2edc12..f3200aa78a 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -1,6 +1,5 @@
require 'active_support/core_ext/enumerable'
require 'active_support/deprecation'
-require 'thread'
module ActiveRecord
# = Active Record Attribute Methods
@@ -39,8 +38,6 @@ module ActiveRecord
def define_attribute_methods
# Use a mutex; we don't want two thread simaltaneously trying to define
# attribute methods.
- @attribute_methods_mutex ||= Mutex.new
-
@attribute_methods_mutex.synchronize do
return if attribute_methods_generated?
superclass.define_attribute_methods unless self == base_class
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index fa5846de39..198db715b2 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -5,6 +5,7 @@ end
require 'yaml'
require 'set'
+require 'thread'
require 'active_support/benchmarkable'
require 'active_support/dependencies'
require 'active_support/descendants_tracker'
@@ -390,12 +391,18 @@ module ActiveRecord #:nodoc:
class << self # Class methods
def inherited(child_class) #:nodoc:
- # force attribute methods to be higher in inheritance hierarchy than other generated methods
- child_class.generated_attribute_methods
- child_class.generated_feature_methods
+ child_class.initialize_generated_modules
super
end
+ def initialize_generated_modules #:nodoc:
+ @attribute_methods_mutex = Mutex.new
+
+ # force attribute methods to be higher in inheritance hierarchy than other generated methods
+ generated_attribute_methods
+ generated_feature_methods
+ end
+
def generated_feature_methods
@generated_feature_methods ||= begin
mod = const_set(:GeneratedFeatureMethods, Module.new)
diff --git a/activerecord/lib/active_record/counter_cache.rb b/activerecord/lib/active_record/counter_cache.rb
index 031918712a..c9c46b8d4f 100644
--- a/activerecord/lib/active_record/counter_cache.rb
+++ b/activerecord/lib/active_record/counter_cache.rb
@@ -25,9 +25,10 @@ module ActiveRecord
self.name
end
+ foreign_key = has_many_association.foreign_key.to_s
child_class = has_many_association.klass
belongs_to = child_class.reflect_on_all_associations(:belongs_to)
- reflection = belongs_to.find { |e| e.class_name == expected_name }
+ reflection = belongs_to.find { |e| e.foreign_key.to_s == foreign_key }
counter_name = reflection.counter_cache_column
stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({
diff --git a/activerecord/lib/active_record/locking/pessimistic.rb b/activerecord/lib/active_record/locking/pessimistic.rb
index 66994e4797..58af92f0b1 100644
--- a/activerecord/lib/active_record/locking/pessimistic.rb
+++ b/activerecord/lib/active_record/locking/pessimistic.rb
@@ -38,6 +38,18 @@ module ActiveRecord
# account2.save!
# end
#
+ # You can start a transaction and acquire the lock in one go by calling
+ # <tt>with_lock</tt> with a block. The block is called from within
+ # a transaction, the object is already locked. Example:
+ #
+ # account = Account.first
+ # account.with_lock do
+ # # This block is called within a transaction,
+ # # account is already locked.
+ # account.balance -= 100
+ # account.save!
+ # end
+ #
# Database-specific information on row locking:
# MySQL: http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html
# PostgreSQL: http://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE
@@ -50,6 +62,16 @@ module ActiveRecord
reload(:lock => lock) if persisted?
self
end
+
+ # Wraps the passed block in a transaction, locking the object
+ # before yielding. You pass can the SQL locking clause
+ # as argument (see <tt>lock!</tt>).
+ def with_lock(lock = true)
+ transaction do
+ lock!(lock)
+ yield
+ end
+ end
end
end
end
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 7fd5ad88d9..fab2cd77f0 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -57,9 +57,9 @@ module ActiveRecord
# array, it actually returns a relation object and can have other query
# methods appended to it, such as the other methods in ActiveRecord::QueryMethods.
#
- # This method will also take multiple parameters:
+ # The argument to the method can also be an array of fields.
#
- # >> Model.select(:field, :other_field, :and_one_more)
+ # >> Model.select([:field, :other_field, :and_one_more])
# => [#<Model field: "value", other_field: "value", and_one_more: "value">]
#
# Any attributes that do not have fields retrieved by a select
diff --git a/activerecord/lib/active_record/version.rb b/activerecord/lib/active_record/version.rb
index ae6110aa96..7d845896a0 100644
--- a/activerecord/lib/active_record/version.rb
+++ b/activerecord/lib/active_record/version.rb
@@ -3,7 +3,7 @@ module ActiveRecord
MAJOR = 3
MINOR = 2
TINY = 0
- PRE = "rc2"
+ PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb
index 7665f1c12e..6562041e9b 100644
--- a/activerecord/test/cases/attribute_methods/read_test.rb
+++ b/activerecord/test/cases/attribute_methods/read_test.rb
@@ -1,5 +1,6 @@
require "cases/helper"
require 'active_support/core_ext/object/inclusion'
+require 'thread'
module ActiveRecord
module AttributeMethods
@@ -19,6 +20,13 @@ module ActiveRecord
include ActiveRecord::AttributeMethods
+ def self.define_attribute_methods
+ # Created in the inherited/included hook for "proper" ARs
+ @attribute_methods_mutex ||= Mutex.new
+
+ super
+ end
+
def self.column_names
%w{ one two three }
end
diff --git a/activerecord/test/cases/counter_cache_test.rb b/activerecord/test/cases/counter_cache_test.rb
index 3ed96a3ec8..cd3d19e783 100644
--- a/activerecord/test/cases/counter_cache_test.rb
+++ b/activerecord/test/cases/counter_cache_test.rb
@@ -6,9 +6,11 @@ require 'models/engine'
require 'models/reply'
require 'models/category'
require 'models/categorization'
+require 'models/dog'
+require 'models/dog_lover'
class CounterCacheTest < ActiveRecord::TestCase
- fixtures :topics, :categories, :categorizations, :cars
+ fixtures :topics, :categories, :categorizations, :cars, :dogs, :dog_lovers
class ::SpecialTopic < ::Topic
has_many :special_replies, :foreign_key => 'parent_id'
@@ -61,7 +63,7 @@ class CounterCacheTest < ActiveRecord::TestCase
end
end
- test "reset counter should with belongs_to which has class_name" do
+ test "reset counter with belongs_to which has class_name" do
car = cars(:honda)
assert_nothing_raised do
Car.reset_counters(car.id, :engines)
@@ -71,6 +73,20 @@ class CounterCacheTest < ActiveRecord::TestCase
end
end
+ test "reset the right counter if two have the same class_name" do
+ david = dog_lovers(:david)
+
+ DogLover.increment_counter(:bred_dogs_count, david.id)
+ DogLover.increment_counter(:trained_dogs_count, david.id)
+
+ assert_difference 'david.reload.bred_dogs_count', -1 do
+ DogLover.reset_counters(david.id, :bred_dogs)
+ end
+ assert_difference 'david.reload.trained_dogs_count', -1 do
+ DogLover.reset_counters(david.id, :trained_dogs)
+ end
+ end
+
test "update counter with initial null value" do
category = categories(:general)
assert_equal 2, category.categorizations.count
diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb
index be7edb858f..6da9830525 100644
--- a/activerecord/test/cases/locking_test.rb
+++ b/activerecord/test/cases/locking_test.rb
@@ -415,6 +415,26 @@ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter) || in_memory_db?
end
end
+ def test_with_lock_commits_transaction
+ person = Person.find 1
+ person.with_lock do
+ person.first_name = 'fooman'
+ person.save!
+ end
+ assert_equal 'fooman', person.reload.first_name
+ end
+
+ def test_with_lock_rolls_back_transaction
+ person = Person.find 1
+ old = person.first_name
+ person.with_lock do
+ person.first_name = 'fooman'
+ person.save!
+ raise 'oops'
+ end rescue nil
+ assert_equal old, person.reload.first_name
+ end
+
if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
def test_no_locks_no_wait
first, second = duel { Person.find 1 }
diff --git a/activerecord/test/fixtures/dog_lovers.yml b/activerecord/test/fixtures/dog_lovers.yml
new file mode 100644
index 0000000000..d3e5e4a1aa
--- /dev/null
+++ b/activerecord/test/fixtures/dog_lovers.yml
@@ -0,0 +1,4 @@
+david:
+ id: 1
+ bred_dogs_count: 0
+ trained_dogs_count: 1
diff --git a/activerecord/test/fixtures/dogs.yml b/activerecord/test/fixtures/dogs.yml
new file mode 100644
index 0000000000..16d19be2c5
--- /dev/null
+++ b/activerecord/test/fixtures/dogs.yml
@@ -0,0 +1,3 @@
+sophie:
+ id: 1
+ trainer_id: 1
diff --git a/activerecord/test/models/dog.rb b/activerecord/test/models/dog.rb
new file mode 100644
index 0000000000..72b7d33a86
--- /dev/null
+++ b/activerecord/test/models/dog.rb
@@ -0,0 +1,4 @@
+class Dog < ActiveRecord::Base
+ belongs_to :breeder, :class_name => "DogLover", :counter_cache => :bred_dogs_count
+ belongs_to :trainer, :class_name => "DogLover", :counter_cache => :trained_dogs_count
+end
diff --git a/activerecord/test/models/dog_lover.rb b/activerecord/test/models/dog_lover.rb
new file mode 100644
index 0000000000..a33dc575c5
--- /dev/null
+++ b/activerecord/test/models/dog_lover.rb
@@ -0,0 +1,4 @@
+class DogLover < ActiveRecord::Base
+ has_many :trained_dogs, :class_name => "Dog", :foreign_key => :trainer_id
+ has_many :bred_dogs, :class_name => "Dog", :foreign_key => :breeder_id
+end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 5933e1f46e..8a29089011 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -212,6 +212,16 @@ ActiveRecord::Schema.define do
t.integer :access_level, :default => 1
end
+ create_table :dog_lovers, :force => true do |t|
+ t.integer :trained_dogs_count, :default => 0
+ t.integer :bred_dogs_count, :default => 0
+ end
+
+ create_table :dogs, :force => true do |t|
+ t.integer :trainer_id
+ t.integer :breeder_id
+ end
+
create_table :edges, :force => true, :id => false do |t|
t.column :source_id, :integer, :null => false
t.column :sink_id, :integer, :null => false
diff --git a/activeresource/CHANGELOG.md b/activeresource/CHANGELOG.md
index 09d1eeb1c8..a69bfd0d73 100644
--- a/activeresource/CHANGELOG.md
+++ b/activeresource/CHANGELOG.md
@@ -1,4 +1,4 @@
-## Rails 3.2.0 (unreleased) ##
+## Rails 3.2.0 (January 20, 2012) ##
* Redirect responses: 303 See Other and 307 Temporary Redirect now behave like
301 Moved Permanently and 302 Found. GH #3302.
diff --git a/activeresource/lib/active_resource/version.rb b/activeresource/lib/active_resource/version.rb
index 4b2532be06..7609b6f07c 100644
--- a/activeresource/lib/active_resource/version.rb
+++ b/activeresource/lib/active_resource/version.rb
@@ -3,7 +3,7 @@ module ActiveResource
MAJOR = 3
MINOR = 2
TINY = 0
- PRE = "rc2"
+ PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index fe4c64aed0..db0832e741 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,4 +1,4 @@
-## Rails 3.2.0 (unreleased) ##
+## Rails 3.2.0 (January 20, 2012) ##
* ActiveSupport::Base64 is deprecated in favor of ::Base64. *Sergey Nartimov*
diff --git a/activesupport/lib/active_support/base64.rb b/activesupport/lib/active_support/base64.rb
index bb4c955eea..61a4af1a87 100644
--- a/activesupport/lib/active_support/base64.rb
+++ b/activesupport/lib/active_support/base64.rb
@@ -40,7 +40,7 @@ module ActiveSupport
def self.decode64(value)
ActiveSupport::Deprecation.warn "ActiveSupport::Base64.decode64 " \
"is deprecated. Use Base64.decode64 instead", caller
- ::Base64.encode64(value)
+ ::Base64.decode64(value)
end
def self.encode64s(value)
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 0495741c15..f5fd86bf74 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -396,7 +396,7 @@ module ActiveSupport
def __run_callback(key, kind, object, &blk) #:nodoc:
name = __callback_runner_name(key, kind)
unless object.respond_to?(name)
- str = send("_#{kind}_callbacks").compile(key, object)
+ str = object.send("_#{kind}_callbacks").compile(key, object)
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def #{name}() #{str} end
protected :#{name}
diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
index 48cf1a435d..6f3fd416c1 100644
--- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
@@ -4,7 +4,7 @@ class DateTime
class << self
# DateTimes aren't aware of DST rules, so use a consistent non-DST offset when creating a DateTime with an offset in the local zone
def local_offset
- ::Time.local(2007).utc_offset.to_r / 86400
+ ::Time.local(2012).utc_offset.to_r / 86400
end
# Returns <tt>Time.zone.now.to_datetime</tt> when <tt>Time.zone</tt> or <tt>config.time_zone</tt> are set, otherwise returns <tt>Time.now.to_datetime</tt>.
diff --git a/activesupport/lib/active_support/tagged_logging.rb b/activesupport/lib/active_support/tagged_logging.rb
index 2fad91495d..d71215b447 100644
--- a/activesupport/lib/active_support/tagged_logging.rb
+++ b/activesupport/lib/active_support/tagged_logging.rb
@@ -27,7 +27,7 @@ module ActiveSupport
new_tags.size.times { tags.pop }
end
- def silence(temporary_level = ERROR, &block)
+ def silence(temporary_level = Logger::ERROR, &block)
@logger.silence(temporary_level, &block)
end
deprecate :silence
diff --git a/activesupport/lib/active_support/version.rb b/activesupport/lib/active_support/version.rb
index 7a9037ee32..0fee9e5c31 100644
--- a/activesupport/lib/active_support/version.rb
+++ b/activesupport/lib/active_support/version.rb
@@ -3,7 +3,7 @@ module ActiveSupport
MAJOR = 3
MINOR = 2
TINY = 0
- PRE = "rc2"
+ PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb
index e723121bb4..c88e7550be 100644
--- a/activesupport/test/callbacks_test.rb
+++ b/activesupport/test/callbacks_test.rb
@@ -298,7 +298,7 @@ module CallbacksTest
end
end
end
-
+
class AroundPersonResult < MySuper
attr_reader :result
@@ -309,7 +309,7 @@ module CallbacksTest
def tweedle_dum
@result = yield
end
-
+
def tweedle_1
:tweedle_1
end
@@ -317,7 +317,7 @@ module CallbacksTest
def tweedle_2
:tweedle_2
end
-
+
def save
run_callbacks :save do
:running
@@ -345,6 +345,55 @@ module CallbacksTest
end
end
+
+ module ExtendModule
+ def self.extended(base)
+ base.class_eval do
+ set_callback :save, :before, :record3
+ end
+ end
+ def record3
+ @recorder << 3
+ end
+ end
+
+ module IncludeModule
+ def self.included(base)
+ base.class_eval do
+ set_callback :save, :before, :record2
+ end
+ end
+ def record2
+ @recorder << 2
+ end
+ end
+
+ class ExtendCallbacks
+
+ include ActiveSupport::Callbacks
+
+ define_callbacks :save
+ set_callback :save, :before, :record1
+
+ include IncludeModule
+
+ def save
+ run_callbacks :save
+ end
+
+ attr_reader :recorder
+
+ def initialize
+ @recorder = []
+ end
+
+ private
+
+ def record1
+ @recorder << 1
+ end
+ end
+
class AroundCallbacksTest < Test::Unit::TestCase
def test_save_around
around = AroundPerson.new
@@ -363,7 +412,7 @@ module CallbacksTest
], around.history
end
end
-
+
class AroundCallbackResultTest < Test::Unit::TestCase
def test_save_around
around = AroundPersonResult.new
@@ -646,4 +695,12 @@ module CallbacksTest
end
end
+ class ExtendCallbacksTest < Test::Unit::TestCase
+ def test_save
+ model = ExtendCallbacks.new.extend ExtendModule
+ model.save
+ assert_equal [1, 2, 3], model.recorder
+ end
+ end
+
end
diff --git a/activesupport/test/core_ext/base64_ext_test.rb b/activesupport/test/core_ext/base64_ext_test.rb
index 544c990b3c..07052a366a 100644
--- a/activesupport/test/core_ext/base64_ext_test.rb
+++ b/activesupport/test/core_ext/base64_ext_test.rb
@@ -7,4 +7,13 @@ class Base64Test < Test::Unit::TestCase
assert_no_match(/\n/, ActiveSupport::Base64.encode64s("oneverylongstringthatwouldnormallybesplitupbynewlinesbytheregularbase64"))
end
end
+
+ def test_encode_and_decode
+ ActiveSupport::Deprecation.silence do
+ string = "foobar"
+ encoded_string = ActiveSupport::Base64.encode64(string)
+ assert_equal "Zm9vYmFy\n", encoded_string
+ assert_equal string, ActiveSupport::Base64.decode64(encoded_string)
+ end
+ end
end
diff --git a/activesupport/test/tagged_logging_test.rb b/activesupport/test/tagged_logging_test.rb
index 17c4214dfc..7ecab33a9a 100644
--- a/activesupport/test/tagged_logging_test.rb
+++ b/activesupport/test/tagged_logging_test.rb
@@ -64,4 +64,10 @@ class TaggedLoggingTest < ActiveSupport::TestCase
assert_equal "[BCX] [Jason] Funky time\n[BCX] Junky time!\n", @output.string
end
+
+ test "silence" do
+ assert_deprecated do
+ assert_nothing_raised { @logger.silence {} }
+ end
+ end
end
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 3083cf1bf2..0c3f5aeb78 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,4 +1,4 @@
-## Rails 3.2.0 (unreleased) ##
+## Rails 3.2.0 (January 20, 2012) ##
* Rails 2.3-style plugins in vendor/plugins are deprecated and will be removed in Rails 4.0. Move them out of vendor/plugins and bundle them in your Gemfile, or fold them in to your app as lib/myplugin/* and config/initializers/myplugin.rb. *Santiago Pastorino*
diff --git a/railties/guides/code/getting_started/Gemfile b/railties/guides/code/getting_started/Gemfile
index 898510dcaa..768985070c 100644
--- a/railties/guides/code/getting_started/Gemfile
+++ b/railties/guides/code/getting_started/Gemfile
@@ -1,8 +1,9 @@
-source 'http://rubygems.org'
+source 'https://rubygems.org'
+
+gem 'rails', '3.2.0'
-gem 'rails', '3.1.0'
# Bundle edge Rails instead:
-# gem 'rails', :git => 'git://github.com/rails/rails.git'
+# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'sqlite3'
@@ -10,13 +11,23 @@ gem 'sqlite3'
# Gems used only for assets and not required
# in production environments by default.
group :assets do
- gem 'sass-rails', " ~> 3.1.0"
- gem 'coffee-rails', "~> 3.1.0"
- gem 'uglifier'
+ gem 'sass-rails', '~> 3.2.3'
+ gem 'coffee-rails', '~> 3.2.1'
+
+ # See https://github.com/sstephenson/execjs#readme for more supported runtimes
+ # gem 'therubyracer'
+
+ gem 'uglifier', '>= 1.0.3'
end
gem 'jquery-rails'
+# To use ActiveModel has_secure_password
+# gem 'bcrypt-ruby', '~> 3.0.0'
+
+# To use Jbuilder templates for JSON
+# gem 'jbuilder'
+
# Use unicorn as the web server
# gem 'unicorn'
diff --git a/railties/guides/code/getting_started/app/assets/javascripts/application.js b/railties/guides/code/getting_started/app/assets/javascripts/application.js
index 37c7bfcdb5..9097d830e2 100644
--- a/railties/guides/code/getting_started/app/assets/javascripts/application.js
+++ b/railties/guides/code/getting_started/app/assets/javascripts/application.js
@@ -1,9 +1,15 @@
-// This is a manifest file that'll be compiled into including all the files listed below.
-// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
-// be included in the compiled file accessible from http://example.com/assets/application.js
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
+//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
+// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
+// GO AFTER THE REQUIRES BELOW.
+//
//= require jquery
//= require jquery_ujs
//= require_tree .
diff --git a/railties/guides/code/getting_started/app/assets/stylesheets/application.css b/railties/guides/code/getting_started/app/assets/stylesheets/application.css
index fc25b5723f..3b5cc6648e 100644
--- a/railties/guides/code/getting_started/app/assets/stylesheets/application.css
+++ b/railties/guides/code/getting_started/app/assets/stylesheets/application.css
@@ -1,7 +1,13 @@
/*
- * This is a manifest file that'll automatically include all the stylesheets available in this directory
- * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
- * the top of the compiled file, but it's generally better to create a new file per style scope.
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
+ * compiled file, but it's generally better to create a new file per style scope.
+ *
*= require_self
- *= require_tree .
-*/ \ No newline at end of file
+ *= require_tree .
+*/
diff --git a/railties/guides/code/getting_started/app/views/layouts/application.html.erb b/railties/guides/code/getting_started/app/views/layouts/application.html.erb
index 7fd6b4f516..6578a41da2 100644
--- a/railties/guides/code/getting_started/app/views/layouts/application.html.erb
+++ b/railties/guides/code/getting_started/app/views/layouts/application.html.erb
@@ -6,7 +6,7 @@
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
-<body style="background: #EEEEEE;">
+<body>
<%= yield %>
diff --git a/railties/guides/code/getting_started/config/application.rb b/railties/guides/code/getting_started/config/application.rb
index e16da30f72..9026a5b5e1 100644
--- a/railties/guides/code/getting_started/config/application.rb
+++ b/railties/guides/code/getting_started/config/application.rb
@@ -4,7 +4,7 @@ require 'rails/all'
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
- Bundler.require *Rails.groups(:assets => %w(development test))
+ Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
@@ -44,6 +44,12 @@ module Blog
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
+ # Enforce whitelist mode for mass assignment.
+ # This will create an empty whitelist of attributes available for mass-assignment for all models
+ # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
+ # parameters by using an attr_accessible or attr_protected declaration.
+ # config.active_record.whitelist_attributes = true
+
# Enable the asset pipeline
config.assets.enabled = true
diff --git a/railties/guides/code/getting_started/config/environments/test.rb b/railties/guides/code/getting_started/config/environments/test.rb
index 08697cbbc9..8b826f56ef 100644
--- a/railties/guides/code/getting_started/config/environments/test.rb
+++ b/railties/guides/code/getting_started/config/environments/test.rb
@@ -29,9 +29,9 @@ Blog::Application.configure do
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
+ # Raise exception on mass assignment protection for Active Record models
+ config.active_record.mass_assignment_sanitizer = :strict
+
# Print deprecation notices to the stderr
config.active_support.deprecation = :stderr
-
- # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets
- config.assets.allow_debugging = true
end
diff --git a/railties/guides/code/getting_started/config/initializers/inflections.rb b/railties/guides/code/getting_started/config/initializers/inflections.rb
index 9e8b0131f8..5d8d9be237 100644
--- a/railties/guides/code/getting_started/config/initializers/inflections.rb
+++ b/railties/guides/code/getting_started/config/initializers/inflections.rb
@@ -8,3 +8,8 @@
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
+#
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections do |inflect|
+# inflect.acronym 'RESTful'
+# end
diff --git a/railties/guides/code/getting_started/config/routes.rb b/railties/guides/code/getting_started/config/routes.rb
index 31f0d210db..b048ac68f1 100644
--- a/railties/guides/code/getting_started/config/routes.rb
+++ b/railties/guides/code/getting_started/config/routes.rb
@@ -1,7 +1,7 @@
Blog::Application.routes.draw do
- resources :posts do
- resources :comments
- end
+ resources :posts do
+ resources :comments
+ end
get "home/index"
@@ -60,5 +60,5 @@ Blog::Application.routes.draw do
# This is a legacy wild controller route that's not recommended for RESTful applications.
# Note: This route will make all actions in every controller accessible via GET requests.
- # match ':controller(/:action(/:id(.:format)))'
+ # match ':controller(/:action(/:id))(.:format)'
end
diff --git a/railties/guides/code/getting_started/public/500.html b/railties/guides/code/getting_started/public/500.html
index b80307fc16..f3648a0dbc 100644
--- a/railties/guides/code/getting_started/public/500.html
+++ b/railties/guides/code/getting_started/public/500.html
@@ -20,7 +20,6 @@
<!-- This file lives in public/500.html -->
<div class="dialog">
<h1>We're sorry, but something went wrong.</h1>
- <p>We've been notified about this issue and we'll take a look at it shortly.</p>
</div>
</body>
</html>
diff --git a/railties/guides/source/3_2_release_notes.textile b/railties/guides/source/3_2_release_notes.textile
index 41f565ea28..74bc757948 100644
--- a/railties/guides/source/3_2_release_notes.textile
+++ b/railties/guides/source/3_2_release_notes.textile
@@ -27,6 +27,7 @@ h4. What to update in your apps
** <tt>rails = 3.2.0</tt>
** <tt>sass-rails ~> 3.2.3</tt>
** <tt>coffee-rails ~> 3.2.1</tt>
+** <tt>uglifier >= 1.0.3</tt>
* Rails 3.2 deprecates <tt>vendor/plugins</tt> and Rails 4.0 will remove them completely. You can start replacing these plugins by extracting them as gems and adding them in your Gemfile. If you choose not to make them gems, you can move them into, say, <tt>lib/my_plugin/*</tt> and add an appropriate initializer in <tt>config/initializers/my_plugin.rb</tt>.
@@ -138,10 +139,16 @@ will create indexes for +title+ and +author+ with the latter being an unique ind
* Remove old <tt>config.paths.app.controller</tt> API in favor of <tt>config.paths["app/controller"]</tt>.
-h4. Deprecations
+h4(#railties_deprecations). Deprecations
* +Rails::Plugin+ is deprecated and will be removed in Rails 4.0. Instead of adding plugins to +vendor/plugins+ use gems or bundler with path or git dependencies.
+h3. Action Mailer
+
+* Upgraded <tt>mail</tt> version to 2.4.0.
+
+* Removed the old Action Mailer API which was deprecated since Rails 3.0.
+
h3. Action Pack
h4. Action Controller
@@ -198,7 +205,7 @@ We now no longer write out HTTP_COOKIE and the cookie jar is persistent between
* Assets should use the request protocol by default or default to relative if no request is available.
-h5. Deprecations
+h5(#actioncontroller_deprecations). Deprecations
* Deprecated implied layout lookup in controllers whose parent had a explicit layout set:
@@ -213,9 +220,17 @@ end
In the example above, Posts controller will no longer automatically look up for a posts layout. If you need this functionality you could either remove <tt>layout "application"</tt> from +ApplicationController+ or explicitly set it to +nil+ in +PostsController+.
+* Deprecated <tt>ActionController::UnknownAction</tt> in favour of <tt>AbstractController::ActionNotFound</tt>.
+
+* Deprecated <tt>ActionController::DoubleRenderError</tt> in favour of <tt>AbstractController::DoubleRenderError</tt>.
+
+* Deprecated <tt>method_missing</tt> in favour of +action_missing+ for missing actions.
+
+* Deprecated <tt>ActionController#rescue_action</tt>, <tt>ActionController#initialize_template_class</tt> and <tt>ActionController#assign_shortcuts</tt>.
+
h4. Action Dispatch
-* Use a BodyProxy instead of including a Module that responds to close. Closes #4441 if Active Record is disabled assets are delivered correctly.
+* Add <tt>config.action_dispatch.default_charset</tt> to configure default charset for <tt>ActionDispatch::Response</tt>.
* Added <tt>ActionDispatch::RequestId</tt> middleware that'll make a unique X-Request-Id header available to the response and enables the <tt>ActionDispatch::Request#uuid</tt> method. This makes it easy to trace requests from end-to-end in the stack and to identify individual requests in mixed logs like Syslog.
@@ -223,6 +238,10 @@ h4. Action Dispatch
* Allow rescue responses to be configured through a railtie as in <tt>config.action_dispatch.rescue_responses</tt>.
+h5(#actiondispatch_deprecations). Deprecations
+
+* Deprecated the ability to set a default charset at the controller level, use the new <tt>config.action_dispatch.default_charset</tt> instead.
+
h4. Action View
* Add +button_tag+ support to <tt>ActionView::Helpers::FormBuilder</tt>. This support mimics the default behavior of +submit_tag+.
@@ -266,14 +285,20 @@ end
* Added +font_path+ helper method that computes the path to a font asset in <tt>public/fonts</tt>.
-h5. Deprecations
+h5(#actionview_deprecations). Deprecations
* Passing formats or handlers to render :template and friends like <tt>render :template => "foo.html.erb"</tt> is deprecated. Instead, you can provide :handlers and :formats directly as an options: <tt> render :template => "foo", :formats => [:html, :js], :handlers => :erb</tt>.
+h4. Sprockets
+
+* Adds a configuration option <tt>config.assets.logger</tt> to control Sprockets logging. Set it to +false+ to turn off logging and to +nil+ to default to +Rails.logger+.
+
h3. Active Record
* Boolean columns with 'on' and 'ON' values are type casted to true.
+* When the +timestamps+ method creates the +created_at+ and +updated_at+ columns, it makes them non-nullable by default.
+
* Implemented <tt>ActiveRecord::Relation#explain</tt>.
* Implements <tt>AR::Base.silence_auto_explain</tt> which allows the user to selectively disable automatic EXPLAINs within a block.
@@ -347,7 +372,34 @@ has_many :clients, :class_name => :Client # Note that the symbol need to be capi
User.where(:first_name => "Scarlett").first_or_create!(:last_name => "Johansson")
</ruby>
-h4. Deprecations
+* Added a <tt>with_lock</tt> method to Active Record objects, which starts a transaction, locks the object (pessimistically) and yields to the block. The method takes one (optional) parameter and passes it to +lock!+.
+
+This makes it possible to write the following:
+
+<ruby>
+class Order < ActiveRecord::Base
+ def cancel!
+ transaction do
+ lock!
+ # ... cancelling logic
+ end
+ end
+end
+</ruby>
+
+as:
+
+<ruby>
+class Order < ActiveRecord::Base
+ def cancel!
+ with_lock do
+ # ... cancelling logic
+ end
+ end
+end
+</ruby>
+
+h4(#activerecord_deprecations). Deprecations
* Automatic closure of connections in threads is deprecated. For example the following code is deprecated:
@@ -395,7 +447,7 @@ h3. Active Model
* Provide mass_assignment_sanitizer as an easy API to replace the sanitizer behavior. Also support both :logger (default) and :strict sanitizer behavior.
-h4. Deprecations
+h4(#activemodel_deprecations). Deprecations
* Deprecated <tt>define_attr_method</tt> in <tt>ActiveModel::AttributeMethods</tt> because this only existed to support methods like +set_table_name+ in Active Record, which are themselves being deprecated.
@@ -455,7 +507,7 @@ Event.where(:created_at => Time.now.all_day)
* Removed <tt>ActiveSupport::SecureRandom</tt> in favor of <tt>SecureRandom</tt> from the standard library.
-h4. Deprecations
+h4(#activesupport_deprecations). Deprecations
* +ActiveSupport::Base64+ is deprecated in favor of <tt>::Base64</tt>.
diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile
index beada85ce3..5970a45839 100644
--- a/railties/guides/source/active_record_querying.textile
+++ b/railties/guides/source/active_record_querying.textile
@@ -692,6 +692,17 @@ Item.transaction do
end
</ruby>
+If you already have an instance of your model, you can start a transaction and acquire the lock in one go using the following code:
+
+<ruby>
+item = Item.first
+item.with_lock do
+ # This block is called within a transaction,
+ # item is already locked.
+ item.increment!(:views)
+end
+</ruby>
+
h3. Joining Tables
Active Record provides a finder method called +joins+ for specifying +JOIN+ clauses on the resulting SQL. There are multiple ways to use the +joins+ method.
diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile
index da7d46ef71..ff2bd08602 100644
--- a/railties/guides/source/asset_pipeline.textile
+++ b/railties/guides/source/asset_pipeline.textile
@@ -109,22 +109,74 @@ NOTE: You must have an "ExecJS":https://github.com/sstephenson/execjs#readme sup
h4. Asset Organization
-Assets that must be precompiled can be placed inside an application in one of three locations: +app/assets+, +lib/assets+ or +vendor/assets+.
+Pipeline assets can be placed inside an application in one of three locations: +app/assets+, +lib/assets+ or +vendor/assets+.
+app/assets+ is for assets that are owned by the application, such as custom images, JavaScript files or stylesheets.
+lib/assets+ is for your own libraries' code that doesn't really fit into the scope of the application or those libraries which are shared across applications.
-+vendor/assets+ is for assets that are owned by outside entities, such as code for JavaScript plugins.
++vendor/assets+ is for assets that are owned by outside entities, such as code for JavaScript plugins and CSS frameworks.
-All subdirectories that exist within these three locations are added to the search path for Sprockets. You can see this search path by inspecting +Rails.application.config.assets.paths+ in the Rails console. When a client requests an asset, these paths are traversed (in the order that they occur in the search path) to see if they contain an asset matching the name specified. If an asset is found, it's processed by Sprockets and served.
+h5. Search paths
-You can add additional (fully qualified) paths to the pipeline in +config/application.rb+. For example:
+When a file is referenced from a manifest or a helper, Sprockets searches the three default asset locations for it.
+
+The default locations are: +app/assets/images+ and the subdirectories +javascripts+ and +stylesheets+ in all three asset locations.
+
+For example, these files:
+
+<plain>
+app/assets/javascripts/home.js
+lib/assets/javascripts/moovinator.js
+vendor/assets/javascript/slider.js
+</plain>
+
+would be referenced in a manifest like this:
+
+<plain>
+//= require home
+//= require moovinator
+//= require slider
+</plain>
+
+Assets inside subdirectories can also be accessed.
+
+<plain>
+app/assets/javascripts/sub/something.js
+</plain>
+
+is referenced as:
+
+<plain>
+//= require sub/something
+</plain>
+
+You can view the search path by inspecting +Rails.application.config.assets.paths+ in the Rails console.
+
+Additional (fully qualified) paths can be added to the pipeline in +config/application.rb+. For example:
<ruby>
config.assets.paths << Rails.root.join("app", "assets", "flash")
</ruby>
+Paths are traversed in the order that they occur in the search path.
+
+It is important to note that files you want to reference outside a manifest must be added to the precompile array or they will not be available in the production environment.
+
+h5. Using index files
+
+Sprockets uses files named +index+ (with the relevant extensions) for a special purpose.
+
+For example, if you have a jQuery library with many modules, which is stored in +lib/assets/library_name+, the file +lib/assets/library_name/index.js+ serves as the manifest for all files in this library. This file could include a list of all the required files in order, or a simple <tt>require_tree</tt> directive.
+
+The library as a whole can be accessed in the site's application manifest like so:
+
+<plain>
+//= require library_name
+</plain>
+
+This simplifies maintenance and keeps things clean by allowing related code to be grouped before inclusion elsewhere.
+
h4. Coding Links to Assets
Sprockets does not add any new methods to access your assets - you still use the familiar +javascript_include_tag+ and +stylesheet_link_tag+.
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 09ef308665..2488f86450 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -156,6 +156,7 @@ Rails 3.1, by default, is set up to use the +sprockets+ gem to manage assets wit
* +config.assets.compile+ is a boolean that can be used to turn on live Sprockets compilation in production.
+* +config.assets.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby +Logger+ class. Defaults to the same configured at +config.logger+. Setting +config.assets.logger+ to false will turn off served assets logging.
h4. Configuring Generators
diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile
index 64eb2d8f36..1681629620 100644
--- a/railties/guides/source/form_helpers.textile
+++ b/railties/guides/source/form_helpers.textile
@@ -630,10 +630,10 @@ action for a Person model, +params[:model]+ would usually be a hash of all the a
Fundamentally HTML forms don't know about any sort of structured data, all they generate is name–value pairs, where pairs are just plain strings. The arrays and hashes you see in your application are the result of some parameter naming conventions that Rails uses.
-TIP: You may find you can try out examples in this section faster by using the console to directly invoke Rails' parameter parser. For example,
+TIP: You may find you can try out examples in this section faster by using the console to directly invoke Racks' parameter parser. For example,
<ruby>
-ActionController::UrlEncodedPairParser.parse_query_parameters "name=fred&phone=0123456789"
+Rack::Utils.parse_query "name=fred&phone=0123456789"
# => {"name"=>"fred", "phone"=>"0123456789"}
</ruby>
diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile
index c986b2edce..8f2fa47c8b 100644
--- a/railties/guides/source/getting_started.textile
+++ b/railties/guides/source/getting_started.textile
@@ -450,7 +450,13 @@ start a web server on your development machine. You can do this by running:
$ rails server
</shell>
-TIP: Compiling CoffeeScript to JavaScript requires a JavaScript runtime and the absence of a runtime will give you an +execjs+ error. Usually Mac OS X and Windows come with a JavaScript runtime installed. +therubyracer+ and +therubyrhino+ are the commonly used runtimes for Ruby and JRuby respectively. You can also investigate a list of runtimes at "ExecJS":https://github.com/sstephenson/execjs.
+TIP: Compiling CoffeeScript to JavaScript requires a JavaScript runtime and
+the absence of a runtime will give you an +execjs+ error. Usually Mac OS X
+and Windows come with a JavaScript runtime installed. Rails adds the +therubyracer+ gem
+to Gemfile in a commented line for new apps and you can uncomment if you need it.
++therubyrhino+ is the recommended runtime for JRuby users and is added by default
+to Gemfile in apps generated under JRuby. You can investigate about all the
+supported runtimes at "ExecJS":https://github.com/sstephenson/execjs#readme.
This will fire up an instance of the WEBrick web server by default (Rails can
also use several other web servers). To see your application in action, open a
@@ -1011,7 +1017,7 @@ by its id value. After finding the record, Rails displays it by using
+app/views/posts/show.html.erb+:
<erb>
-<p class="notice"><%= notice %></p>
+<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
@@ -1278,7 +1284,7 @@ So first, we'll wire up the Post show template
(+/app/views/posts/show.html.erb+) to let us make a new comment:
<erb>
-<p class="notice"><%= notice %></p>
+<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
@@ -1344,7 +1350,7 @@ template. This is where we want the comment to show, so let's add that to the
+app/views/posts/show.html.erb+.
<erb>
-<p class="notice"><%= notice %></p>
+<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
@@ -1426,7 +1432,7 @@ Then you can change +app/views/posts/show.html.erb+ to look like the
following:
<erb>
-<p class="notice"><%= notice %></p>
+<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
@@ -1497,7 +1503,7 @@ create a file +app/views/comments/_form.html.erb+ containing:
Then you make the +app/views/posts/show.html.erb+ look like the following:
<erb>
-<p class="notice"><%= notice %></p>
+<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
@@ -1692,10 +1698,10 @@ class Post < ActiveRecord::Base
end
</ruby>
-The +:allow_destroy+ option on the nested attribute declaration tells Rails to
-display a "remove" checkbox on the view that you'll build shortly. The
-+:reject_if+ option prevents saving new tags that do not have any attributes
-filled in.
+The +:allow_destroy+ option tells Rails to enable destroying tags through the
+nested attributes (you'll handle that by displaying a "remove" checkbox on the
+view that you'll build shortly). The +:reject_if+ option prevents saving new
+tags that do not have any attributes filled in.
We will modify +views/posts/_form.html.erb+ to render a partial to make a tag:
@@ -1768,7 +1774,7 @@ Finally, we will edit the <tt>app/views/posts/show.html.erb</tt> template to
show our tags.
<erb>
-<p class="notice"><%= notice %></p>
+<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
@@ -1828,7 +1834,7 @@ Now you can edit the view in <tt>app/views/posts/show.html.erb</tt> to look like
this:
<erb>
-<p class="notice"><%= notice %></p>
+<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index a782441a21..38c9bd7070 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -57,6 +57,7 @@ module Rails
@assets.js_compressor = nil
@assets.css_compressor = nil
@assets.initialize_on_precompile = true
+ @assets.logger = nil
end
def compiled_asset_path
diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb
index b9944bed26..7da495211d 100644
--- a/railties/lib/rails/application/finisher.rb
+++ b/railties/lib/rails/application/finisher.rb
@@ -2,7 +2,6 @@ module Rails
class Application
module Finisher
include Initializable
- $rails_rake_task = nil
initializer :add_generator_templates do
config.generators.templates.unshift(*paths["lib/templates"].existent)
@@ -49,7 +48,7 @@ module Rails
end
initializer :eager_load! do
- if config.cache_classes && !$rails_rake_task
+ if config.cache_classes && !(defined?($rails_rake_task) && $rails_rake_task)
ActiveSupport.run_load_hooks(:before_eager_load, self)
eager_load!
end
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index ca93f9ef9d..781d7bf47c 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -1,5 +1,6 @@
require 'open-uri'
require 'rbconfig'
+require 'active_support/core_ext/array/wrap'
module Rails
module Generators
diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb
index cfd58527ef..8d307ca536 100644
--- a/railties/lib/rails/generators/generated_attribute.rb
+++ b/railties/lib/rails/generators/generated_attribute.rb
@@ -29,8 +29,8 @@ module Rails
case type
when /(string|text|binary|integer)\{(\d+)\}/
return $1, :limit => $2.to_i
- when /decimal\{(\d+),(\d+)\}/
- return :decimal, :precision => $1.to_i, :scale => $2.to_i
+ when /decimal\{(\d+)(,|\.|\-)(\d+)\}/
+ return :decimal, :precision => $1.to_i, :scale => $3.to_i
else
return type, {}
end
diff --git a/railties/lib/rails/version.rb b/railties/lib/rails/version.rb
index d1440ea90c..8820ec314d 100644
--- a/railties/lib/rails/version.rb
+++ b/railties/lib/rails/version.rb
@@ -3,7 +3,7 @@ module Rails
MAJOR = 3
MINOR = 2
TINY = 0
- PRE = "rc2"
+ PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index cedf5fe5d5..eb16713455 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -286,6 +286,14 @@ module ApplicationTests
assert_equal res, last_response.body # value should be unchanged
end
+ test "sets ActionDispatch::Response.default_charset" do
+ make_basic_app do |app|
+ app.config.action_dispatch.default_charset = "utf-16"
+ end
+
+ assert_equal "utf-16", ActionDispatch::Response.default_charset
+ end
+
test "sets all Active Record models to whitelist all attributes by default" do
add_to_config <<-RUBY
config.active_record.whitelist_attributes = true
diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb
index cdac014965..3f4e160988 100644
--- a/railties/test/generators/migration_generator_test.rb
+++ b/railties/test/generators/migration_generator_test.rb
@@ -105,18 +105,18 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
def test_add_migration_with_attributes_index_declaration_and_attribute_options
migration = "add_title_and_content_to_books"
- run_generator [migration, "title:string{40}:index", "content:string{255}", "price:decimal{5,2}:index", "discount:decimal{3,2}:uniq"]
+ run_generator [migration, "title:string{40}:index", "content:string{255}", "price:decimal{1,2}:index", "discount:decimal{3.4}:uniq"]
assert_migration "db/migrate/#{migration}.rb" do |content|
assert_method :change, content do |up|
assert_match(/add_column :books, :title, :string, :limit => 40/, up)
assert_match(/add_column :books, :content, :string, :limit => 255/, up)
assert_match(/add_column :books, :price, :decimal,/, up)
- assert_match(/, :precision => 5/, up)
+ assert_match(/, :precision => 1/, up)
assert_match(/, :scale => 2/, up)
assert_match(/add_column :books, :discount, :decimal,/, up)
assert_match(/, :precision => 3/, up)
- assert_match(/, :scale => 2/, up)
+ assert_match(/, :scale => 4/, up)
end
assert_match(/add_index :books, :title/, content)
assert_match(/add_index :books, :price/, content)
diff --git a/version.rb b/version.rb
index d1440ea90c..8820ec314d 100644
--- a/version.rb
+++ b/version.rb
@@ -3,7 +3,7 @@ module Rails
MAJOR = 3
MINOR = 2
TINY = 0
- PRE = "rc2"
+ PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end