aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionmailer/actionmailer.gemspec2
-rw-r--r--actionpack/CHANGELOG.md5
-rw-r--r--actionpack/lib/action_controller/metal.rb10
-rw-r--r--actionpack/lib/action_controller/metal/implicit_render.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb13
-rw-r--r--actionpack/lib/action_view/helpers/number_helper.rb96
-rw-r--r--actionpack/lib/action_view/locale/en.yml1
-rw-r--r--actionpack/lib/action_view/template.rb5
-rw-r--r--actionpack/lib/action_view/template/error.rb4
-rw-r--r--actionpack/test/controller/base_test.rb6
-rw-r--r--actionpack/test/controller/force_ssl_test.rb3
-rw-r--r--actionpack/test/controller/rescue_test.rb4
-rw-r--r--actionpack/test/dispatch/debug_exceptions_test.rb2
-rw-r--r--actionpack/test/dispatch/show_exceptions_test.rb2
-rw-r--r--actionpack/test/template/number_helper_test.rb1
-rw-r--r--actionpack/test/template/template_error_test.rb4
-rw-r--r--activemodel/lib/active_model/attribute_methods.rb4
-rw-r--r--activerecord/CHANGELOG.md29
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb3
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb16
-rw-r--r--activerecord/lib/active_record/core.rb45
-rw-r--r--activerecord/lib/active_record/locking/pessimistic.rb22
-rw-r--r--activerecord/lib/active_record/railtie.rb3
-rw-r--r--activerecord/test/cases/attribute_methods/read_test.rb8
-rw-r--r--activerecord/test/cases/base_test.rb29
-rw-r--r--activerecord/test/cases/locking_test.rb20
-rw-r--r--activeresource/lib/active_resource/base.rb4
-rw-r--r--activeresource/lib/active_resource/connection.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/uri.rb2
-rw-r--r--activesupport/lib/active_support/log_subscriber.rb6
-rw-r--r--activesupport/lib/active_support/logger.rb35
-rw-r--r--activesupport/lib/active_support/ordered_options.rb5
-rw-r--r--activesupport/lib/active_support/tagged_logging.rb68
-rw-r--r--activesupport/test/broadcast_logger_test.rb82
-rw-r--r--activesupport/test/core_ext/uri_ext_test.rb8
-rw-r--r--activesupport/test/log_subscriber_test.rb4
-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.textile44
-rw-r--r--railties/guides/source/active_record_querying.textile11
-rw-r--r--railties/lib/rails/commands/server.rb9
-rw-r--r--railties/lib/rails/rack/log_tailer.rb10
49 files changed, 503 insertions, 209 deletions
diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec
index 1527e0ad86..c605f1ff04 100644
--- a/actionmailer/actionmailer.gemspec
+++ b/actionmailer/actionmailer.gemspec
@@ -17,5 +17,5 @@ Gem::Specification.new do |s|
s.requirements << 'none'
s.add_dependency('actionpack', version)
- s.add_dependency('mail', '~> 2.4.0')
+ s.add_dependency('mail', '~> 2.4.1')
end
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 382a3cbd1d..5e78aba0cc 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,4 +1,7 @@
## Rails 4.0.0 (unreleased) ##
+
+* Add `:format` option to number_to_percentage *Rodrigo Flores*
+
* Add `config.action_view.logger` to configure logger for ActionView. *Rafael França*
* Deprecated ActionController::Integration in favour of ActionDispatch::Integration
@@ -33,8 +36,6 @@
* Deprecate method_missing handling for not found actions, use action_missing instead. *Carlos Antonio da Silva*
-* Deprecate ActionController#performed?, check for response_body presence 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*
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 3aab77a069..92433ab462 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -181,9 +181,13 @@ module ActionController
@_status = Rack::Utils.status_code(status)
end
- def response_body=(val)
- body = (val.nil? || val.respond_to?(:each)) ? val : [val]
- super body
+ def response_body=(body)
+ body = [body] unless body.nil? || body.respond_to?(:each)
+ super
+ end
+
+ def performed?
+ !!response_body
end
def dispatch(name, request) #:nodoc:
diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb
index e8e465d3ba..ae04b53825 100644
--- a/actionpack/lib/action_controller/metal/implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/implicit_render.rb
@@ -2,7 +2,7 @@ module ActionController
module ImplicitRender
def send_action(method, *args)
ret = super
- default_render unless response_body
+ default_render unless performed?
ret
end
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index db1e3198b3..5b7f1c989c 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -464,7 +464,7 @@ module ActionDispatch
#
# get 'bacon', :to => 'food#bacon'
def get(*args, &block)
- map_method(:get, *args, &block)
+ map_method(:get, args, &block)
end
# Define a route that only recognizes HTTP POST.
@@ -474,7 +474,7 @@ module ActionDispatch
#
# post 'bacon', :to => 'food#bacon'
def post(*args, &block)
- map_method(:post, *args, &block)
+ map_method(:post, args, &block)
end
# Define a route that only recognizes HTTP PUT.
@@ -484,7 +484,7 @@ module ActionDispatch
#
# put 'bacon', :to => 'food#bacon'
def put(*args, &block)
- map_method(:put, *args, &block)
+ map_method(:put, args, &block)
end
# Define a route that only recognizes HTTP PUT.
@@ -494,15 +494,14 @@ module ActionDispatch
#
# delete 'broccoli', :to => 'food#broccoli'
def delete(*args, &block)
- map_method(:delete, *args, &block)
+ map_method(:delete, args, &block)
end
private
- def map_method(method, *args, &block)
+ def map_method(method, args, &block)
options = args.extract_options!
options[:via] = method
- args.push(options)
- match(*args, &block)
+ match(*args, options, &block)
self
end
end
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 5cc3ec1b10..fc1cbfcb14 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -125,11 +125,10 @@ module ActionView
options.symbolize_keys!
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
- currency = I18n.translate(:'number.currency.format', :locale => options[:locale], :default => {})
+ currency = translations_for('currency', options[:locale])
currency[:negative_format] ||= "-" + currency[:format] if currency[:format]
- defaults = DEFAULT_CURRENCY_VALUES.merge(defaults).merge!(currency)
+ defaults = DEFAULT_CURRENCY_VALUES.merge(defaults_translations(options[:locale])).merge!(currency)
defaults[:negative_format] = "-" + options[:format] if options[:format]
options = defaults.merge!(options)
@@ -152,7 +151,6 @@ module ActionView
e.number.to_s.html_safe? ? formatted_number.html_safe : formatted_number
end
end
-
end
# Formats a +number+ as a percentage string (e.g., 65%). You can customize the format in the +options+ hash.
@@ -169,6 +167,8 @@ 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>:format</tt> - Specifies the format of the percentage string
+ # The number field is <tt>%n</tt> (defaults to "%n%").
# * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid.
#
# ==== Examples
@@ -180,6 +180,7 @@ module ActionView
# number_to_percentage(302.24398923423, :precision => 5) # => 302.24399%
# number_to_percentage(1000, :locale => :fr) # => 1 000,000%
# number_to_percentage("98a") # => 98a%
+ # number_to_percentage(100, :format => "%n %") # => 100 %
#
# number_to_percentage("98a", :raise => true) # => InvalidNumberError
def number_to_percentage(number, options = {})
@@ -187,19 +188,20 @@ module ActionView
options.symbolize_keys!
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
- percentage = I18n.translate(:'number.percentage.format', :locale => options[:locale], :default => {})
- defaults = defaults.merge(percentage)
+ defaults = defaults_translations(options[:locale]).merge(translations_for('percentage', options[:locale]))
options = options.reverse_merge(defaults)
+ format = options[:format] || "%n%"
+
begin
- "#{number_with_precision(number, options.merge(:raise => true))}%".html_safe
+ value = number_with_precision(number, options.merge(:raise => true))
+ format.gsub(/%n/, value).html_safe
rescue InvalidNumberError => e
if options[:raise]
raise
else
- e.number.to_s.html_safe? ? "#{e.number}%".html_safe : "#{e.number}%"
+ e.number.to_s.html_safe? ? format.gsub(/%n/, e.number).html_safe : format.gsub(/%n/, e.number)
end
end
end
@@ -231,23 +233,15 @@ module ActionView
def number_with_delimiter(number, options = {})
options.symbolize_keys!
- begin
- Float(number)
- rescue ArgumentError, TypeError
- if options[:raise]
- raise InvalidNumberError, number
- else
- return number
- end
+ parse_float_number(number, options[:raise]) do
+ return number
end
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
- options = options.reverse_merge(defaults)
+ options = options.reverse_merge(defaults_translations(options[:locale]))
parts = number.to_s.to_str.split('.')
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
parts.join(options[:separator]).html_safe
-
end
# Formats a +number+ with the specified level of <tt>:precision</tt> (e.g., 112.32 has a precision
@@ -285,19 +279,11 @@ module ActionView
def number_with_precision(number, options = {})
options.symbolize_keys!
- number = begin
- Float(number)
- rescue ArgumentError, TypeError
- if options[:raise]
- raise InvalidNumberError, number
- else
- return number
- end
+ number = parse_float_number(number, options[:raise]) do
+ return number
end
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
- precision_defaults = I18n.translate(:'number.precision.format', :locale => options[:locale], :default => {})
- defaults = defaults.merge(precision_defaults)
+ defaults = defaults_translations(options[:locale]).merge(translations_for('precision', options[:locale]))
options = options.reverse_merge(defaults) # Allow the user to unset default values: Eg.: :significant => false
precision = options.delete :precision
@@ -324,7 +310,6 @@ module ActionView
else
formatted_number
end
-
end
STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb].freeze
@@ -363,19 +348,11 @@ module ActionView
def number_to_human_size(number, options = {})
options.symbolize_keys!
- number = begin
- Float(number)
- rescue ArgumentError, TypeError
- if options[:raise]
- raise InvalidNumberError, number
- else
- return number
- end
+ number = parse_float_number(number, options[:raise]) do
+ return number
end
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
- human = I18n.translate(:'number.human.format', :locale => options[:locale], :default => {})
- defaults = defaults.merge(human)
+ defaults = defaults_translations(options[:locale]).merge(translations_for('human', options[:locale]))
options = options.reverse_merge(defaults)
#for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
@@ -483,19 +460,11 @@ module ActionView
def number_to_human(number, options = {})
options.symbolize_keys!
- number = begin
- Float(number)
- rescue ArgumentError, TypeError
- if options[:raise]
- raise InvalidNumberError, number
- else
- return number
- end
+ number = parse_float_number(number, options[:raise]) do
+ return number
end
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
- human = I18n.translate(:'number.human.format', :locale => options[:locale], :default => {})
- defaults = defaults.merge(human)
+ defaults = defaults_translations(options[:locale]).merge(translations_for('human', options[:locale]))
options = options.reverse_merge(defaults)
#for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
@@ -533,6 +502,25 @@ module ActionView
decimal_format.gsub(/%n/, formatted_number).gsub(/%u/, unit).strip.html_safe
end
+ private
+
+ def defaults_translations(locale)
+ I18n.translate(:'number.format', :locale => locale, :default => {})
+ end
+
+ def translations_for(namespace, locale)
+ I18n.translate(:"number.#{namespace}.format", :locale => locale, :default => {})
+ end
+
+ def parse_float_number(number, raise_error)
+ Float(number)
+ rescue ArgumentError, TypeError
+ if raise_error
+ raise InvalidNumberError, number
+ else
+ yield
+ end
+ end
end
end
end
diff --git a/actionpack/lib/action_view/locale/en.yml b/actionpack/lib/action_view/locale/en.yml
index f2a83b92a9..7cca7d969a 100644
--- a/actionpack/lib/action_view/locale/en.yml
+++ b/actionpack/lib/action_view/locale/en.yml
@@ -37,6 +37,7 @@
# precision:
# significant: false
# strip_insignificant_zeros: false
+ format: "%n%"
# Used in number_to_precision()
precision:
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 593eaa2abf..edb3d427d5 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -288,7 +288,7 @@ module ActionView
logger.debug "Backtrace: #{e.backtrace.join("\n")}"
end
- raise ActionView::Template::Error.new(self, {}, e)
+ raise ActionView::Template::Error.new(self, e)
end
end
@@ -297,13 +297,12 @@ module ActionView
e.sub_template_of(self)
raise e
else
- assigns = view.respond_to?(:assigns) ? view.assigns : {}
template = self
unless template.source
template = refresh(view)
template.encode!
end
- raise Template::Error.new(template, assigns, e)
+ raise Template::Error.new(template, e)
end
end
diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb
index 83df2604bb..d8258f7b11 100644
--- a/actionpack/lib/action_view/template/error.rb
+++ b/actionpack/lib/action_view/template/error.rb
@@ -55,9 +55,9 @@ module ActionView
attr_reader :original_exception, :backtrace
- def initialize(template, assigns, original_exception)
+ def initialize(template, original_exception)
super(original_exception.message)
- @template, @assigns, @original_exception = template, assigns.dup, original_exception
+ @template, @original_exception = template, original_exception
@sub_templates = nil
@backtrace = original_exception.backtrace
end
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index b95a524612..70e03d24ea 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -93,6 +93,12 @@ class ControllerInstanceTests < ActiveSupport::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!"
diff --git a/actionpack/test/controller/force_ssl_test.rb b/actionpack/test/controller/force_ssl_test.rb
index 125012631e..3ea3c06ac4 100644
--- a/actionpack/test/controller/force_ssl_test.rb
+++ b/actionpack/test/controller/force_ssl_test.rb
@@ -39,10 +39,8 @@ class ForceSSLFlash < ForceSSLController
@flashy = flash["that"]
render :inline => "hello"
end
-
end
-
class ForceSSLControllerLevelTest < ActionController::TestCase
tests ForceSSLControllerLevel
@@ -135,5 +133,4 @@ class ForceSSLFlashTest < ActionController::TestCase
assert_equal "hello", assigns["flash_copy"]["that"]
assert_equal "hello", assigns["flashy"]
end
-
end
diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb
index 86d6737cbb..9c51db135b 100644
--- a/actionpack/test/controller/rescue_test.rb
+++ b/actionpack/test/controller/rescue_test.rb
@@ -137,11 +137,11 @@ class RescueController < ActionController::Base
end
def io_error_in_view
- raise ActionView::TemplateError.new(nil, {}, IOError.new('this is io error'))
+ raise ActionView::TemplateError.new(nil, IOError.new('this is io error'))
end
def zero_division_error_in_view
- raise ActionView::TemplateError.new(nil, {}, ZeroDivisionError.new('this is zero division error'))
+ raise ActionView::TemplateError.new(nil, ZeroDivisionError.new('this is zero division error'))
end
protected
diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb
index c3a565990e..11c292d61a 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -34,7 +34,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
when "/unprocessable_entity"
raise ActionController::InvalidAuthenticityToken
when "/not_found_original_exception"
- raise ActionView::Template::Error.new('template', {}, AbstractController::ActionNotFound.new)
+ raise ActionView::Template::Error.new('template', AbstractController::ActionNotFound.new)
else
raise "puke!"
end
diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb
index 4a6d5ddbf7..45f8fc11b3 100644
--- a/actionpack/test/dispatch/show_exceptions_test.rb
+++ b/actionpack/test/dispatch/show_exceptions_test.rb
@@ -11,7 +11,7 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest
when "/method_not_allowed"
raise ActionController::MethodNotAllowed
when "/not_found_original_exception"
- raise ActionView::Template::Error.new('template', {}, AbstractController::ActionNotFound.new)
+ raise ActionView::Template::Error.new('template', AbstractController::ActionNotFound.new)
else
raise "puke!"
end
diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb
index 8d679aac1d..ca897a48cc 100644
--- a/actionpack/test/template/number_helper_test.rb
+++ b/actionpack/test/template/number_helper_test.rb
@@ -57,6 +57,7 @@ class NumberHelperTest < ActionView::TestCase
assert_equal("1000.000%", number_to_percentage("1000"))
assert_equal("123.4%", number_to_percentage(123.400, :precision => 3, :strip_insignificant_zeros => true))
assert_equal("1.000,000%", number_to_percentage(1000, :delimiter => '.', :separator => ','))
+ assert_equal("1000.000 %", number_to_percentage(1000, :format => "%n %"))
end
def test_number_with_delimiter
diff --git a/actionpack/test/template/template_error_test.rb b/actionpack/test/template/template_error_test.rb
index 3a874082d9..91424daeed 100644
--- a/actionpack/test/template/template_error_test.rb
+++ b/actionpack/test/template/template_error_test.rb
@@ -2,12 +2,12 @@ require "abstract_unit"
class TemplateErrorTest < ActiveSupport::TestCase
def test_provides_original_message
- error = ActionView::Template::Error.new("test", {}, Exception.new("original"))
+ error = ActionView::Template::Error.new("test", Exception.new("original"))
assert_equal "original", error.message
end
def test_provides_useful_inspect
- error = ActionView::Template::Error.new("test", {}, Exception.new("original"))
+ error = ActionView::Template::Error.new("test", Exception.new("original"))
assert_equal "#<ActionView::Template::Error: original>", error.inspect
end
end
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb
index 432f3d4302..52f270ff33 100644
--- a/activemodel/lib/active_model/attribute_methods.rb
+++ b/activemodel/lib/active_model/attribute_methods.rb
@@ -325,14 +325,14 @@ module ActiveModel
end
@prefix, @suffix = options[:prefix] || '', options[:suffix] || ''
- @regex = /^(#{Regexp.escape(@prefix)})(.+?)(#{Regexp.escape(@suffix)})$/
+ @regex = /^(?:#{Regexp.escape(@prefix)})(.*)(?:#{Regexp.escape(@suffix)})$/
@method_missing_target = "#{@prefix}attribute#{@suffix}"
@method_name = "#{prefix}%s#{suffix}"
end
def match(method_name)
if @regex =~ method_name
- AttributeMethodMatch.new(method_missing_target, $2, method_name)
+ AttributeMethodMatch.new(method_missing_target, $1, method_name)
else
nil
end
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index f7de341fbe..a458f9e6e4 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -72,6 +72,33 @@
## Rails 3.2.0 (unreleased) ##
+* 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*
@@ -82,7 +109,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 f8815fefc9..a1e34a3aa1 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
@@ -38,8 +37,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/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index e6ddf8bf8f..dbfb375ba8 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -171,15 +171,15 @@ module ActiveRecord
# Extracts the value from a PostgreSQL column default definition.
def self.extract_value_from_default(default)
+ # This is a performance optimization for Ruby 1.9.2 in development.
+ # If the value is nil, we return nil straight away without checking
+ # the regular expressions. If we check each regular expression,
+ # Regexp#=== will call NilClass#to_str, which will trigger
+ # method_missing (defined by whiny nil in ActiveSupport) which
+ # makes this method very very slow.
+ return default unless default
+
case default
- # This is a performance optimization for Ruby 1.9.2 in development.
- # If the value is nil, we return nil straight away without checking
- # the regular expressions. If we check each regular expression,
- # Regexp#=== will call NilClass#to_str, which will trigger
- # method_missing (defined by whiny nil in ActiveSupport) which
- # makes this method very very slow.
- when NilClass
- nil
# Numeric types
when /\A\(?(-?\d+(\.\d*)?\)?)\z/
$1
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 22574c4ce7..adba3f710c 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -1,4 +1,5 @@
require 'active_support/concern'
+require 'thread'
module ActiveRecord
module Core
@@ -44,10 +45,10 @@ module ActiveRecord
##
# :singleton-method:
- # Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling
- # dates and times from the database. This is set to :local by default.
+ # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
+ # dates and times from the database. This is set to :utc by default.
config_attribute :default_timezone, :global => true
- self.default_timezone = :local
+ self.default_timezone = :utc
##
# :singleton-method:
@@ -80,6 +81,8 @@ module ActiveRecord
end
def initialize_generated_modules
+ @attribute_methods_mutex = Mutex.new
+
# force attribute methods to be higher in inheritance hierarchy than other generated methods
generated_attribute_methods
generated_feature_methods
@@ -152,16 +155,8 @@ module ActiveRecord
# User.new({ :first_name => 'Jamie', :is_admin => true }, :without_protection => true)
def initialize(attributes = nil, options = {})
@attributes = self.class.initialize_attributes(self.class.column_defaults.dup)
- @association_cache = {}
- @aggregation_cache = {}
- @attributes_cache = {}
- @new_record = true
- @readonly = false
- @destroyed = false
- @marked_for_destruction = false
- @previously_changed = {}
- @changed_attributes = {}
- @relation = nil
+
+ init_internals
ensure_proper_type
@@ -185,13 +180,11 @@ module ActiveRecord
# post.title # => 'hello world'
def init_with(coder)
@attributes = self.class.initialize_attributes(coder['attributes'])
- @relation = nil
- @attributes_cache, @previously_changed, @changed_attributes = {}, {}, {}
- @association_cache = {}
- @aggregation_cache = {}
- @readonly = @destroyed = @marked_for_destruction = false
+ init_internals
+
@new_record = false
+
run_callbacks :find
run_callbacks :initialize
@@ -219,7 +212,8 @@ module ActiveRecord
@aggregation_cache = {}
@association_cache = {}
- @attributes_cache = {}
+ @attributes_cache = {}
+
@new_record = true
ensure_proper_type
@@ -330,5 +324,18 @@ module ActiveRecord
def to_ary # :nodoc:
nil
end
+
+ def init_internals
+ @relation = nil
+ @aggregation_cache = {}
+ @association_cache = {}
+ @attributes_cache = {}
+ @previously_changed = {}
+ @changed_attributes = {}
+ @readonly = false
+ @destroyed = false
+ @marked_for_destruction = false
+ @new_record = true
+ end
end
end
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/railtie.rb b/activerecord/lib/active_record/railtie.rb
index b1c8ae5b77..058dd58efb 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -38,7 +38,8 @@ module ActiveRecord
# first time. Also, make it output to STDERR.
console do |app|
require "active_record/railties/console_sandbox" if app.sandbox?
- ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDERR)
+ console = ActiveSupport::Logger.new(STDERR)
+ Rails.logger.extend ActiveSupport::Logger.broadcast console
end
initializer "active_record.initialize_timezone" do
diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb
index 0df9ffc0c5..764305459d 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
@@ -20,6 +21,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/base_test.rb b/activerecord/test/cases/base_test.rb
index f5c139e85f..87a3a0deb9 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -187,6 +187,31 @@ class BasicsTest < ActiveRecord::TestCase
end
end
+ def test_previously_changed
+ topic = Topic.find :first
+ topic.title = '<3<3<3'
+ assert_equal({}, topic.previous_changes)
+
+ topic.save!
+ expected = ["The First Topic", "<3<3<3"]
+ assert_equal(expected, topic.previous_changes['title'])
+ end
+
+ def test_previously_changed_dup
+ topic = Topic.find :first
+ topic.title = '<3<3<3'
+ topic.save!
+
+ t2 = topic.dup
+
+ assert_equal(topic.previous_changes, t2.previous_changes)
+
+ topic.title = "lolwut"
+ topic.save!
+
+ assert_not_equal(topic.previous_changes, t2.previous_changes)
+ end
+
def test_preserving_time_objects
assert_kind_of(
Time, Topic.find(1).bonus_time,
@@ -664,7 +689,7 @@ class BasicsTest < ActiveRecord::TestCase
}
topic = Topic.find(1)
topic.attributes = attributes
- assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on
+ assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on
end
def test_multiparameter_attributes_on_time_with_no_date
@@ -913,7 +938,7 @@ class BasicsTest < ActiveRecord::TestCase
}
topic = Topic.find(1)
topic.attributes = attributes
- assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time
+ assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time
end
def test_boolean
diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb
index 0c458d5318..807274ca67 100644
--- a/activerecord/test/cases/locking_test.rb
+++ b/activerecord/test/cases/locking_test.rb
@@ -388,6 +388,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/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index 548990cb70..ed872c0883 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -939,12 +939,12 @@ module ActiveResource
# Accepts a URI and creates the site URI from that.
def create_site_uri_from(site)
- site.is_a?(URI) ? site.dup : URI.parser.parse(site)
+ site.is_a?(URI) ? site.dup : URI.parse(site)
end
# Accepts a URI and creates the proxy URI from that.
def create_proxy_uri_from(proxy)
- proxy.is_a?(URI) ? proxy.dup : URI.parser.parse(proxy)
+ proxy.is_a?(URI) ? proxy.dup : URI.parse(proxy)
end
# contains a set of the current prefix parameters.
diff --git a/activeresource/lib/active_resource/connection.rb b/activeresource/lib/active_resource/connection.rb
index 94839c8c25..2a034f9269 100644
--- a/activeresource/lib/active_resource/connection.rb
+++ b/activeresource/lib/active_resource/connection.rb
@@ -39,14 +39,14 @@ module ActiveResource
# Set URI for remote service.
def site=(site)
- @site = site.is_a?(URI) ? site : URI.parser.parse(site)
+ @site = site.is_a?(URI) ? site : URI.parse(site)
@user = URI.parser.unescape(@site.user) if @site.user
@password = URI.parser.unescape(@site.password) if @site.password
end
# Set the proxy for remote service.
def proxy=(proxy)
- @proxy = proxy.is_a?(URI) ? proxy : URI.parser.parse(proxy)
+ @proxy = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
end
# Sets the user for remote service.
diff --git a/activesupport/lib/active_support/core_ext/uri.rb b/activesupport/lib/active_support/core_ext/uri.rb
index 0b219ce44a..bfe0832b37 100644
--- a/activesupport/lib/active_support/core_ext/uri.rb
+++ b/activesupport/lib/active_support/core_ext/uri.rb
@@ -20,7 +20,7 @@ end
module URI
class << self
def parser
- @parser ||= URI.const_defined?(:Parser) ? URI::Parser.new : URI
+ @parser ||= URI::Parser.new
end
end
end
diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb
index 6296c1d4b8..58938cdc3d 100644
--- a/activesupport/lib/active_support/log_subscriber.rb
+++ b/activesupport/lib/active_support/log_subscriber.rb
@@ -92,7 +92,7 @@ module ActiveSupport
begin
send(method, ActiveSupport::Notifications::Event.new(message, *args))
rescue Exception => e
- logger.error "Could not log #{message.inspect} event. #{e.class}: #{e.message}"
+ logger.error "Could not log #{message.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
end
end
@@ -100,9 +100,9 @@ module ActiveSupport
%w(info debug warn error fatal unknown).each do |level|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
- def #{level}(*args, &block)
+ def #{level}(progname = nil, &block)
return unless logger
- logger.#{level}(*args, &block)
+ logger.#{level}(progname, &block)
end
METHOD
end
diff --git a/activesupport/lib/active_support/logger.rb b/activesupport/lib/active_support/logger.rb
index 66e8fcadb4..d055767eab 100644
--- a/activesupport/lib/active_support/logger.rb
+++ b/activesupport/lib/active_support/logger.rb
@@ -2,6 +2,41 @@ require 'logger'
module ActiveSupport
class Logger < ::Logger
+ # Broadcasts logs to multiple loggers
+ def self.broadcast(logger) # :nodoc:
+ Module.new do
+ define_method(:add) do |*args, &block|
+ logger.add(*args, &block)
+ super(*args, &block)
+ end
+
+ define_method(:<<) do |x|
+ logger << x
+ super(x)
+ end
+
+ define_method(:close) do
+ logger.close
+ super()
+ end
+
+ define_method(:progname=) do |name|
+ logger.progname = name
+ super(name)
+ end
+
+ define_method(:formatter=) do |formatter|
+ logger.formatter = formatter
+ super(formatter)
+ end
+
+ define_method(:level=) do |level|
+ logger.level = level
+ super(level)
+ end
+ end
+ end
+
def initialize(*args)
super
@formatter = SimpleFormatter.new
diff --git a/activesupport/lib/active_support/ordered_options.rb b/activesupport/lib/active_support/ordered_options.rb
index bf81567d22..9e5a5d0246 100644
--- a/activesupport/lib/active_support/ordered_options.rb
+++ b/activesupport/lib/active_support/ordered_options.rb
@@ -30,8 +30,9 @@ module ActiveSupport #:nodoc:
end
def method_missing(name, *args)
- if name.to_s =~ /(.*)=$/
- self[$1] = args.first
+ name_string = name.to_s
+ if name_string.chomp!('=')
+ self[name_string] = args.first
else
self[name]
end
diff --git a/activesupport/lib/active_support/tagged_logging.rb b/activesupport/lib/active_support/tagged_logging.rb
index c579f1ed51..f6ad861353 100644
--- a/activesupport/lib/active_support/tagged_logging.rb
+++ b/activesupport/lib/active_support/tagged_logging.rb
@@ -1,5 +1,6 @@
require 'active_support/core_ext/object/blank'
require 'logger'
+require 'active_support/logger'
module ActiveSupport
# Wraps any standard Logger object to provide tagging capabilities. Examples:
@@ -11,52 +12,47 @@ module ActiveSupport
#
# This is used by the default Rails.logger as configured by Railties to make it easy to stamp log lines
# with subdomains, request ids, and anything else to aid debugging of multi-user production applications.
- class TaggedLogging
- def initialize(logger)
- @logger = logger
+ module TaggedLogging
+ class Formatter < ActiveSupport::Logger::SimpleFormatter # :nodoc:
+ # This method is invoked when a log event occurs
+ def call(severity, timestamp, progname, msg)
+ super(severity, timestamp, progname, "#{tags_text}#{msg}")
+ end
+
+ def clear!
+ current_tags.clear
+ end
+
+ def current_tags
+ Thread.current[:activesupport_tagged_logging_tags] ||= []
+ end
+
+ private
+ def tags_text
+ tags = current_tags
+ if tags.any?
+ tags.collect { |tag| "[#{tag}] " }.join
+ end
+ end
+ end
+
+ def self.new(logger)
+ logger.formatter = Formatter.new
+ logger.extend(self)
end
def tagged(*new_tags)
- tags = current_tags
- new_tags = Array(new_tags).flatten.reject(&:blank?)
+ tags = formatter.current_tags
+ new_tags = new_tags.flatten.reject(&:blank?)
tags.concat new_tags
yield
ensure
tags.pop(new_tags.size)
end
- def add(severity, message = nil, progname = nil, &block)
- @logger.add(severity, "#{tags_text}#{message}", progname, &block)
- end
-
- %w( fatal error warn info debug unknown ).each do |severity|
- eval <<-EOM, nil, __FILE__, __LINE__ + 1
- def #{severity}(progname = nil, &block) # def warn(progname = nil, &block)
- add(Logger::#{severity.upcase}, progname, &block) # add(Logger::WARN, progname, &block)
- end # end
- EOM
- end
-
def flush
- current_tags.clear
- @logger.flush if @logger.respond_to?(:flush)
- end
-
- def method_missing(method, *args)
- @logger.send(method, *args)
- end
-
- protected
-
- def tags_text
- tags = current_tags
- if tags.any?
- tags.collect { |tag| "[#{tag}] " }.join
- end
- end
-
- def current_tags
- Thread.current[:activesupport_tagged_logging_tags] ||= []
+ formatter.clear!
+ super if defined?(super)
end
end
end
diff --git a/activesupport/test/broadcast_logger_test.rb b/activesupport/test/broadcast_logger_test.rb
new file mode 100644
index 0000000000..6d4e3b74f7
--- /dev/null
+++ b/activesupport/test/broadcast_logger_test.rb
@@ -0,0 +1,82 @@
+require 'abstract_unit'
+
+module ActiveSupport
+ class BroadcastLoggerTest < TestCase
+ attr_reader :logger, :log1, :log2
+ def setup
+ @log1 = FakeLogger.new
+ @log2 = FakeLogger.new
+ @log1.extend Logger.broadcast @log2
+ @logger = @log1
+ end
+
+ def test_debug
+ logger.debug "foo"
+ assert_equal 'foo', log1.adds.first[2]
+ assert_equal 'foo', log2.adds.first[2]
+ end
+
+ def test_close
+ logger.close
+ assert log1.closed, 'should be closed'
+ assert log2.closed, 'should be closed'
+ end
+
+ def test_chevrons
+ logger << "foo"
+ assert_equal %w{ foo }, log1.chevrons
+ assert_equal %w{ foo }, log2.chevrons
+ end
+
+ def test_level
+ assert_nil logger.level
+ logger.level = 10
+ assert_equal 10, log1.level
+ assert_equal 10, log2.level
+ end
+
+ def test_progname
+ assert_nil logger.progname
+ logger.progname = 10
+ assert_equal 10, log1.progname
+ assert_equal 10, log2.progname
+ end
+
+ def test_formatter
+ assert_nil logger.formatter
+ logger.formatter = 10
+ assert_equal 10, log1.formatter
+ assert_equal 10, log2.formatter
+ end
+
+ class FakeLogger
+ attr_reader :adds, :closed, :chevrons
+ attr_accessor :level, :progname, :formatter
+
+ def initialize
+ @adds = []
+ @closed = false
+ @chevrons = []
+ @level = nil
+ @progname = nil
+ @formatter = nil
+ end
+
+ def debug msg, &block
+ add(:omg, nil, msg, &block)
+ end
+
+ def << x
+ @chevrons << x
+ end
+
+ def add(*args)
+ @adds << args
+ end
+
+ def close
+ @closed = true
+ end
+ end
+ end
+end
diff --git a/activesupport/test/core_ext/uri_ext_test.rb b/activesupport/test/core_ext/uri_ext_test.rb
index 4a6cbb8801..03e388dd7a 100644
--- a/activesupport/test/core_ext/uri_ext_test.rb
+++ b/activesupport/test/core_ext/uri_ext_test.rb
@@ -7,11 +7,7 @@ class URIExtTest < ActiveSupport::TestCase
def test_uri_decode_handle_multibyte
str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese.
- if URI.const_defined?(:Parser)
- parser = URI::Parser.new
- assert_equal str, parser.unescape(parser.escape(str))
- else
- assert_equal str, URI.unescape(URI.escape(str))
- end
+ parser = URI::Parser.new
+ assert_equal str, parser.unescape(parser.escape(str))
end
end
diff --git a/activesupport/test/log_subscriber_test.rb b/activesupport/test/log_subscriber_test.rb
index 0c1f3c51ed..8e160714b1 100644
--- a/activesupport/test/log_subscriber_test.rb
+++ b/activesupport/test/log_subscriber_test.rb
@@ -118,6 +118,6 @@ class SyncLogSubscriberTest < ActiveSupport::TestCase
assert_equal 'some_event.my_log_subscriber', @logger.logged(:info).last
assert_equal 1, @logger.logged(:error).size
- assert_equal 'Could not log "puke.my_log_subscriber" event. RuntimeError: puke', @logger.logged(:error).last
+ assert_match 'Could not log "puke.my_log_subscriber" event. RuntimeError: puke', @logger.logged(:error).last
end
-end \ No newline at end of file
+end
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 5f9010fced..dad91d7943 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
@@ -40,6 +40,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 1d45541d5c..e97f82c6bd 100644
--- a/railties/guides/code/getting_started/config/environments/test.rb
+++ b/railties/guides/code/getting_started/config/environments/test.rb
@@ -26,9 +26,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 379b7472c6..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,7 +139,7 @@ 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.
@@ -204,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:
@@ -225,8 +226,6 @@ In the example above, Posts controller will no longer automatically look up for
* Deprecated <tt>method_missing</tt> in favour of +action_missing+ for missing actions.
-* Deprecated <tt>ActionController#performed?</tt> in favour of checking for the presence of <tt>response_body</tt>.
-
* Deprecated <tt>ActionController#rescue_action</tt>, <tt>ActionController#initialize_template_class</tt> and <tt>ActionController#assign_shortcuts</tt>.
h4. Action Dispatch
@@ -239,7 +238,7 @@ h4. Action Dispatch
* Allow rescue responses to be configured through a railtie as in <tt>config.action_dispatch.rescue_responses</tt>.
-h5. Deprecations
+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.
@@ -286,7 +285,7 @@ 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>.
@@ -373,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:
@@ -421,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.
@@ -481,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/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb
index 20484a10c8..0b757cbe28 100644
--- a/railties/lib/rails/commands/server.rb
+++ b/railties/lib/rails/commands/server.rb
@@ -67,6 +67,13 @@ module Rails
FileUtils.mkdir_p(Rails.root.join('tmp', dir_to_make))
end
+ unless options[:daemonize]
+ wrapped_app # touch the app so the logger is set up
+
+ console = ActiveSupport::Logger.new($stdout)
+ Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
+ end
+
super
ensure
# The '-h' option calls exit before @options is set.
@@ -76,7 +83,6 @@ module Rails
def middleware
middlewares = []
- middlewares << [Rails::Rack::LogTailer, log_path] unless options[:daemonize]
middlewares << [Rails::Rack::Debugger] if options[:debugger]
middlewares << [::Rack::ContentLength]
Hash.new(middlewares)
@@ -89,6 +95,7 @@ module Rails
def default_options
super.merge({
:Port => 3000,
+ :DoNotReverseLookup => true,
:environment => (ENV['RAILS_ENV'] || "development").dup,
:daemonize => false,
:debugger => false,
diff --git a/railties/lib/rails/rack/log_tailer.rb b/railties/lib/rails/rack/log_tailer.rb
index 830d840894..18f22e8089 100644
--- a/railties/lib/rails/rack/log_tailer.rb
+++ b/railties/lib/rails/rack/log_tailer.rb
@@ -4,10 +4,13 @@ module Rails
def initialize(app, log = nil)
@app = app
- path = Pathname.new(log || "#{File.expand_path(Rails.root)}/log/#{Rails.env}.log").cleanpath
- @cursor = ::File.size(path)
+ path = Pathname.new(log || "#{::File.expand_path(Rails.root)}/log/#{Rails.env}.log").cleanpath
- @file = ::File.open(path, 'r')
+ @cursor = @file = nil
+ if ::File.exists?(path)
+ @cursor = ::File.size(path)
+ @file = ::File.open(path, 'r')
+ end
end
def call(env)
@@ -17,6 +20,7 @@ module Rails
end
def tail!
+ return unless @cursor
@file.seek @cursor
unless @file.eof?