aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG.md7
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb11
-rw-r--r--actionpack/lib/action_controller/record_identifier.rb7
-rw-r--r--actionpack/lib/action_controller/test_case.rb26
-rw-r--r--actionpack/lib/action_dispatch/routing/redirection.rb18
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb8
-rw-r--r--actionpack/lib/action_view/helpers/tags/check_box.rb6
-rw-r--r--actionpack/lib/action_view/renderer/partial_renderer.rb31
-rw-r--r--actionpack/test/controller/render_json_test.rb2
-rw-r--r--actionpack/test/controller/test_case_test.rb63
-rw-r--r--actionpack/test/dispatch/routing_test.rb60
-rw-r--r--actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb1
-rw-r--r--actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb1
-rw-r--r--actionpack/test/template/form_helper_test.rb117
-rw-r--r--actionpack/test/template/render_test.rb19
-rw-r--r--activemodel/CHANGELOG.md2
-rw-r--r--activemodel/lib/active_model/locale/en.yml2
-rw-r--r--activemodel/lib/active_model/observing.rb11
-rw-r--r--activemodel/lib/active_model/validations/confirmation.rb3
-rw-r--r--activemodel/test/cases/observing_test.rb15
-rw-r--r--activemodel/test/cases/validations/confirmation_validation_test.rb21
-rw-r--r--activemodel/test/cases/validations/i18n_generate_message_validation_test.rb2
-rw-r--r--activemodel/test/cases/validations/i18n_validation_test.rb17
-rw-r--r--activemodel/test/cases/validations/validates_test.rb2
-rw-r--r--activerecord/lib/active_record/persistence.rb8
-rw-r--r--activesupport/CHANGELOG.md2
-rw-r--r--activesupport/lib/active_support/callbacks.rb14
-rw-r--r--activesupport/lib/active_support/core_ext/array/access.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/array/conversions.rb94
-rw-r--r--activesupport/lib/active_support/core_ext/array/grouping.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/array/uniq_by.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute_accessors.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/class/delegating_attributes.rb32
-rw-r--r--activesupport/lib/active_support/core_ext/date/calculations.rb52
-rw-r--r--activesupport/lib/active_support/core_ext/date/conversions.rb19
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/calculations.rb33
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/conversions.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/zones.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/enumerable.rb20
-rw-r--r--activesupport/lib/active_support/core_ext/file/atomic.rb18
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb36
-rw-r--r--activesupport/lib/active_support/core_ext/hash/diff.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/hash/except.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/hash/keys.rb11
-rw-r--r--activesupport/lib/active_support/core_ext/hash/reverse_merge.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/hash/slice.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/reporting.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/logger.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/module/aliasing.rb15
-rw-r--r--activesupport/lib/active_support/core_ext/module/attr_internal.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/module/attribute_accessors.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/module/delegation.rb18
-rw-r--r--activesupport/lib/active_support/core_ext/module/introspection.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/module/qualified_const.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/object/blank.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/object/inclusion.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/object/with_options.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/range/include_range.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/access.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/conversions.rb32
-rw-r--r--activesupport/lib/active_support/core_ext/string/filters.rb27
-rw-r--r--activesupport/lib/active_support/core_ext/string/inflections.rb102
-rw-r--r--activesupport/lib/active_support/core_ext/string/inquiry.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb31
-rw-r--r--activesupport/lib/active_support/core_ext/time/calculations.rb102
-rw-r--r--activesupport/lib/active_support/core_ext/time/conversions.rb22
-rw-r--r--activesupport/lib/active_support/core_ext/time/zones.rb28
-rw-r--r--activesupport/lib/active_support/deprecation/behaviors.rb12
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb6
-rw-r--r--activesupport/test/deprecation_test.rb20
-rw-r--r--guides/source/active_record_querying.textile16
-rw-r--r--guides/source/configuring.textile2
-rw-r--r--guides/source/layouts_and_rendering.textile10
-rw-r--r--railties/lib/rails/application.rb3
-rw-r--r--railties/lib/rails/application/routes_reloader.rb5
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/index.html.erb36
-rw-r--r--railties/test/application/routing_test.rb2
-rw-r--r--railties/test/isolation/abstract_unit.rb2
79 files changed, 957 insertions, 435 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 9f1c44ca66..dc152b7a6e 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,5 +1,12 @@
## Rails 4.0.0 (unreleased) ##
+* Make current object and counter (when it applies) variables accessible when
+ rendering templates with :object / :collection. *Carlos Antonio da Silva*
+
+* JSONP now uses mimetype application/javascript instead of application/json *omjokine*
+
+* Allow to lazy load `default_form_builder` by passing a `String` instead of a constant. *Piotr Sarnacki*
+
* Session arguments passed to `process` calls in functional tests are now merged into
the existing session, whereas previously they would replace the existing session.
This change may break some existing tests if they are asserting the exact contents of
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index 6e9ce450ac..4a0c1c7dd7 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -91,9 +91,14 @@ module ActionController
add :json do |json, options|
json = json.to_json(options) unless json.kind_of?(String)
- json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
- self.content_type ||= Mime::JSON
- json
+
+ if options[:callback].present?
+ self.content_type ||= Mime::JS
+ "#{options[:callback]}(#{json})"
+ else
+ self.content_type ||= Mime::JSON
+ json
+ end
end
add :js do |js, options|
diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb
index 5c40889f6b..e7af3f5b8d 100644
--- a/actionpack/lib/action_controller/record_identifier.rb
+++ b/actionpack/lib/action_controller/record_identifier.rb
@@ -75,12 +75,7 @@ module ActionController
def record_key_for_dom_id(record)
record = record.to_model if record.respond_to?(:to_model)
key = record.to_key
- key ? sanitize_dom_id(key.join('_')) : key
- end
-
- # Replaces characters that are invalid in HTML DOM ids with valid ones.
- def sanitize_dom_id(candidate_id)
- candidate_id # TODO implement conversion to valid DOM id values
+ key ? key.join('_') : key
end
end
end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 7db7d270e5..d2581296cf 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -147,17 +147,23 @@ module ActionController
extra_keys = routes.extra_keys(parameters)
non_path_parameters = get? ? query_parameters : request_parameters
parameters.each do |key, value|
- if value.is_a? Fixnum
- value = value.to_s
- elsif value.is_a? Array
- value = Result.new(value.map { |v| v.is_a?(String) ? v.dup : v })
- elsif value.is_a? String
+ if value.is_a?(Array) && (value.frozen? || value.any?(&:frozen?))
+ value = value.map{ |v| v.duplicable? ? v.dup : v }
+ elsif value.is_a?(Hash) && (value.frozen? || value.any?{ |k,v| v.frozen? })
+ value = Hash[value.map{ |k,v| [k, v.duplicable? ? v.dup : v] }]
+ elsif value.frozen? && value.duplicable?
value = value.dup
end
if extra_keys.include?(key.to_sym)
non_path_parameters[key] = value
else
+ if value.is_a?(Array)
+ value = Result.new(value.map(&:to_param))
+ else
+ value = value.to_param
+ end
+
path_parameters[key.to_s] = value
end
end
@@ -453,7 +459,7 @@ module ActionController
# Ensure that numbers and symbols passed as params are converted to
# proper params, as is the case when engaging rack.
- parameters = paramify_values(parameters)
+ parameters = paramify_values(parameters) if html_format?(parameters)
@request.recycle!
@response.recycle!
@@ -466,7 +472,7 @@ module ActionController
parameters ||= {}
controller_class_name = @controller.class.anonymous? ?
- "anonymous_controller" :
+ "anonymous" :
@controller.class.name.underscore.sub(/_controller$/, '')
@request.assign_parameters(@routes, controller_class_name, action.to_s, parameters)
@@ -546,6 +552,12 @@ module ActionController
@request.env["QUERY_STRING"] = query_string || ""
end
end
+
+ def html_format?(parameters)
+ return true unless parameters.is_a?(Hash)
+ format = Mime[parameters[:format]]
+ format.nil? || format.html?
+ end
end
# When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline
diff --git a/actionpack/lib/action_dispatch/routing/redirection.rb b/actionpack/lib/action_dispatch/routing/redirection.rb
index ae01781013..444a79c50d 100644
--- a/actionpack/lib/action_dispatch/routing/redirection.rb
+++ b/actionpack/lib/action_dispatch/routing/redirection.rb
@@ -1,4 +1,6 @@
require 'action_dispatch/http/request'
+require 'active_support/core_ext/uri'
+require 'rack/utils'
module ActionDispatch
module Routing
@@ -46,8 +48,17 @@ module ActionDispatch
:params => request.query_parameters
}.merge options
+ if !params.empty? && url_options[:path].match(/%\{\w*\}/)
+ url_options[:path] = (url_options[:path] % escape_path(params))
+ end
+
ActionDispatch::Http::URL.url_for url_options
end
+
+ private
+ def escape_path(params)
+ Hash[params.map{ |k,v| [k, URI.parser.escape(v)] }]
+ end
end
module Redirection
@@ -96,13 +107,18 @@ module ActionDispatch
path = args.shift
block = lambda { |params, request|
- (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % params)
+ (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % escape(params))
} if String === path
block = path if path.respond_to? :call
raise ArgumentError, "redirection argument not supported" unless block
Redirect.new status, block
end
+
+ private
+ def escape(params)
+ Hash[params.map{ |k,v| [k, Rack::Utils.escape(v)] }]
+ end
end
end
end
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 8e7224937d..67f2abe509 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -10,6 +10,7 @@ require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/string/output_safety'
require 'active_support/core_ext/array/extract_options'
require 'active_support/deprecation'
+require 'active_support/core_ext/string/inflections'
module ActionView
# = Action View Form Helpers
@@ -1039,9 +1040,14 @@ module ActionView
object_name = ActiveModel::Naming.param_key(object)
end
- builder = options[:builder] || ActionView::Base.default_form_builder
+ builder = options[:builder] || default_form_builder
builder.new(object_name, object, self, options)
end
+
+ def default_form_builder
+ builder = ActionView::Base.default_form_builder
+ builder.respond_to?(:constantize) ? builder.constantize : builder
+ end
end
class FormBuilder
diff --git a/actionpack/lib/action_view/helpers/tags/check_box.rb b/actionpack/lib/action_view/helpers/tags/check_box.rb
index 1a4aebb936..9d17a1dde3 100644
--- a/actionpack/lib/action_view/helpers/tags/check_box.rb
+++ b/actionpack/lib/action_view/helpers/tags/check_box.rb
@@ -41,17 +41,15 @@ module ActionView
def checked?(value)
case value
when TrueClass, FalseClass
- value
+ value == !!@checked_value
when NilClass
false
- when Integer
- value != 0
when String
value == @checked_value
when Array
value.include?(@checked_value)
else
- value.to_i != 0
+ value.to_i == @checked_value.to_i
end
end
diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb
index 34ea06c9cf..c5d5540510 100644
--- a/actionpack/lib/action_view/renderer/partial_renderer.rb
+++ b/actionpack/lib/action_view/renderer/partial_renderer.rb
@@ -158,8 +158,8 @@ module ActionView
# Name: <%= user.name %>
# </div>
#
- # If a collection is given, the layout will be rendered once for each item in the collection. Just think
- # these two snippets have the same output:
+ # If a collection is given, the layout will be rendered once for each item in
+ # the collection. Just think these two snippets have the same output:
#
# <%# app/views/users/_user.html.erb %>
# Name: <%= user.name %>
@@ -184,7 +184,7 @@ module ActionView
# <%= render :partial => "user", :layout => "li_layout", :collection => users %>
# </ul>
#
- # Given two users whose names are Alice and Bob, these snippets return:
+ # Given two users whose names are Alice and Bob, these snippets return:
#
# <ul>
# <li>
@@ -195,6 +195,10 @@ module ActionView
# </li>
# </ul>
#
+ # The current object being rendered, as well as the object_counter, will be
+ # available as local variables inside the layout template under the same names
+ # as available in the partial.
+ #
# You can also apply a layout to a block within any template:
#
# <%# app/views/users/_chief.html.erb &>
@@ -282,14 +286,7 @@ module ActionView
spacer = find_template(@options[:spacer_template]).render(@view, @locals)
end
- if layout = @options[:layout]
- layout = find_template(layout)
- end
-
result = @template ? collection_with_template : collection_without_template
-
- result.map!{|content| layout.render(@view, @locals) { content } } if layout
-
result.join(spacer).html_safe
end
@@ -298,7 +295,7 @@ module ActionView
object, as = @object, @variable
if !block && (layout = @options[:layout])
- layout = find_template(layout)
+ layout = find_template(layout, @locals.keys + [@variable])
end
object ||= locals[as]
@@ -384,17 +381,23 @@ module ActionView
segments, locals, template = [], @locals, @template
as, counter = @variable, @variable_counter
+ if layout = @options[:layout]
+ layout = find_template(layout, @locals.keys + [@variable, @variable_counter])
+ end
+
locals[counter] = -1
@collection.each do |object|
locals[counter] += 1
locals[as] = object
- segments << template.render(@view, locals)
+
+ content = template.render(@view, locals)
+ content = layout.render(@view, locals) { content } if layout
+ segments << content
end
-
+
segments
end
-
def collection_without_template
segments, locals, collection_data = [], @locals, @collection_data
diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb
index 75fed8e933..7c0a6bd67e 100644
--- a/actionpack/test/controller/render_json_test.rb
+++ b/actionpack/test/controller/render_json_test.rb
@@ -102,7 +102,7 @@ class RenderJsonTest < ActionController::TestCase
def test_render_json_with_callback
get :render_json_hello_world_with_callback
assert_equal 'alert({"hello":"world"})', @response.body
- assert_equal 'application/json', @response.content_type
+ assert_equal 'text/javascript', @response.content_type
end
def test_render_json_with_custom_content_type
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index 03b7396d5b..0d6d303b51 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -45,6 +45,10 @@ class TestCaseTest < ActionController::TestCase
render :text => request.fullpath
end
+ def test_format
+ render :text => request.format
+ end
+
def test_query_string
render :text => request.query_string
end
@@ -579,14 +583,34 @@ XML
)
end
+ def test_params_passing_with_fixnums_when_not_html_request
+ get :test_params, :format => 'json', :count => 999
+ parsed_params = eval(@response.body)
+ assert_equal(
+ {'controller' => 'test_case_test/test', 'action' => 'test_params',
+ 'format' => 'json', 'count' => 999 },
+ parsed_params
+ )
+ end
+
+ def test_params_passing_path_parameter_is_string_when_not_html_request
+ get :test_params, :format => 'json', :id => 1
+ parsed_params = eval(@response.body)
+ assert_equal(
+ {'controller' => 'test_case_test/test', 'action' => 'test_params',
+ 'format' => 'json', 'id' => '1' },
+ parsed_params
+ )
+ end
+
def test_params_passing_with_frozen_values
assert_nothing_raised do
- get :test_params, :frozen => 'icy'.freeze, :frozens => ['icy'.freeze].freeze
+ get :test_params, :frozen => 'icy'.freeze, :frozens => ['icy'.freeze].freeze, :deepfreeze => { :frozen => 'icy'.freeze }.freeze
end
parsed_params = eval(@response.body)
assert_equal(
{'controller' => 'test_case_test/test', 'action' => 'test_params',
- 'frozen' => 'icy', 'frozens' => ['icy']},
+ 'frozen' => 'icy', 'frozens' => ['icy'], 'deepfreeze' => { 'frozen' => 'icy' }},
parsed_params
)
end
@@ -687,6 +711,20 @@ XML
assert_equal "http://", @response.body
end
+ def test_request_format
+ get :test_format, :format => 'html'
+ assert_equal 'text/html', @response.body
+
+ get :test_format, :format => 'json'
+ assert_equal 'application/json', @response.body
+
+ get :test_format, :format => 'xml'
+ assert_equal 'application/xml', @response.body
+
+ get :test_format
+ assert_equal 'text/html', @response.body
+ end
+
def test_should_have_knowledge_of_client_side_cookie_state_even_if_they_are_not_set
cookies['foo'] = 'bar'
get :no_op
@@ -848,3 +886,24 @@ class NamedRoutesControllerTest < ActionController::TestCase
end
end
end
+
+class AnonymousControllerTest < ActionController::TestCase
+ def setup
+ @controller = Class.new(ActionController::Base) do
+ def index
+ render :text => params[:controller]
+ end
+ end.new
+
+ @routes = ActionDispatch::Routing::RouteSet.new.tap do |r|
+ r.draw do
+ get ':controller(/:action(/:id))'
+ end
+ end
+ end
+
+ def test_controller_name
+ get :index
+ assert_equal 'anonymous', @response.body
+ end
+end \ No newline at end of file
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 463dd6cb85..4b8d308043 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -63,8 +63,13 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
get 'secure', :to => redirect("/secure/login")
get 'mobile', :to => redirect(:subdomain => 'mobile')
+ get 'documentation', :to => redirect(:domain => 'example-documentation.com', :path => '')
+ get 'new_documentation', :to => redirect(:path => '/documentation/new')
get 'super_new_documentation', :to => redirect(:host => 'super-docs.com')
+ get 'stores/:name', :to => redirect(:subdomain => 'stores', :path => '/%{name}')
+ get 'stores/:name(*rest)', :to => redirect(:subdomain => 'stores', :path => '/%{name}%{rest}')
+
get 'youtube_favorites/:youtube_id/:name', :to => redirect(YoutubeFavoritesRedirector)
constraints(lambda { |req| true }) do
@@ -693,11 +698,31 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
verify_redirect 'http://mobile.example.com/mobile'
end
+ def test_redirect_hash_with_domain_and_path
+ get '/documentation'
+ verify_redirect 'http://www.example-documentation.com'
+ end
+
+ def test_redirect_hash_with_path
+ get '/new_documentation'
+ verify_redirect 'http://www.example.com/documentation/new'
+ end
+
def test_redirect_hash_with_host
get '/super_new_documentation?section=top'
verify_redirect 'http://super-docs.com/super_new_documentation?section=top'
end
+ def test_redirect_hash_path_substitution
+ get '/stores/iernest'
+ verify_redirect 'http://stores.example.com/iernest'
+ end
+
+ def test_redirect_hash_path_substitution_with_catch_all
+ get '/stores/iernest/products'
+ verify_redirect 'http://stores.example.com/iernest/products'
+ end
+
def test_redirect_class
get '/youtube_favorites/oHg5SJYRHA0/rick-rolld'
verify_redirect 'http://www.youtube.com/watch?v=oHg5SJYRHA0'
@@ -2452,3 +2477,38 @@ class TestTildeAndMinusPaths < ActionDispatch::IntegrationTest
end
end
+
+class TestRedirectInterpolation < ActionDispatch::IntegrationTest
+ Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
+ app.draw do
+ ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
+
+ get "/foo/:id" => redirect("/foo/bar/%{id}")
+ get "/bar/:id" => redirect(:path => "/foo/bar/%{id}")
+ get "/foo/bar/:id" => ok
+ end
+ end
+
+ def app; Routes end
+
+ test "redirect escapes interpolated parameters with redirect proc" do
+ get "/foo/1%3E"
+ verify_redirect "http://www.example.com/foo/bar/1%3E"
+ end
+
+ test "redirect escapes interpolated parameters with option proc" do
+ get "/bar/1%3E"
+ verify_redirect "http://www.example.com/foo/bar/1%3E"
+ end
+
+private
+ def verify_redirect(url, status=301)
+ assert_equal status, @response.status
+ assert_equal url, @response.headers['Location']
+ assert_equal expected_redirect_body(url), @response.body
+ end
+
+ def expected_redirect_body(url)
+ %(<html><body>You are being <a href="#{ERB::Util.h(url)}">redirected</a>.</body></html>)
+ end
+end
diff --git a/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb
new file mode 100644
index 0000000000..bdd53014cd
--- /dev/null
+++ b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb
@@ -0,0 +1 @@
+<b class="<%= customer.name.downcase %>"><%= yield %></b> \ No newline at end of file
diff --git a/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb
new file mode 100644
index 0000000000..44d6121297
--- /dev/null
+++ b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb
@@ -0,0 +1 @@
+<b data-counter="<%= customer_counter %>"><%= yield %></b> \ No newline at end of file
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index a714264909..beb3ea752a 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -350,36 +350,52 @@ class FormHelperTest < ActionView::TestCase
text_field("user", "email", :type => "email")
end
- def test_check_box
+ def test_check_box_is_html_safe
assert check_box("post", "secret").html_safe?
+ end
+
+ def test_check_box_checked_if_object_value_is_same_that_check_value
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret")
)
+ end
+
+ def test_check_box_not_checked_if_object_value_is_same_that_unchecked_value
@post.secret = 0
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret")
)
+ end
+
+ def test_check_box_checked_if_option_checked_is_present
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret" ,{"checked"=>"checked"})
)
+ end
+
+ def test_check_box_checked_if_object_value_is_true
@post.secret = true
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret")
)
+
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret?")
)
+ end
+ def test_check_box_checked_if_object_value_includes_checked_value
@post.secret = ['0']
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret")
)
+
@post.secret = ['1']
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />',
@@ -392,12 +408,92 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal('<input id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret", :include_hidden => false))
end
- def test_check_box_with_explicit_checked_and_unchecked_values
+ def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_string
@post.secret = "on"
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="off" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="on" />',
check_box("post", "secret", {}, "on", "off")
)
+
+ @post.secret = "off"
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="off" /><input id="post_secret" name="post[secret]" type="checkbox" value="on" />',
+ check_box("post", "secret", {}, "on", "off")
+ )
+ end
+
+ def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_boolean
+ @post.secret = false
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="true" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="false" />',
+ check_box("post", "secret", {}, false, true)
+ )
+
+ @post.secret = true
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="true" /><input id="post_secret" name="post[secret]" type="checkbox" value="false" />',
+ check_box("post", "secret", {}, false, true)
+ )
+ end
+
+ def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_integer
+ @post.secret = 0
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = 1
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = 2
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+ end
+
+ def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_float
+ @post.secret = 0.0
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = 1.1
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = 2.2
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+ end
+
+ def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_big_decimal
+ @post.secret = BigDecimal.new(0)
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = BigDecimal.new(1)
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = BigDecimal.new(2.2, 1)
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
end
def test_check_box_with_nil_unchecked_value
@@ -2169,6 +2265,23 @@ class FormHelperTest < ActionView::TestCase
ActionView::Base.default_form_builder = old_default_form_builder
end
+ def test_lazy_loading_default_form_builder
+ old_default_form_builder, ActionView::Base.default_form_builder =
+ ActionView::Base.default_form_builder, "FormHelperTest::LabelledFormBuilder"
+
+ form_for(@post) do |f|
+ concat f.text_field(:title)
+ end
+
+ expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do
+ "<label for='title'>Title:</label> <input name='post[title]' type='text' id='post_title' value='Hello World' /><br/>"
+ end
+
+ assert_dom_equal expected, output_buffer
+ ensure
+ ActionView::Base.default_form_builder = old_default_form_builder
+ end
+
def test_fields_for_with_labelled_builder
output_buffer = fields_for(:post, @post, :builder => LabelledFormBuilder) do |f|
concat f.text_field(:title)
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index 43b176df3c..cdaca56ef2 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -233,11 +233,26 @@ module RenderTestCases
def test_render_partial_with_nil_values_in_collection
assert_equal "Hello: davidHello: Anonymous", @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), nil ])
end
-
+
def test_render_partial_with_layout_using_collection_and_template
assert_equal "<b>Hello: Amazon</b><b>Hello: Yahoo</b>", @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ])
end
+ def test_render_partial_with_layout_using_collection_and_template_makes_current_item_available_in_layout
+ assert_equal '<b class="amazon">Hello: Amazon</b><b class="yahoo">Hello: Yahoo</b>',
+ @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ])
+ end
+
+ def test_render_partial_with_layout_using_collection_and_template_makes_current_item_counter_available_in_layout
+ assert_equal '<b data-counter="0">Hello: Amazon</b><b data-counter="1">Hello: Yahoo</b>',
+ @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object_counter', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ])
+ end
+
+ def test_render_partial_with_layout_using_object_and_template_makes_object_available_in_layout
+ assert_equal '<b class="amazon">Hello: Amazon</b>',
+ @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object', :object => Customer.new("Amazon"))
+ end
+
def test_render_partial_with_empty_array_should_return_nil
assert_nil @view.render(:partial => [])
end
@@ -310,7 +325,7 @@ module RenderTestCases
ActionView::Template.register_template_handler :foo, CustomHandler
assert_equal 'source: "Hello, <%= name %>!"', @view.render(:inline => "Hello, <%= name %>!", :locals => { :name => "Josh" }, :type => :foo)
end
-
+
def test_render_knows_about_types_registered_when_extensions_are_checked_earlier_in_initialization
ActionView::Template::Handlers.extensions
ActionView::Template.register_template_handler :foo, CustomHandler
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index c6d8eae46c..789cff0673 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,5 +1,7 @@
## Rails 4.0.0 (unreleased) ##
+* `ConfirmationValidator` error messages will attach to `:#{attribute}_confirmation` instead of `attribute` *Brian Cardarella*
+
* Added ActiveModel::Model, a mixin to make Ruby objects work with AP out of box *Guillermo Iguaran*
* `AM::Errors#to_json`: support `:full_messages` parameter *Bogdan Gusiev*
diff --git a/activemodel/lib/active_model/locale/en.yml b/activemodel/lib/active_model/locale/en.yml
index ba49c6beaa..d17848c861 100644
--- a/activemodel/lib/active_model/locale/en.yml
+++ b/activemodel/lib/active_model/locale/en.yml
@@ -9,7 +9,7 @@ en:
inclusion: "is not included in the list"
exclusion: "is reserved"
invalid: "is invalid"
- confirmation: "doesn't match confirmation"
+ confirmation: "doesn't match %{attribute}"
accepted: "must be accepted"
empty: "can't be empty"
blank: "can't be blank"
diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb
index e303425a7c..f3781f7a68 100644
--- a/activemodel/lib/active_model/observing.rb
+++ b/activemodel/lib/active_model/observing.rb
@@ -90,14 +90,15 @@ module ActiveModel
def instantiate_observer(observer) #:nodoc:
# string/symbol
if observer.respond_to?(:to_sym)
- observer.to_s.camelize.constantize.instance
- elsif observer.respond_to?(:instance)
+ observer = observer.to_s.camelize.constantize
+ end
+ if observer.respond_to?(:instance)
observer.instance
else
raise ArgumentError,
- "#{observer} must be a lowercase, underscored class name (or an " +
- "instance of the class itself) responding to the instance " +
- "method. Example: Person.observers = :big_brother # calls " +
+ "#{observer} must be a lowercase, underscored class name (or " +
+ "the class itself) responding to the method :instance. " +
+ "Example: Person.observers = :big_brother # calls " +
"BigBrother.instance"
end
end
diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb
index e8526303e2..69ab74734d 100644
--- a/activemodel/lib/active_model/validations/confirmation.rb
+++ b/activemodel/lib/active_model/validations/confirmation.rb
@@ -5,7 +5,8 @@ module ActiveModel
class ConfirmationValidator < EachValidator
def validate_each(record, attribute, value)
if (confirmed = record.send("#{attribute}_confirmation")) && (value != confirmed)
- record.errors.add(attribute, :confirmation, options)
+ human_attribute_name = record.class.human_attribute_name(attribute)
+ record.errors.add(:"#{attribute}_confirmation", :confirmation, options.merge(:attribute => human_attribute_name))
end
end
diff --git a/activemodel/test/cases/observing_test.rb b/activemodel/test/cases/observing_test.rb
index 096a309335..f8bfcf839d 100644
--- a/activemodel/test/cases/observing_test.rb
+++ b/activemodel/test/cases/observing_test.rb
@@ -70,6 +70,21 @@ class ObservingTest < ActiveModel::TestCase
ObservedModel.instantiate_observers
end
+ test "raises an appropriate error when a developer accidentally adds the wrong class (i.e. Widget instead of WidgetObserver)" do
+ assert_raise ArgumentError do
+ ObservedModel.observers = ['string']
+ ObservedModel.instantiate_observers
+ end
+ assert_raise ArgumentError do
+ ObservedModel.observers = [:string]
+ ObservedModel.instantiate_observers
+ end
+ assert_raise ArgumentError do
+ ObservedModel.observers = [String]
+ ObservedModel.instantiate_observers
+ end
+ end
+
test "passes observers to subclasses" do
FooObserver.instance
bar = Class.new(Foo)
diff --git a/activemodel/test/cases/validations/confirmation_validation_test.rb b/activemodel/test/cases/validations/confirmation_validation_test.rb
index d0418170fa..f7556a249f 100644
--- a/activemodel/test/cases/validations/confirmation_validation_test.rb
+++ b/activemodel/test/cases/validations/confirmation_validation_test.rb
@@ -44,7 +44,7 @@ class ConfirmationValidationTest < ActiveModel::TestCase
p.karma_confirmation = "None"
assert p.invalid?
- assert_equal ["doesn't match confirmation"], p.errors[:karma]
+ assert_equal ["doesn't match Karma"], p.errors[:karma_confirmation]
p.karma = "None"
assert p.valid?
@@ -52,4 +52,23 @@ class ConfirmationValidationTest < ActiveModel::TestCase
Person.reset_callbacks(:validate)
end
+ def test_title_confirmation_with_i18n_attribute
+ @old_load_path, @old_backend = I18n.load_path.dup, I18n.backend
+ I18n.load_path.clear
+ I18n.backend = I18n::Backend::Simple.new
+ I18n.backend.store_translations('en', {
+ :errors => {:messages => {:confirmation => "doesn't match %{attribute}"}},
+ :activemodel => {:attributes => {:topic => {:title => 'Test Title'}}}
+ })
+
+ Topic.validates_confirmation_of(:title)
+
+ t = Topic.new("title" => "We should be confirmed","title_confirmation" => "")
+ assert t.invalid?
+ assert_equal ["doesn't match Test Title"], t.errors[:title_confirmation]
+
+ I18n.load_path.replace @old_load_path
+ I18n.backend = @old_backend
+ end
+
end
diff --git a/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb b/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb
index 0679e67f84..df0fcd243a 100644
--- a/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb
+++ b/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb
@@ -37,7 +37,7 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase
# validates_confirmation_of: generate_message(attr_name, :confirmation, :message => custom_message)
def test_generate_message_confirmation_with_default_message
- assert_equal "doesn't match confirmation", @person.errors.generate_message(:title, :confirmation)
+ assert_equal "doesn't match Title", @person.errors.generate_message(:title, :confirmation)
end
def test_generate_message_confirmation_with_custom_message
diff --git a/activemodel/test/cases/validations/i18n_validation_test.rb b/activemodel/test/cases/validations/i18n_validation_test.rb
index e9f0e430fe..6b6aad3bd1 100644
--- a/activemodel/test/cases/validations/i18n_validation_test.rb
+++ b/activemodel/test/cases/validations/i18n_validation_test.rb
@@ -81,7 +81,7 @@ class I18nValidationTest < ActiveModel::TestCase
test "validates_confirmation_of on generated message #{name}" do
Person.validates_confirmation_of :title, validation_options
@person.title_confirmation = 'foo'
- @person.errors.expects(:generate_message).with(:title, :confirmation, generate_message_options)
+ @person.errors.expects(:generate_message).with(:title_confirmation, :confirmation, generate_message_options.merge(:attribute => 'Title'))
@person.valid?
end
end
@@ -217,24 +217,29 @@ class I18nValidationTest < ActiveModel::TestCase
# To make things DRY this macro is defined to define 3 tests for every validation case.
def self.set_expectations_for_validation(validation, error_type, &block_that_sets_validation)
+ if error_type == :confirmation
+ attribute = :title_confirmation
+ else
+ attribute = :title
+ end
# test "validates_confirmation_of finds custom model key translation when blank"
test "#{validation} finds custom model key translation when #{error_type}" do
- I18n.backend.store_translations 'en', :activemodel => {:errors => {:models => {:person => {:attributes => {:title => {error_type => 'custom message'}}}}}}
+ I18n.backend.store_translations 'en', :activemodel => {:errors => {:models => {:person => {:attributes => {attribute => {error_type => 'custom message'}}}}}}
I18n.backend.store_translations 'en', :errors => {:messages => {error_type => 'global message'}}
yield(@person, {})
@person.valid?
- assert_equal ['custom message'], @person.errors[:title]
+ assert_equal ['custom message'], @person.errors[attribute]
end
# test "validates_confirmation_of finds custom model key translation with interpolation when blank"
test "#{validation} finds custom model key translation with interpolation when #{error_type}" do
- I18n.backend.store_translations 'en', :activemodel => {:errors => {:models => {:person => {:attributes => {:title => {error_type => 'custom message with %{extra}'}}}}}}
+ I18n.backend.store_translations 'en', :activemodel => {:errors => {:models => {:person => {:attributes => {attribute => {error_type => 'custom message with %{extra}'}}}}}}
I18n.backend.store_translations 'en', :errors => {:messages => {error_type => 'global message'}}
yield(@person, {:extra => "extra information"})
@person.valid?
- assert_equal ['custom message with extra information'], @person.errors[:title]
+ assert_equal ['custom message with extra information'], @person.errors[attribute]
end
# test "validates_confirmation_of finds global default key translation when blank"
@@ -243,7 +248,7 @@ class I18nValidationTest < ActiveModel::TestCase
yield(@person, {})
@person.valid?
- assert_equal ['global message'], @person.errors[:title]
+ assert_equal ['global message'], @person.errors[attribute]
end
end
diff --git a/activemodel/test/cases/validations/validates_test.rb b/activemodel/test/cases/validations/validates_test.rb
index 575154ffbd..90bc018ae1 100644
--- a/activemodel/test/cases/validations/validates_test.rb
+++ b/activemodel/test/cases/validations/validates_test.rb
@@ -154,6 +154,6 @@ class ValidatesTest < ActiveModel::TestCase
topic.title = "What's happening"
topic.title_confirmation = "Not this"
assert !topic.valid?
- assert_equal ['Y U NO CONFIRM'], topic.errors[:title]
+ assert_equal ['Y U NO CONFIRM'], topic.errors[:title_confirmation]
end
end
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 12e232a97f..4a987c2343 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -268,7 +268,13 @@ module ActiveRecord
clear_aggregation_cache
clear_association_cache
- fresh_object = self.class.unscoped { self.class.find(id, options) }
+ fresh_object =
+ if options && options[:lock]
+ self.class.unscoped { self.class.lock.find(id) }
+ else
+ self.class.unscoped { self.class.find(id) }
+ end
+
@attributes.update(fresh_object.instance_variable_get('@attributes'))
@columns_hash = fresh_object.instance_variable_get('@columns_hash')
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index b6c3e91db8..92713cae85 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,5 +1,7 @@
## Rails 4.0.0 (unreleased) ##
+* Add `ActiveSupport::Deprecations.behavior = :silence` to completely ignore *twinturbo*
+
* Make Module#delegate stop using `send` - can no longer delegate to private methods. *dasch*
* AS::Callbacks: deprecate `:rescuable` option. *Bogdan Gusiev*
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 2a569d9a9b..cbeba3139a 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -76,7 +76,8 @@ module ActiveSupport
#
def run_callbacks(kind, key = nil, &block)
#TODO: deprecate key argument
- self.class.__run_callbacks(kind, self, &block)
+ runner_name = self.class.__define_callbacks(kind, self)
+ send(runner_name, &block)
end
private
@@ -323,18 +324,17 @@ module ActiveSupport
method << callbacks
method << "halted ? false : (block_given? ? value : true)"
- method.flatten.compact.join("\n")
+ method.join("\n")
end
end
module ClassMethods
- # This method runs callback chain for the given kind.
- # If this called first time it creates a new callback method for the kind.
+ # This method defines callback chain method for the given kind
+ # if it was not yet defined.
# This generated method plays caching role.
- #
- def __run_callbacks(kind, object, &blk) #:nodoc:
+ def __define_callbacks(kind, object) #:nodoc:
name = __callback_runner_name(kind)
unless object.respond_to?(name, true)
str = object.send("_#{kind}_callbacks").compile
@@ -343,7 +343,7 @@ module ActiveSupport
protected :#{name}
RUBY_EVAL
end
- object.send(name, &blk)
+ name
end
def __reset_runner(symbol)
diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb
index 6162f7af27..44d90ef732 100644
--- a/activesupport/lib/active_support/core_ext/array/access.rb
+++ b/activesupport/lib/active_support/core_ext/array/access.rb
@@ -16,7 +16,7 @@ class Array
# %w( a b c d ).to(10) # => %w( a b c d )
# %w().to(0) # => %w()
def to(position)
- self.first position + 1
+ first position + 1
end
# Equal to <tt>self[1]</tt>.
diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb
index f3d06ecb2f..24aa28b895 100644
--- a/activesupport/lib/active_support/core_ext/array/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/array/conversions.rb
@@ -9,28 +9,32 @@ class Array
# * <tt>:two_words_connector</tt> - The sign or word used to join the elements in arrays with two elements (default: " and ")
# * <tt>:last_word_connector</tt> - The sign or word used to join the last element in arrays with three or more elements (default: ", and ")
def to_sentence(options = {})
+ options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
+
+ default_connectors = {
+ :words_connector => ', ',
+ :two_words_connector => ' and ',
+ :last_word_connector => ', and '
+ }
if defined?(I18n)
- default_words_connector = I18n.translate(:'support.array.words_connector', :locale => options[:locale])
- default_two_words_connector = I18n.translate(:'support.array.two_words_connector', :locale => options[:locale])
- default_last_word_connector = I18n.translate(:'support.array.last_word_connector', :locale => options[:locale])
- else
- default_words_connector = ", "
- default_two_words_connector = " and "
- default_last_word_connector = ", and "
+ namespace = 'support.array.'
+ default_connectors.each_key do |name|
+ i18n_key = (namespace + name.to_s).to_sym
+ default_connectors[name] = I18n.translate i18n_key, :locale => options[:locale]
+ end
end
- options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
- options.reverse_merge! :words_connector => default_words_connector, :two_words_connector => default_two_words_connector, :last_word_connector => default_last_word_connector
+ options.reverse_merge! default_connectors
case length
- when 0
- ""
- when 1
- self[0].to_s.dup
- when 2
- "#{self[0]}#{options[:two_words_connector]}#{self[1]}"
- else
- "#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
+ when 0
+ ''
+ when 1
+ self[0].to_s.dup
+ when 2
+ "#{self[0]}#{options[:two_words_connector]}#{self[1]}"
+ else
+ "#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
end
end
@@ -45,14 +49,14 @@ class Array
# Blog.all.to_formatted_s(:db) # => "1,2,3"
def to_formatted_s(format = :default)
case format
- when :db
- if respond_to?(:empty?) && self.empty?
- "null"
- else
- collect { |element| element.id }.join(",")
- end
+ when :db
+ if empty?
+ 'null'
else
- to_default_s
+ collect { |element| element.id }.join(',')
+ end
+ else
+ to_default_s
end
end
alias_method :to_default_s, :to_s
@@ -86,20 +90,20 @@ class Array
# </project>
# </projects>
#
- # Otherwise the root element is "records":
+ # Otherwise the root element is "objects":
#
# [{:foo => 1, :bar => 2}, {:baz => 3}].to_xml
#
# <?xml version="1.0" encoding="UTF-8"?>
- # <records type="array">
- # <record>
+ # <objects type="array">
+ # <object>
# <bar type="integer">2</bar>
# <foo type="integer">1</foo>
- # </record>
- # <record>
+ # </object>
+ # <object>
# <baz type="integer">3</baz>
- # </record>
- # </records>
+ # </object>
+ # </objects>
#
# If the collection is empty the root element is "nil-classes" by default:
#
@@ -139,26 +143,28 @@ class Array
options = options.dup
options[:indent] ||= 2
options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
- options[:root] ||= if first.class.to_s != "Hash" && all? { |e| e.is_a?(first.class) }
- underscored = ActiveSupport::Inflector.underscore(first.class.name)
- ActiveSupport::Inflector.pluralize(underscored).tr('/', '_')
- else
- "objects"
- end
+ options[:root] ||= \
+ if first.class != Hash && all? { |e| e.is_a?(first.class) }
+ underscored = ActiveSupport::Inflector.underscore(first.class.name)
+ ActiveSupport::Inflector.pluralize(underscored).tr('/', '_')
+ else
+ 'objects'
+ end
builder = options[:builder]
builder.instruct! unless options.delete(:skip_instruct)
root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
children = options.delete(:children) || root.singularize
+ attributes = options[:skip_types] ? {} : {:type => 'array'}
- attributes = options[:skip_types] ? {} : {:type => "array"}
- return builder.tag!(root, attributes) if empty?
-
- builder.__send__(:method_missing, root, attributes) do
- each { |value| ActiveSupport::XmlMini.to_tag(children, value, options) }
- yield builder if block_given?
+ if empty?
+ builder.tag!(root, attributes)
+ else
+ builder.__send__(:method_missing, root, attributes) do
+ each { |value| ActiveSupport::XmlMini.to_tag(children, value, options) }
+ yield builder if block_given?
+ end
end
end
-
end
diff --git a/activesupport/lib/active_support/core_ext/array/grouping.rb b/activesupport/lib/active_support/core_ext/array/grouping.rb
index 2b3f639cb1..ac1ae53db0 100644
--- a/activesupport/lib/active_support/core_ext/array/grouping.rb
+++ b/activesupport/lib/active_support/core_ext/array/grouping.rb
@@ -82,11 +82,9 @@ class Array
#
# [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
# (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
- def split(value = nil)
- using_block = block_given?
-
+ def split(value = nil, &block)
inject([[]]) do |results, element|
- if (using_block && yield(element)) || (value == element)
+ if block && block.call(element) || value == element
results << []
else
results.last << element
diff --git a/activesupport/lib/active_support/core_ext/array/uniq_by.rb b/activesupport/lib/active_support/core_ext/array/uniq_by.rb
index ac3dedc0e3..3bedfa9a61 100644
--- a/activesupport/lib/active_support/core_ext/array/uniq_by.rb
+++ b/activesupport/lib/active_support/core_ext/array/uniq_by.rb
@@ -6,8 +6,7 @@ class Array
# [1, 2, 3, 4].uniq_by { |i| i.odd? } # => [1, 2]
#
def uniq_by(&block)
- ActiveSupport::Deprecation.warn "uniq_by " \
- "is deprecated. Use Array#uniq instead", caller
+ ActiveSupport::Deprecation.warn 'uniq_by is deprecated. Use Array#uniq instead', caller
uniq(&block)
end
@@ -15,8 +14,7 @@ class Array
#
# Same as +uniq_by+, but modifies +self+.
def uniq_by!(&block)
- ActiveSupport::Deprecation.warn "uniq_by! " \
- "is deprecated. Use Array#uniq! instead", caller
+ ActiveSupport::Deprecation.warn 'uniq_by! is deprecated. Use Array#uniq! instead', caller
uniq!(&block)
end
end
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index 305ed4964b..c64685a694 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -109,7 +109,7 @@ class Class
end
private
- def singleton_class?
- ancestors.first != self
- end
+ def singleton_class?
+ ancestors.first != self
+ end
end
diff --git a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
index 95eb94fdf6..5cb528cfe9 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
@@ -29,7 +29,7 @@ class Class
def cattr_reader(*syms)
options = syms.extract_options!
syms.each do |sym|
- raise NameError.new("invalid attribute name") unless sym =~ /^[_A-Za-z]\w*$/
+ raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
unless defined? @@#{sym}
@@#{sym} = nil
@@ -53,7 +53,7 @@ class Class
def cattr_writer(*syms)
options = syms.extract_options!
syms.each do |sym|
- raise NameError.new("invalid attribute name") unless sym =~ /^[_A-Za-z]\w*$/
+ raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
unless defined? @@#{sym}
@@#{sym} = nil
@@ -71,7 +71,7 @@ class Class
end
EOS
end
- self.send("#{sym}=", yield) if block_given?
+ send("#{sym}=", yield) if block_given?
end
end
diff --git a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
index 0634f20e3c..ff870f5fd1 100644
--- a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
+++ b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
@@ -20,23 +20,21 @@ class Class
define_method("#{name}?") { !!send("#{name}") } if options[:instance_reader] != false
end
-private
-
- # Take the object being set and store it in a method. This gives us automatic
- # inheritance behavior, without having to store the object in an instance
- # variable and look up the superclass chain manually.
- def _stash_object_in_method(object, method, instance_reader = true)
- singleton_class.remove_possible_method(method)
- singleton_class.send(:define_method, method) { object }
- remove_possible_method(method)
- define_method(method) { object } if instance_reader
- end
-
- def _superclass_delegating_accessor(name, options = {})
- singleton_class.send(:define_method, "#{name}=") do |value|
- _stash_object_in_method(value, name, options[:instance_reader] != false)
+ private
+ # Take the object being set and store it in a method. This gives us automatic
+ # inheritance behavior, without having to store the object in an instance
+ # variable and look up the superclass chain manually.
+ def _stash_object_in_method(object, method, instance_reader = true)
+ singleton_class.remove_possible_method(method)
+ singleton_class.send(:define_method, method) { object }
+ remove_possible_method(method)
+ define_method(method) { object } if instance_reader
end
- send("#{name}=", nil)
- end
+ def _superclass_delegating_accessor(name, options = {})
+ singleton_class.send(:define_method, "#{name}=") do |value|
+ _stash_object_in_method(value, name, options[:instance_reader] != false)
+ end
+ send("#{name}=", nil)
+ end
end
diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb
index 6d4270f8b0..323126fcfa 100644
--- a/activesupport/lib/active_support/core_ext/date/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -5,7 +5,15 @@ require 'active_support/core_ext/date/zones'
require 'active_support/core_ext/time/zones'
class Date
- DAYS_INTO_WEEK = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6 }
+ DAYS_INTO_WEEK = {
+ :monday => 0,
+ :tuesday => 1,
+ :wednesday => 2,
+ :thursday => 3,
+ :friday => 4,
+ :saturday => 5,
+ :sunday => 6
+ }
class << self
# Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
@@ -31,7 +39,7 @@ class Date
# Returns true if the Date object's date is today.
def today?
- self.to_date == ::Date.current # we need the to_date because of DateTime
+ to_date == ::Date.current # we need the to_date because of DateTime
end
# Returns true if the Date object's date lies in the future.
@@ -105,9 +113,9 @@ class Date
# Date.new(2007, 5, 12).change(:year => 2005, :month => 1) # => Date.new(2005, 1, 12)
def change(options)
::Date.new(
- options[:year] || self.year,
- options[:month] || self.month,
- options[:day] || self.day
+ options.fetch(:year, year),
+ options.fetch(:month, month),
+ options.fetch(:day, day)
)
end
@@ -166,7 +174,7 @@ class Date
def end_of_week(start_day = :monday)
days_to_end = 6 - days_to_week_start(start_day)
result = self + days_to_end.days
- self.acts_like?(:time) ? result.end_of_day : result
+ acts_like?(:time) ? result.end_of_day : result
end
alias :at_end_of_week :end_of_week
@@ -180,7 +188,7 @@ class Date
# week. Default is +:monday+. +DateTime+ objects have their time set to 0:00.
def prev_week(day = :monday)
result = (self - 7).beginning_of_week + DAYS_INTO_WEEK[day]
- self.acts_like?(:time) ? result.change(:hour => 0) : result
+ acts_like?(:time) ? result.change(:hour => 0) : result
end
alias :last_week :prev_week
@@ -193,43 +201,57 @@ class Date
# Returns a new Date/DateTime representing the start of the given day in next week (default is :monday).
def next_week(day = :monday)
result = (self + 7).beginning_of_week + DAYS_INTO_WEEK[day]
- self.acts_like?(:time) ? result.change(:hour => 0) : result
+ acts_like?(:time) ? result.change(:hour => 0) : result
end
# Returns a new ; DateTime objects will have time set to 0:00DateTime representing the start of the month (1st of the month; DateTime objects will have time set to 0:00)
def beginning_of_month
- self.acts_like?(:time) ? change(:day => 1, :hour => 0) : change(:day => 1)
+ acts_like?(:time) ? change(:day => 1, :hour => 0) : change(:day => 1)
end
alias :at_beginning_of_month :beginning_of_month
# Returns a new Date/DateTime representing the end of the month (last day of the month; DateTime objects will have time set to 0:00)
def end_of_month
- last_day = ::Time.days_in_month( self.month, self.year )
- self.acts_like?(:time) ? change(:day => last_day, :hour => 23, :min => 59, :sec => 59) : change(:day => last_day)
+ last_day = ::Time.days_in_month(month, year)
+ if acts_like?(:time)
+ change(:day => last_day, :hour => 23, :min => 59, :sec => 59)
+ else
+ change(:day => last_day)
+ end
end
alias :at_end_of_month :end_of_month
# Returns a new Date/DateTime representing the start of the quarter (1st of january, april, july, october; DateTime objects will have time set to 0:00)
def beginning_of_quarter
- beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month })
+ first_quarter_month = [10, 7, 4, 1].detect { |m| m <= month }
+ beginning_of_month.change(:month => first_quarter_month)
end
alias :at_beginning_of_quarter :beginning_of_quarter
# Returns a new Date/DateTime representing the end of the quarter (last day of march, june, september, december; DateTime objects will have time set to 23:59:59)
def end_of_quarter
- beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= self.month }).end_of_month
+ last_quarter_month = [3, 6, 9, 12].detect { |m| m >= month }
+ beginning_of_month.change(:month => last_quarter_month).end_of_month
end
alias :at_end_of_quarter :end_of_quarter
# Returns a new Date/DateTime representing the start of the year (1st of january; DateTime objects will have time set to 0:00)
def beginning_of_year
- self.acts_like?(:time) ? change(:month => 1, :day => 1, :hour => 0) : change(:month => 1, :day => 1)
+ if acts_like?(:time)
+ change(:month => 1, :day => 1, :hour => 0)
+ else
+ change(:month => 1, :day => 1)
+ end
end
alias :at_beginning_of_year :beginning_of_year
# Returns a new Time representing the end of the year (31st of december; DateTime objects will have time set to 23:59:59)
def end_of_year
- self.acts_like?(:time) ? change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59) : change(:month => 12, :day => 31)
+ if acts_like?(:time)
+ change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59)
+ else
+ change(:month => 12, :day => 31)
+ end
end
alias :at_end_of_year :end_of_year
diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb
index 3262c254f7..97e3c71992 100644
--- a/activesupport/lib/active_support/core_ext/date/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date/conversions.rb
@@ -5,12 +5,15 @@ require 'active_support/core_ext/module/remove_method'
class Date
DATE_FORMATS = {
- :short => "%e %b",
- :long => "%B %e, %Y",
- :db => "%Y-%m-%d",
- :number => "%Y%m%d",
- :long_ordinal => lambda { |date| date.strftime("%B #{ActiveSupport::Inflector.ordinalize(date.day)}, %Y") }, # => "April 25th, 2007"
- :rfc822 => "%e %b %Y"
+ :short => '%e %b',
+ :long => '%B %e, %Y',
+ :db => '%Y-%m-%d',
+ :number => '%Y%m%d',
+ :long_ordinal => lambda { |date|
+ day_format = ActiveSupport::Inflector.ordinalize(date.day)
+ date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
+ },
+ :rfc822 => '%e %b %Y'
}
# Ruby 1.9 has Date#to_time which converts to localtime only.
@@ -40,7 +43,7 @@ class Date
# or Proc instance that takes a date argument as the value.
#
# # config/initializers/time_formats.rb
- # Date::DATE_FORMATS[:month_and_year] = "%B %Y"
+ # Date::DATE_FORMATS[:month_and_year] = '%B %Y'
# Date::DATE_FORMATS[:short_ordinal] = lambda { |date| date.strftime("%B #{date.day.ordinalize}") }
def to_formatted_s(format = :default)
if formatter = DATE_FORMATS[format]
@@ -58,7 +61,7 @@ class Date
# Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
def readable_inspect
- strftime("%a, %d %b %Y")
+ strftime('%a, %d %b %Y')
end
alias_method :default_inspect, :inspect
alias_method :inspect, :readable_inspect
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 6f730e4b6f..0e5aa5af10 100644
--- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
@@ -4,8 +4,8 @@ class DateTime
class << self
# *DEPRECATED*: Use +DateTime.civil_from_format+ directly.
def local_offset
- ActiveSupport::Deprecation.warn 'DateTime.local_offset is deprecated. ' \
- 'Use DateTime.civil_from_format directly.', caller
+ ActiveSupport::Deprecation.warn 'DateTime.local_offset is deprecated. Use DateTime.civil_from_format directly.', caller
+
::Time.local(2012).utc_offset.to_r / 86400
end
@@ -35,14 +35,14 @@ class DateTime
# minute is passed, then sec is set to 0.
def change(options)
::DateTime.civil(
- options[:year] || year,
- options[:month] || month,
- options[:day] || day,
- options[:hour] || hour,
- options[:min] || (options[:hour] ? 0 : min),
- options[:sec] || ((options[:hour] || options[:min]) ? 0 : sec),
- options[:offset] || offset,
- options[:start] || start
+ options.fetch(:year, year),
+ options.fetch(:month, month),
+ options.fetch(:day, day),
+ options.fetch(:hour, hour),
+ options.fetch(:min, options[:hour] ? 0 : min),
+ options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec),
+ options.fetch(:offset, offset),
+ options.fetch(:start, start)
)
end
@@ -53,8 +53,16 @@ class DateTime
def advance(options)
d = to_date.advance(options)
datetime_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
- seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
- seconds_to_advance == 0 ? datetime_advanced_by_date : datetime_advanced_by_date.since(seconds_to_advance)
+ seconds_to_advance = \
+ options.fetch(:seconds, 0) +
+ options.fetch(:minutes, 0) * 60 +
+ options.fetch(:hours, 0) * 3600
+
+ if seconds_to_advance.zero?
+ datetime_advanced_by_date
+ else
+ datetime_advanced_by_date.since seconds_to_advance
+ end
end
# Returns a new DateTime representing the time a number of seconds ago
@@ -108,4 +116,5 @@ class DateTime
def <=>(other)
super other.to_datetime
end
+
end
diff --git a/activesupport/lib/active_support/core_ext/date_time/conversions.rb b/activesupport/lib/active_support/core_ext/date_time/conversions.rb
index dc55e9c33c..6338dc6397 100644
--- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb
@@ -30,7 +30,7 @@ class DateTime
# datetime argument as the value.
#
# # config/initializers/time_formats.rb
- # Time::DATE_FORMATS[:month_and_year] = "%B %Y"
+ # Time::DATE_FORMATS[:month_and_year] = '%B %Y'
# Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
def to_formatted_s(format = :default)
if formatter = ::Time::DATE_FORMATS[format]
@@ -61,7 +61,11 @@ class DateTime
# Attempts to convert self to a Ruby Time object; returns self if out of range of Ruby Time class.
# If self has an offset other than 0, self will just be returned unaltered, since there's no clean way to map it to a Time.
def to_time
- self.offset == 0 ? ::Time.utc_time(year, month, day, hour, min, sec, sec_fraction * 1000000) : self
+ if offset == 0
+ ::Time.utc_time(year, month, day, hour, min, sec, sec_fraction * 1000000)
+ else
+ self
+ end
end
# Returns DateTime with local offset for given year if format is local else offset is zero
diff --git a/activesupport/lib/active_support/core_ext/date_time/zones.rb b/activesupport/lib/active_support/core_ext/date_time/zones.rb
index 6fa55a9255..823735d3e2 100644
--- a/activesupport/lib/active_support/core_ext/date_time/zones.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/zones.rb
@@ -14,8 +14,10 @@ class DateTime
#
# DateTime.new(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
def in_time_zone(zone = ::Time.zone)
- return self unless zone
-
- ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
+ if zone
+ ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
+ else
+ self
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb
index 77a5087981..b9c632e4f5 100644
--- a/activesupport/lib/active_support/core_ext/enumerable.rb
+++ b/activesupport/lib/active_support/core_ext/enumerable.rb
@@ -11,7 +11,7 @@ module Enumerable
# It can also calculate the sum without the use of a block.
#
# [5, 15, 10].sum # => 30
- # ["foo", "bar"].sum # => "foobar"
+ # ['foo', 'bar'].sum # => "foobar"
# [[1, 2], [3, 1, 5]].sum => [1, 2, 3, 1, 5]
#
# The default sum of an empty list is zero. You can override this default:
@@ -34,8 +34,11 @@ module Enumerable
# => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
#
def index_by
- return to_enum :index_by unless block_given?
- Hash[map { |elem| [yield(elem), elem] }]
+ if block_given?
+ Hash[map { |elem| [yield(elem), elem] }]
+ else
+ to_enum :index_by
+ end
end
# Returns true if the enumerable has more than 1 element. Functionally equivalent to enum.to_a.size > 1.
@@ -48,7 +51,7 @@ module Enumerable
cnt > 1
end
else
- any?{ (cnt += 1) > 1 }
+ any? { (cnt += 1) > 1 }
end
end
@@ -62,8 +65,11 @@ class Range #:nodoc:
# Optimize range sum to use arithmetic progression if a block is not given and
# we have a range of numeric values.
def sum(identity = 0)
- return super if block_given? || !(first.instance_of?(Integer) && last.instance_of?(Integer))
- actual_last = exclude_end? ? (last - 1) : last
- (actual_last - first + 1) * (actual_last + first) / 2
+ if block_given? || !(first.instance_of?(Integer) && last.instance_of?(Integer))
+ super
+ else
+ actual_last = exclude_end? ? (last - 1) : last
+ (actual_last - first + 1) * (actual_last + first) / 2
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/file/atomic.rb b/activesupport/lib/active_support/core_ext/file/atomic.rb
index fc3277f4d2..9e504851e7 100644
--- a/activesupport/lib/active_support/core_ext/file/atomic.rb
+++ b/activesupport/lib/active_support/core_ext/file/atomic.rb
@@ -2,15 +2,15 @@ class File
# Write to a file atomically. Useful for situations where you don't
# want other processes or threads to see half-written files.
#
- # File.atomic_write("important.file") do |file|
- # file.write("hello")
+ # File.atomic_write('important.file') do |file|
+ # file.write('hello')
# end
#
# If your temp directory is not on the same filesystem as the file you're
# trying to write, you can provide a different temporary directory.
#
- # File.atomic_write("/data/something.important", "/data/tmp") do |file|
- # file.write("hello")
+ # File.atomic_write('/data/something.important', '/data/tmp') do |file|
+ # file.write('hello')
# end
def self.atomic_write(file_name, temp_dir = Dir.tmpdir)
require 'tempfile' unless defined?(Tempfile)
@@ -26,8 +26,14 @@ class File
old_stat = stat(file_name)
rescue Errno::ENOENT
# No old permissions, write a temp file to determine the defaults
- check_name = join(dirname(file_name), ".permissions_check.#{Thread.current.object_id}.#{Process.pid}.#{rand(1000000)}")
- open(check_name, "w") { }
+ temp_file_name = [
+ '.permissions_check',
+ Thread.current.object_id,
+ Process.pid,
+ rand(1000000)
+ ].join('.')
+ check_name = join(dirname(file_name), temp_file_name)
+ open(check_name, 'w') { }
old_stat = stat(check_name)
unlink(check_name)
end
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index 5f07bb4f5a..469dc41f2d 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -8,7 +8,7 @@ require 'active_support/core_ext/string/inflections'
class Hash
# Returns a string containing an XML representation of its receiver:
#
- # {"foo" => 1, "bar" => 2}.to_xml
+ # {'foo' => 1, 'bar' => 2}.to_xml
# # =>
# # <?xml version="1.0" encoding="UTF-8"?>
# # <hash>
@@ -26,20 +26,20 @@ class Hash
#
# * If +value+ is a callable object it must expect one or two arguments. Depending
# on the arity, the callable is invoked with the +options+ hash as first argument
- # with +key+ as <tt>:root</tt>, and +key+ singularized as second argument. The
+ # with +key+ as <tt>:root</tt>, and +key+ singularized as second argument. The
# callable can add nodes by using <tt>options[:builder]</tt>.
#
- # "foo".to_xml(lambda { |options, key| options[:builder].b(key) })
+ # 'foo'.to_xml(lambda { |options, key| options[:builder].b(key) })
# # => "<b>foo</b>"
#
# * If +value+ responds to +to_xml+ the method is invoked with +key+ as <tt>:root</tt>.
- #
+ #
# class Foo
# def to_xml(options)
- # options[:builder].bar "fooing!"
+ # options[:builder].bar 'fooing!'
# end
# end
- #
+ #
# {:foo => Foo.new}.to_xml(:skip_instruct => true)
# # => "<hash><bar>fooing!</bar></hash>"
#
@@ -71,7 +71,7 @@ class Hash
options = options.dup
options[:indent] ||= 2
- options[:root] ||= "hash"
+ options[:root] ||= 'hash'
options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
builder = options[:builder]
@@ -100,24 +100,24 @@ class Hash
[]
else
case entries.class.to_s # something weird with classes not matching here. maybe singleton methods breaking is_a?
- when "Array"
+ when 'Array'
entries.collect { |v| typecast_xml_value(v) }
- when "Hash"
+ when 'Hash'
[typecast_xml_value(entries)]
else
raise "can't typecast #{entries.inspect}"
end
end
- elsif value['type'] == 'file' ||
- (value["__content__"] && (value.keys.size == 1 || value["__content__"].present?))
- content = value["__content__"]
- if parser = ActiveSupport::XmlMini::PARSING[value["type"]]
+ elsif value['type'] == 'file' ||
+ (value['__content__'] && (value.keys.size == 1 || value['__content__'].present?))
+ content = value['__content__']
+ if parser = ActiveSupport::XmlMini::PARSING[value['type']]
parser.arity == 1 ? parser.call(content) : parser.call(content, value)
else
content
end
elsif value['type'] == 'string' && value['nil'] != 'true'
- ""
+ ''
# blank or nil parsed values are represented by nil
elsif value.blank? || value['nil'] == 'true'
nil
@@ -131,7 +131,7 @@ class Hash
# Turn { :files => { :file => #<StringIO> } into { :files => #<StringIO> } so it is compatible with
# how multipart uploaded files from HTML appear
- xml_value["file"].is_a?(StringIO) ? xml_value["file"] : xml_value
+ xml_value['file'].is_a?(StringIO) ? xml_value['file'] : xml_value
end
when 'Array'
value.map! { |i| typecast_xml_value(i) }
@@ -145,9 +145,9 @@ class Hash
def unrename_keys(params)
case params.class.to_s
- when "Hash"
- Hash[params.map { |k,v| [k.to_s.tr("-", "_"), unrename_keys(v)] } ]
- when "Array"
+ when 'Hash'
+ Hash[params.map { |k,v| [k.to_s.tr('-', '_'), unrename_keys(v)] } ]
+ when 'Array'
params.map { |v| unrename_keys(v) }
else
params
diff --git a/activesupport/lib/active_support/core_ext/hash/diff.rb b/activesupport/lib/active_support/core_ext/hash/diff.rb
index b904f49fa8..855dcb38bc 100644
--- a/activesupport/lib/active_support/core_ext/hash/diff.rb
+++ b/activesupport/lib/active_support/core_ext/hash/diff.rb
@@ -7,7 +7,9 @@ class Hash
# {1 => 2}.diff(1 => 3) # => {1 => 2}
# {}.diff(1 => 2) # => {1 => 2}
# {1 => 2, 3 => 4}.diff(1 => 2) # => {3 => 4}
- def diff(h2)
- dup.delete_if { |k, v| h2[k] == v }.merge!(h2.dup.delete_if { |k, v| has_key?(k) })
+ def diff(other)
+ dup.
+ delete_if { |k, v| other[k] == v }.
+ merge!(other.dup.delete_if { |k, v| has_key?(k) })
end
end
diff --git a/activesupport/lib/active_support/core_ext/hash/except.rb b/activesupport/lib/active_support/core_ext/hash/except.rb
index 89729df258..5a61906222 100644
--- a/activesupport/lib/active_support/core_ext/hash/except.rb
+++ b/activesupport/lib/active_support/core_ext/hash/except.rb
@@ -9,7 +9,7 @@ class Hash
# for instance:
#
# {:a => 1}.with_indifferent_access.except(:a) # => {}
- # {:a => 1}.with_indifferent_access.except("a") # => {}
+ # {:a => 1}.with_indifferent_access.except('a') # => {}
#
def except(*keys)
dup.except!(*keys)
diff --git a/activesupport/lib/active_support/core_ext/hash/keys.rb b/activesupport/lib/active_support/core_ext/hash/keys.rb
index 65c3736593..230a84dabc 100644
--- a/activesupport/lib/active_support/core_ext/hash/keys.rb
+++ b/activesupport/lib/active_support/core_ext/hash/keys.rb
@@ -25,6 +25,7 @@ class Hash
end
result
end
+ alias_method :to_options, :symbolize_keys
# Destructively convert all keys to symbols, as long as they respond
# to +to_sym+.
@@ -34,8 +35,6 @@ class Hash
end
self
end
-
- alias_method :to_options, :symbolize_keys
alias_method :to_options!, :symbolize_keys!
# Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
@@ -43,13 +42,13 @@ class Hash
# as keys, this will fail.
#
# ==== Examples
- # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: years"
- # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key: name"
- # { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
+ # { :name => 'Rob', :years => '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: years"
+ # { :name => 'Rob', :age => '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: name"
+ # { :name => 'Rob', :age => '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
def assert_valid_keys(*valid_keys)
valid_keys.flatten!
each_key do |k|
- raise(ArgumentError, "Unknown key: #{k}") unless valid_keys.include?(k)
+ raise ArgumentError.new("Unknown key: #{k}") unless valid_keys.include?(k)
end
end
end
diff --git a/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb b/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb
index 01863a162b..6074103484 100644
--- a/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb
+++ b/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb
@@ -18,6 +18,5 @@ class Hash
# right wins if there is no left
merge!( other_hash ){|key,left,right| left }
end
-
alias_method :reverse_update, :reverse_merge!
end
diff --git a/activesupport/lib/active_support/core_ext/hash/slice.rb b/activesupport/lib/active_support/core_ext/hash/slice.rb
index 45181f0e16..fdeea4c148 100644
--- a/activesupport/lib/active_support/core_ext/hash/slice.rb
+++ b/activesupport/lib/active_support/core_ext/hash/slice.rb
@@ -31,6 +31,6 @@ class Hash
# Removes and returns the key/value pairs matching the given keys.
# {:a => 1, :b => 2, :c => 3, :d => 4}.extract!(:a, :b) # => {:a => 1, :b => 2}
def extract!(*keys)
- keys.each_with_object({}) {|key, result| result[key] = delete(key) }
+ keys.each_with_object({}) { |key, result| result[key] = delete(key) }
end
end
diff --git a/activesupport/lib/active_support/core_ext/kernel/reporting.rb b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
index 526b8378a5..ad3f9ebec9 100644
--- a/activesupport/lib/active_support/core_ext/kernel/reporting.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
@@ -1,4 +1,5 @@
require 'rbconfig'
+
module Kernel
# Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.
#
@@ -49,10 +50,10 @@ module Kernel
#
# suppress(ZeroDivisionError) do
# 1/0
- # puts "This code is NOT reached"
+ # puts 'This code is NOT reached'
# end
#
- # puts "This code gets executed and nothing related to ZeroDivisionError was seen"
+ # puts 'This code gets executed and nothing related to ZeroDivisionError was seen'
def suppress(*exception_classes)
begin yield
rescue Exception => e
@@ -62,7 +63,7 @@ module Kernel
# Captures the given stream and returns it:
#
- # stream = capture(:stdout) { puts "Cool" }
+ # stream = capture(:stdout) { puts 'Cool' }
# stream # => "Cool\n"
#
def capture(stream)
diff --git a/activesupport/lib/active_support/core_ext/logger.rb b/activesupport/lib/active_support/core_ext/logger.rb
index a51818d2b2..16fce81445 100644
--- a/activesupport/lib/active_support/core_ext/logger.rb
+++ b/activesupport/lib/active_support/core_ext/logger.rb
@@ -56,8 +56,8 @@ class Logger
alias :old_datetime_format= :datetime_format=
# Logging date-time format (string passed to +strftime+). Ignored if the formatter
# does not respond to datetime_format=.
- def datetime_format=(datetime_format)
- formatter.datetime_format = datetime_format if formatter.respond_to?(:datetime_format=)
+ def datetime_format=(format)
+ formatter.datetime_format = format if formatter.respond_to?(:datetime_format=)
end
alias :old_datetime_format :datetime_format
diff --git a/activesupport/lib/active_support/core_ext/module/aliasing.rb b/activesupport/lib/active_support/core_ext/module/aliasing.rb
index ce481f0e84..382156ecd8 100644
--- a/activesupport/lib/active_support/core_ext/module/aliasing.rb
+++ b/activesupport/lib/active_support/core_ext/module/aliasing.rb
@@ -26,18 +26,19 @@ class Module
aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
yield(aliased_target, punctuation) if block_given?
- with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"
+ with_method = "#{aliased_target}_with_#{feature}#{punctuation}"
+ without_method = "#{aliased_target}_without_#{feature}#{punctuation}"
alias_method without_method, target
alias_method target, with_method
case
- when public_method_defined?(without_method)
- public target
- when protected_method_defined?(without_method)
- protected target
- when private_method_defined?(without_method)
- private target
+ when public_method_defined?(without_method)
+ public target
+ when protected_method_defined?(without_method)
+ protected target
+ when private_method_defined?(without_method)
+ private target
end
end
diff --git a/activesupport/lib/active_support/core_ext/module/attr_internal.rb b/activesupport/lib/active_support/core_ext/module/attr_internal.rb
index 00db75bfec..db07d549b0 100644
--- a/activesupport/lib/active_support/core_ext/module/attr_internal.rb
+++ b/activesupport/lib/active_support/core_ext/module/attr_internal.rb
@@ -15,7 +15,6 @@ class Module
attr_internal_reader(*attrs)
attr_internal_writer(*attrs)
end
-
alias_method :attr_internal, :attr_internal_accessor
class << self; attr_accessor :attr_internal_naming_format end
diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
index 84acb629ad..f914425827 100644
--- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
@@ -4,7 +4,7 @@ class Module
def mattr_reader(*syms)
options = syms.extract_options!
syms.each do |sym|
- raise NameError.new("invalid attribute name") unless sym =~ /^[_A-Za-z]\w*$/
+ raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
@@#{sym} = nil unless defined? @@#{sym}
@@ -26,7 +26,7 @@ class Module
def mattr_writer(*syms)
options = syms.extract_options!
syms.each do |sym|
- raise NameError.new("invalid attribute name") unless sym =~ /^[_A-Za-z]\w*$/
+ raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def self.#{sym}=(obj)
@@#{sym} = obj
diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb
index ee8adae1cb..fbef27c76a 100644
--- a/activesupport/lib/active_support/core_ext/module/delegation.rb
+++ b/activesupport/lib/active_support/core_ext/module/delegation.rb
@@ -8,11 +8,11 @@ class Module
#
# class Greeter < ActiveRecord::Base
# def hello
- # "hello"
+ # 'hello'
# end
#
# def goodbye
- # "goodbye"
+ # 'goodbye'
# end
# end
#
@@ -62,7 +62,7 @@ class Module
# delegate :name, :address, :to => :client, :prefix => true
# end
#
- # john_doe = Person.new("John Doe", "Vimmersvej 13")
+ # john_doe = Person.new('John Doe', 'Vimmersvej 13')
# invoice = Invoice.new(john_doe)
# invoice.client_name # => "John Doe"
# invoice.client_address # => "Vimmersvej 13"
@@ -74,8 +74,8 @@ class Module
# end
#
# invoice = Invoice.new(john_doe)
- # invoice.customer_name # => "John Doe"
- # invoice.customer_address # => "Vimmersvej 13"
+ # invoice.customer_name # => 'John Doe'
+ # invoice.customer_address # => 'Vimmersvej 13'
#
# If the delegate object is +nil+ an exception is raised, and that happens
# no matter whether +nil+ responds to the delegated method. You can get a
@@ -104,17 +104,17 @@ class Module
def delegate(*methods)
options = methods.pop
unless options.is_a?(Hash) && to = options[:to]
- raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)."
+ raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter).'
end
to = to.to_s
prefix, allow_nil = options.values_at(:prefix, :allow_nil)
if prefix == true && to =~ /^[^a-z_]/
- raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
+ raise ArgumentError, 'Can only automatically set the delegation prefix when delegating to a method.'
end
- method_prefix =
+ method_prefix = \
if prefix
"#{prefix == true ? to : prefix}_"
else
@@ -129,7 +129,7 @@ class Module
# Attribute writer methods only accept one argument. Makes sure []=
# methods still accept two arguments.
- definition = (method =~ /[^\]]=$/) ? "arg" : "*args, &block"
+ definition = (method =~ /[^\]]=$/) ? 'arg' : '*args, &block'
if allow_nil
module_eval(<<-EOS, file, line - 2)
diff --git a/activesupport/lib/active_support/core_ext/module/introspection.rb b/activesupport/lib/active_support/core_ext/module/introspection.rb
index 743db47bac..3c8e811fa4 100644
--- a/activesupport/lib/active_support/core_ext/module/introspection.rb
+++ b/activesupport/lib/active_support/core_ext/module/introspection.rb
@@ -5,10 +5,11 @@ class Module
#
# M::N.parent_name # => "M"
def parent_name
- unless defined? @parent_name
+ if defined? @parent_name
+ @parent_name
+ else
@parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
end
- @parent_name
end
# Returns the module which contains this one according to its name.
@@ -73,7 +74,7 @@ class Module
# This method is useful for forward compatibility, since Ruby 1.8 returns
# constant names as strings, whereas 1.9 returns them as symbols.
def local_constant_names
- ActiveSupport::Deprecation.warn('Module#local_constant_names is deprecated, use Module#local_constants instead', caller)
+ ActiveSupport::Deprecation.warn 'Module#local_constant_names is deprecated, use Module#local_constants instead', caller
local_constants.map { |c| c.to_s }
end
end
diff --git a/activesupport/lib/active_support/core_ext/module/qualified_const.rb b/activesupport/lib/active_support/core_ext/module/qualified_const.rb
index 8adf050b6b..65525013db 100644
--- a/activesupport/lib/active_support/core_ext/module/qualified_const.rb
+++ b/activesupport/lib/active_support/core_ext/module/qualified_const.rb
@@ -5,7 +5,7 @@ require 'active_support/core_ext/string/inflections'
#++
module QualifiedConstUtils
def self.raise_if_absolute(path)
- raise NameError, "wrong constant name #$&" if path =~ /\A::[^:]+/
+ raise NameError.new("wrong constant name #$&") if path =~ /\A::[^:]+/
end
def self.names(path)
@@ -20,7 +20,7 @@ end
#--
# Qualified names are required to be relative because we are extending existing
# methods that expect constant names, ie, relative paths of length 1. For example,
-# Object.const_get("::String") raises NameError and so does qualified_const_get.
+# Object.const_get('::String') raises NameError and so does qualified_const_get.
#++
class Module
def qualified_const_defined?(path, search_parents=true)
diff --git a/activesupport/lib/active_support/core_ext/object/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb
index d67711f3b8..e238fef5a2 100644
--- a/activesupport/lib/active_support/core_ext/object/blank.rb
+++ b/activesupport/lib/active_support/core_ext/object/blank.rb
@@ -2,7 +2,7 @@
class Object
# An object is blank if it's false, empty, or a whitespace string.
- # For example, "", " ", +nil+, [], and {} are all blank.
+ # For example, '', ' ', +nil+, [], and {} are all blank.
#
# This simplifies:
#
@@ -90,10 +90,10 @@ end
class String
# A string is blank if it's empty or contains whitespaces only:
#
- # "".blank? # => true
- # " ".blank? # => true
- # " ".blank? # => true
- # " something here ".blank? # => false
+ # ''.blank? # => true
+ # ' '.blank? # => true
+ # ' '.blank? # => true
+ # ' something here '.blank? # => false
#
def blank?
self !~ /[^[:space:]]/
diff --git a/activesupport/lib/active_support/core_ext/object/inclusion.rb b/activesupport/lib/active_support/core_ext/object/inclusion.rb
index f611cdd606..3fec465ec0 100644
--- a/activesupport/lib/active_support/core_ext/object/inclusion.rb
+++ b/activesupport/lib/active_support/core_ext/object/inclusion.rb
@@ -2,11 +2,11 @@ class Object
# Returns true if this object is included in the argument(s). Argument must be
# any object which responds to +#include?+ or optionally, multiple arguments can be passed in. Usage:
#
- # characters = ["Konata", "Kagami", "Tsukasa"]
- # "Konata".in?(characters) # => true
- #
- # character = "Konata"
- # character.in?("Konata", "Kagami", "Tsukasa") # => true
+ # characters = ['Konata', 'Kagami', 'Tsukasa']
+ # 'Konata'.in?(characters) # => true
+ #
+ # character = 'Konata'
+ # character.in?('Konata', 'Kagami', 'Tsukasa') # => true
#
# This will throw an ArgumentError if a single argument is passed in and it doesn't respond
# to +#include?+.
@@ -18,7 +18,7 @@ class Object
if another_object.respond_to? :include?
another_object.include? self
else
- raise ArgumentError.new("The single parameter passed to #in? must respond to #include?")
+ raise ArgumentError.new 'The single parameter passed to #in? must respond to #include?'
end
end
end
diff --git a/activesupport/lib/active_support/core_ext/object/with_options.rb b/activesupport/lib/active_support/core_ext/object/with_options.rb
index 1397142c04..e058367111 100644
--- a/activesupport/lib/active_support/core_ext/object/with_options.rb
+++ b/activesupport/lib/active_support/core_ext/object/with_options.rb
@@ -29,7 +29,7 @@ class Object
#
# It can also be used with an explicit receiver:
#
- # I18n.with_options :locale => user.locale, :scope => "newsletter" do |i18n|
+ # I18n.with_options :locale => user.locale, :scope => 'newsletter' do |i18n|
# subject i18n.t :subject
# body i18n.t :body, :user_name => user.name
# end
diff --git a/activesupport/lib/active_support/core_ext/range/include_range.rb b/activesupport/lib/active_support/core_ext/range/include_range.rb
index 684b7cbc4a..3af66aaf2f 100644
--- a/activesupport/lib/active_support/core_ext/range/include_range.rb
+++ b/activesupport/lib/active_support/core_ext/range/include_range.rb
@@ -5,7 +5,7 @@ class Range
# (1..5).include?(2..6) # => false
#
# The native Range#include? behavior is untouched.
- # ("a".."f").include?("c") # => true
+ # ('a'..'f').include?('c') # => true
# (5..9).include?(11) # => false
def include_with_range?(value)
if value.is_a?(::Range)
diff --git a/activesupport/lib/active_support/core_ext/string/access.rb b/activesupport/lib/active_support/core_ext/string/access.rb
index 9b5266c58c..23aaee9c43 100644
--- a/activesupport/lib/active_support/core_ext/string/access.rb
+++ b/activesupport/lib/active_support/core_ext/string/access.rb
@@ -1,4 +1,4 @@
-require "active_support/multibyte"
+require 'active_support/multibyte'
class String
def at(position)
diff --git a/activesupport/lib/active_support/core_ext/string/conversions.rb b/activesupport/lib/active_support/core_ext/string/conversions.rb
index 541f969faa..9084bbee32 100644
--- a/activesupport/lib/active_support/core_ext/string/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/string/conversions.rb
@@ -4,21 +4,33 @@ require 'active_support/core_ext/time/calculations'
class String
# Form can be either :utc (default) or :local.
def to_time(form = :utc)
- return nil if self.blank?
- d = ::Date._parse(self, false).values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset).map { |arg| arg || 0 }
- d[6] *= 1000000
- ::Time.send("#{form}_time", *d[0..6]) - d[7]
+ unless blank?
+ date_values = ::Date._parse(self, false).
+ values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset).
+ map! { |arg| arg || 0 }
+ date_values[6] *= 1000000
+ offset = date_values.pop
+
+ ::Time.send("#{form}_time", *date_values) - offset
+ end
end
def to_date
- return nil if self.blank?
- ::Date.new(*::Date._parse(self, false).values_at(:year, :mon, :mday))
+ unless blank?
+ date_values = ::Date._parse(self, false).values_at(:year, :mon, :mday)
+
+ ::Date.new(*date_values)
+ end
end
def to_datetime
- return nil if self.blank?
- d = ::Date._parse(self, false).values_at(:year, :mon, :mday, :hour, :min, :sec, :zone, :sec_fraction).map { |arg| arg || 0 }
- d[5] += d.pop
- ::DateTime.civil(*d)
+ unless blank?
+ date_values = ::Date._parse(self, false).
+ values_at(:year, :mon, :mday, :hour, :min, :sec, :zone, :sec_fraction).
+ map! { |arg| arg || 0 }
+ date_values[5] += date_values.pop
+
+ ::DateTime.civil(*date_values)
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb
index 1a34e88a87..32a37296d5 100644
--- a/activesupport/lib/active_support/core_ext/string/filters.rb
+++ b/activesupport/lib/active_support/core_ext/string/filters.rb
@@ -22,26 +22,33 @@ class String
# Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>:
#
- # "Once upon a time in a world far far away".truncate(27)
+ # 'Once upon a time in a world far far away'.truncate(27)
# # => "Once upon a time in a wo..."
#
- # Pass a <tt>:separator</tt> to truncate +text+ at a natural break:
+ # Pass a string or regexp <tt>:separator</tt> to truncate +text+ at a natural break:
#
- # "Once upon a time in a world far far away".truncate(27, :separator => ' ')
+ # 'Once upon a time in a world far far away'.truncate(27, :separator => ' ')
+ # # => "Once upon a time in a..."
+ #
+ # 'Once upon a time in a world far far away'.truncate(27, :separator => /\s/)
# # => "Once upon a time in a..."
#
# The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
# for a total length not exceeding <tt>:length</tt>:
#
- # "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)")
+ # 'And they found that many people were sleeping better.'.truncate(25, :omission => '... (continued)')
# # => "And they f... (continued)"
- def truncate(length, options = {})
- return self.dup unless self.length > length
+ def truncate(truncate_at, options = {})
+ return dup unless length > truncate_at
- options[:omission] ||= "..."
- length_with_room_for_omission = length - options[:omission].length
- stop = options[:separator] ?
- (rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission) : length_with_room_for_omission
+ options[:omission] ||= '...'
+ length_with_room_for_omission = truncate_at - options[:omission].length
+ stop = \
+ if options[:separator]
+ rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission
+ else
+ length_with_room_for_omission
+ end
self[0...stop] + options[:omission]
end
diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb
index 2194dafe4d..049ffe7986 100644
--- a/activesupport/lib/active_support/core_ext/string/inflections.rb
+++ b/activesupport/lib/active_support/core_ext/string/inflections.rb
@@ -4,7 +4,7 @@ require 'active_support/inflector/transliterate'
# String inflections define new methods on the String class to transform names for different purposes.
# For instance, you can figure out the name of a table from the name of a class.
#
-# "ScaleScore".tableize # => "scale_scores"
+# 'ScaleScore'.tableize # => "scale_scores"
#
class String
# Returns the plural form of the word in the string.
@@ -14,14 +14,14 @@ class String
# For any other value of +count+ the plural will be returned.
#
# ==== Examples
- # "post".pluralize # => "posts"
- # "octopus".pluralize # => "octopi"
- # "sheep".pluralize # => "sheep"
- # "words".pluralize # => "words"
- # "the blue mailman".pluralize # => "the blue mailmen"
- # "CamelOctopus".pluralize # => "CamelOctopi"
- # "apple".pluralize(1) # => "apple"
- # "apple".pluralize(2) # => "apples"
+ # 'post'.pluralize # => "posts"
+ # 'octopus'.pluralize # => "octopi"
+ # 'sheep'.pluralize # => "sheep"
+ # 'words'.pluralize # => "words"
+ # 'the blue mailman'.pluralize # => "the blue mailmen"
+ # 'CamelOctopus'.pluralize # => "CamelOctopi"
+ # 'apple'.pluralize(1) # => "apple"
+ # 'apple'.pluralize(2) # => "apples"
def pluralize(count = nil)
if count == 1
self
@@ -32,12 +32,12 @@ class String
# The reverse of +pluralize+, returns the singular form of a word in a string.
#
- # "posts".singularize # => "post"
- # "octopi".singularize # => "octopus"
- # "sheep".singularize # => "sheep"
- # "word".singularize # => "word"
- # "the blue mailmen".singularize # => "the blue mailman"
- # "CamelOctopi".singularize # => "CamelOctopus"
+ # 'posts'.singularize # => "post"
+ # 'octopi'.singularize # => "octopus"
+ # 'sheep'.singularize # => "sheep"
+ # 'word'.singularize # => "word"
+ # 'the blue mailmen'.singularize # => "the blue mailman"
+ # 'CamelOctopi'.singularize # => "CamelOctopus"
def singularize
ActiveSupport::Inflector.singularize(self)
end
@@ -47,9 +47,9 @@ class String
# or is not initialized. See ActiveSupport::Inflector.constantize
#
# Examples
- # "Module".constantize # => Module
- # "Class".constantize # => Class
- # "blargle".constantize # => NameError: wrong constant name blargle
+ # 'Module'.constantize # => Module
+ # 'Class'.constantize # => Class
+ # 'blargle'.constantize # => NameError: wrong constant name blargle
def constantize
ActiveSupport::Inflector.constantize(self)
end
@@ -59,9 +59,9 @@ class String
# or is not initialized. See ActiveSupport::Inflector.safe_constantize
#
# Examples
- # "Module".safe_constantize # => Module
- # "Class".safe_constantize # => Class
- # "blargle".safe_constantize # => nil
+ # 'Module'.safe_constantize # => Module
+ # 'Class'.safe_constantize # => Class
+ # 'blargle'.safe_constantize # => nil
def safe_constantize
ActiveSupport::Inflector.safe_constantize(self)
end
@@ -71,14 +71,16 @@ class String
#
# +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
#
- # "active_record".camelize # => "ActiveRecord"
- # "active_record".camelize(:lower) # => "activeRecord"
- # "active_record/errors".camelize # => "ActiveRecord::Errors"
- # "active_record/errors".camelize(:lower) # => "activeRecord::Errors"
+ # 'active_record'.camelize # => "ActiveRecord"
+ # 'active_record'.camelize(:lower) # => "activeRecord"
+ # 'active_record/errors'.camelize # => "ActiveRecord::Errors"
+ # 'active_record/errors'.camelize(:lower) # => "activeRecord::Errors"
def camelize(first_letter = :upper)
case first_letter
- when :upper then ActiveSupport::Inflector.camelize(self, true)
- when :lower then ActiveSupport::Inflector.camelize(self, false)
+ when :upper
+ ActiveSupport::Inflector.camelize(self, true)
+ when :lower
+ ActiveSupport::Inflector.camelize(self, false)
end
end
alias_method :camelcase, :camelize
@@ -89,8 +91,8 @@ class String
#
# +titleize+ is also aliased as +titlecase+.
#
- # "man from the boondocks".titleize # => "Man From The Boondocks"
- # "x-men: the last stand".titleize # => "X Men: The Last Stand"
+ # 'man from the boondocks'.titleize # => "Man From The Boondocks"
+ # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
def titleize
ActiveSupport::Inflector.titleize(self)
end
@@ -100,23 +102,23 @@ class String
#
# +underscore+ will also change '::' to '/' to convert namespaces to paths.
#
- # "ActiveModel".underscore # => "active_model"
- # "ActiveModel::Errors".underscore # => "active_model/errors"
+ # 'ActiveModel'.underscore # => "active_model"
+ # 'ActiveModel::Errors'.underscore # => "active_model/errors"
def underscore
ActiveSupport::Inflector.underscore(self)
end
# Replaces underscores with dashes in the string.
#
- # "puni_puni" # => "puni-puni"
+ # 'puni_puni' # => "puni-puni"
def dasherize
ActiveSupport::Inflector.dasherize(self)
end
# Removes the module part from the constant expression in the string.
#
- # "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections"
- # "Inflections".demodulize # => "Inflections"
+ # 'ActiveRecord::CoreExtensions::String::Inflections'.demodulize # => "Inflections"
+ # 'Inflections'.demodulize # => "Inflections"
#
# See also +deconstantize+.
def demodulize
@@ -125,11 +127,11 @@ class String
# Removes the rightmost segment from the constant expression in the string.
#
- # "Net::HTTP".deconstantize # => "Net"
- # "::Net::HTTP".deconstantize # => "::Net"
- # "String".deconstantize # => ""
- # "::String".deconstantize # => ""
- # "".deconstantize # => ""
+ # 'Net::HTTP'.deconstantize # => "Net"
+ # '::Net::HTTP'.deconstantize # => "::Net"
+ # 'String'.deconstantize # => ""
+ # '::String'.deconstantize # => ""
+ # ''.deconstantize # => ""
#
# See also +demodulize+.
def deconstantize
@@ -158,9 +160,9 @@ class String
# Creates the name of a table like Rails does for models to table names. This method
# uses the +pluralize+ method on the last word in the string.
#
- # "RawScaledScorer".tableize # => "raw_scaled_scorers"
- # "egg_and_ham".tableize # => "egg_and_hams"
- # "fancyCategory".tableize # => "fancy_categories"
+ # 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
+ # 'egg_and_ham'.tableize # => "egg_and_hams"
+ # 'fancyCategory'.tableize # => "fancy_categories"
def tableize
ActiveSupport::Inflector.tableize(self)
end
@@ -169,12 +171,12 @@ class String
# Note that this returns a string and not a class. (To convert to an actual class
# follow +classify+ with +constantize+.)
#
- # "egg_and_hams".classify # => "EggAndHam"
- # "posts".classify # => "Post"
+ # 'egg_and_hams'.classify # => "EggAndHam"
+ # 'posts'.classify # => "Post"
#
# Singular names are not handled correctly.
#
- # "business".classify # => "Busines"
+ # 'business'.classify # => "Busines"
def classify
ActiveSupport::Inflector.classify(self)
end
@@ -182,8 +184,8 @@ class String
# Capitalizes the first word, turns underscores into spaces, and strips '_id'.
# Like +titleize+, this is meant for creating pretty output.
#
- # "employee_salary" # => "Employee salary"
- # "author_id" # => "Author"
+ # 'employee_salary' # => "Employee salary"
+ # 'author_id' # => "Author"
def humanize
ActiveSupport::Inflector.humanize(self)
end
@@ -193,9 +195,9 @@ class String
# the method should put '_' between the name and 'id'.
#
# Examples
- # "Message".foreign_key # => "message_id"
- # "Message".foreign_key(false) # => "messageid"
- # "Admin::Post".foreign_key # => "post_id"
+ # 'Message'.foreign_key # => "message_id"
+ # 'Message'.foreign_key(false) # => "messageid"
+ # 'Admin::Post'.foreign_key # => "post_id"
def foreign_key(separate_class_name_and_id_with_underscore = true)
ActiveSupport::Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
end
diff --git a/activesupport/lib/active_support/core_ext/string/inquiry.rb b/activesupport/lib/active_support/core_ext/string/inquiry.rb
index 5f0a017de6..2562a7cef6 100644
--- a/activesupport/lib/active_support/core_ext/string/inquiry.rb
+++ b/activesupport/lib/active_support/core_ext/string/inquiry.rb
@@ -4,7 +4,7 @@ class String
# Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
# which gives you a prettier way to test for equality. Example:
#
- # env = "production".inquiry
+ # env = 'production'.inquiry
# env.production? # => true
# env.development? # => false
def inquiry
diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb
index 4903687b73..215ba87ca9 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -15,7 +15,7 @@ class ERB
# <%=h @person.name %>
#
# ==== Example:
- # puts html_escape("is a > 0 & a < 10?")
+ # puts html_escape('is a > 0 & a < 10?')
# # => is a &gt; 0 &amp; a &lt; 10?
def html_escape(s)
s = s.to_s
@@ -38,10 +38,10 @@ class ERB
# A utility method for escaping HTML without affecting existing escaped entities.
#
# ==== Examples
- # html_escape_once("1 < 2 &amp; 3")
+ # html_escape_once('1 < 2 &amp; 3')
# # => "1 &lt; 2 &amp; 3"
#
- # html_escape_once("&lt;&lt; Accept & Checkout")
+ # html_escape_once('&lt;&lt; Accept & Checkout')
# # => "&lt;&lt; Accept &amp; Checkout"
def html_escape_once(s)
result = s.to_s.gsub(HTML_ESCAPE_ONCE_REGEXP) { |special| HTML_ESCAPE[special] }
@@ -53,7 +53,7 @@ class ERB
# A utility method for escaping HTML entities in JSON strings
# using \uXXXX JavaScript escape sequences for string literals:
#
- # json_escape("is a > 0 & a < 10?")
+ # json_escape('is a > 0 & a < 10?')
# # => is a \u003E 0 \u0026 a \u003C 10?
#
# Note that after this operation is performed the output is not
@@ -92,26 +92,31 @@ end
module ActiveSupport #:nodoc:
class SafeBuffer < String
- UNSAFE_STRING_METHODS = ["capitalize", "chomp", "chop", "delete", "downcase", "gsub", "lstrip", "next", "reverse", "rstrip", "slice", "squeeze", "strip", "sub", "succ", "swapcase", "tr", "tr_s", "upcase", "prepend"].freeze
+ UNSAFE_STRING_METHODS = %w(
+ capitalize chomp chop delete downcase gsub lstrip next reverse rstrip
+ slice squeeze strip sub succ swapcase tr tr_s upcase prepend
+ )
alias_method :original_concat, :concat
private :original_concat
class SafeConcatError < StandardError
def initialize
- super "Could not concatenate to the buffer because it is not html safe."
+ super 'Could not concatenate to the buffer because it is not html safe.'
end
end
def [](*args)
- return super if args.size < 2
-
- if html_safe?
- new_safe_buffer = super
- new_safe_buffer.instance_eval { @html_safe = true }
- new_safe_buffer
+ if args.size < 2
+ super
else
- to_str[*args]
+ if html_safe?
+ new_safe_buffer = super
+ new_safe_buffer.instance_eval { @html_safe = true }
+ new_safe_buffer
+ else
+ to_str[*args]
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb
index 7add47be44..1434e186c3 100644
--- a/activesupport/lib/active_support/core_ext/time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/time/calculations.rb
@@ -3,7 +3,15 @@ require 'active_support/core_ext/time/conversions'
class Time
COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
- DAYS_INTO_WEEK = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6 }
+ DAYS_INTO_WEEK = {
+ :monday => 0,
+ :tuesday => 1,
+ :wednesday => 2,
+ :thursday => 3,
+ :friday => 4,
+ :saturday => 5,
+ :sunday => 6
+ }
class << self
# Overriding case equality method so that it returns true for ActiveSupport::TimeWithZone instances
@@ -14,8 +22,11 @@ class Time
# Return the number of days in the given month.
# If no year is specified, it will use the current year.
def days_in_month(month, year = now.year)
- return 29 if month == 2 && ::Date.gregorian_leap?(year)
- COMMON_YEAR_DAYS_IN_MONTH[month]
+ if month == 2 && ::Date.gregorian_leap?(year)
+ 29
+ else
+ COMMON_YEAR_DAYS_IN_MONTH[month]
+ end
end
# Returns a new Time if requested year can be accommodated by Ruby's Time class
@@ -23,8 +34,13 @@ class Time
# otherwise returns a DateTime.
def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
time = ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec)
+
# This check is needed because Time.utc(y) returns a time object in the 2000s for 0 <= y <= 138.
- time.year == year ? time : ::DateTime.civil_from_format(utc_or_local, year, month, day, hour, min, sec)
+ if time.year == year
+ time
+ else
+ ::DateTime.civil_from_format(utc_or_local, year, month, day, hour, min, sec)
+ end
rescue
::DateTime.civil_from_format(utc_or_local, year, month, day, hour, min, sec)
end
@@ -71,13 +87,13 @@ class Time
def change(options)
::Time.send(
utc? ? :utc_time : :local_time,
- options[:year] || year,
- options[:month] || month,
- options[:day] || day,
- options[:hour] || hour,
- options[:min] || (options[:hour] ? 0 : min),
- options[:sec] || ((options[:hour] || options[:min]) ? 0 : sec),
- options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
+ options.fetch(:year, year),
+ options.fetch(:month, month),
+ options.fetch(:day, day),
+ options.fetch(:hour, hour),
+ options.fetch(:min, options[:hour] ? 0 : min),
+ options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec),
+ options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
)
end
@@ -88,18 +104,26 @@ class Time
def advance(options)
unless options[:weeks].nil?
options[:weeks], partial_weeks = options[:weeks].divmod(1)
- options[:days] = (options[:days] || 0) + 7 * partial_weeks
+ options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
end
unless options[:days].nil?
options[:days], partial_days = options[:days].divmod(1)
- options[:hours] = (options[:hours] || 0) + 24 * partial_days
+ options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
end
d = to_date.advance(options)
time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
- seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
- seconds_to_advance == 0 ? time_advanced_by_date : time_advanced_by_date.since(seconds_to_advance)
+ seconds_to_advance = \
+ options.fetch(:seconds, 0) +
+ options.fetch(:minutes, 0) * 60 +
+ options.fetch(:hours, 0) * 3600
+
+ if seconds_to_advance.zero?
+ time_advanced_by_date
+ else
+ time_advanced_by_date.since(seconds_to_advance)
+ end
end
# Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
@@ -167,6 +191,7 @@ class Time
start_day_number = DAYS_INTO_WEEK[start_day]
current_day_number = wday != 0 ? wday - 1 : 6
days_span = current_day_number - start_day_number
+
days_span >= 0 ? days_span : 7 + days_span
end
@@ -198,13 +223,19 @@ class Time
# Returns a new Time representing the start of the given day in the previous week (default is :monday).
def prev_week(day = :monday)
- ago(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
+ ago(1.week).
+ beginning_of_week.
+ since(DAYS_INTO_WEEK[day].day).
+ change(:hour => 0)
end
alias_method :last_week, :prev_week
# Returns a new Time representing the start of the given day in next week (default is :monday).
def next_week(day = :monday)
- since(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
+ since(1.week).
+ beginning_of_week.
+ since(DAYS_INTO_WEEK[day].day).
+ change(:hour => 0)
end
# Returns a new Time representing the start of the day (0:00)
@@ -218,7 +249,12 @@ class Time
# Returns a new Time representing the end of the day, 23:59:59.999999 (.999999999 in ruby1.9)
def end_of_day
- change(:hour => 23, :min => 59, :sec => 59, :usec => 999999.999)
+ change(
+ :hour => 23,
+ :min => 59,
+ :sec => 59,
+ :usec => 999999.999
+ )
end
# Returns a new Time representing the start of the month (1st of the month, 0:00)
@@ -232,19 +268,27 @@ class Time
def end_of_month
#self - ((self.mday-1).days + self.seconds_since_midnight)
last_day = ::Time.days_in_month(month, year)
- change(:day => last_day, :hour => 23, :min => 59, :sec => 59, :usec => 999999.999)
+ change(
+ :day => last_day,
+ :hour => 23,
+ :min => 59,
+ :sec => 59,
+ :usec => 999999.999
+ )
end
alias :at_end_of_month :end_of_month
# Returns a new Time representing the start of the quarter (1st of january, april, july, october, 0:00)
def beginning_of_quarter
- beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= month })
+ first_quarter_month = [10, 7, 4, 1].detect { |m| m <= month }
+ beginning_of_month.change(:month => first_quarter_month)
end
alias :at_beginning_of_quarter :beginning_of_quarter
# Returns a new Time representing the end of the quarter (end of the last day of march, june, september, december)
def end_of_quarter
- beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= month }).end_of_month
+ last_quarter_month = [3, 6, 9, 12].detect { |m| m >= month }
+ beginning_of_month.change(:month => last_quarter_month).end_of_month
end
alias :at_end_of_quarter :end_of_quarter
@@ -256,7 +300,14 @@ class Time
# Returns a new Time representing the end of the year (end of the 31st of december)
def end_of_year
- change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59, :usec => 999999.999)
+ change(
+ :month => 12,
+ :day => 31,
+ :hour => 23,
+ :min => 59,
+ :sec => 59,
+ :usec => 999999.999
+ )
end
alias :at_end_of_year :end_of_year
@@ -329,7 +380,11 @@ class Time
# can be chronologically compared with a Time
def compare_with_coercion(other)
# we're avoiding Time#to_datetime cause it's expensive
- other.is_a?(Time) ? compare_without_coercion(other.to_time) : to_datetime <=> other
+ if other.is_a?(Time)
+ compare_without_coercion(other.to_time)
+ else
+ to_datetime <=> other
+ end
end
alias_method :compare_without_coercion, :<=>
alias_method :<=>, :compare_with_coercion
@@ -343,4 +398,5 @@ class Time
end
alias_method :eql_without_coercion, :eql?
alias_method :eql?, :eql_with_coercion
+
end
diff --git a/activesupport/lib/active_support/core_ext/time/conversions.rb b/activesupport/lib/active_support/core_ext/time/conversions.rb
index 0fdcd383f0..4f852fd780 100644
--- a/activesupport/lib/active_support/core_ext/time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/time/conversions.rb
@@ -3,13 +3,19 @@ require 'active_support/values/time_zone'
class Time
DATE_FORMATS = {
- :db => "%Y-%m-%d %H:%M:%S",
- :number => "%Y%m%d%H%M%S",
- :time => "%H:%M",
- :short => "%d %b %H:%M",
- :long => "%B %d, %Y %H:%M",
- :long_ordinal => lambda { |time| time.strftime("%B #{ActiveSupport::Inflector.ordinalize(time.day)}, %Y %H:%M") },
- :rfc822 => lambda { |time| time.strftime("%a, %d %b %Y %H:%M:%S #{time.formatted_offset(false)}") }
+ :db => '%Y-%m-%d %H:%M:%S',
+ :number => '%Y%m%d%H%M%S',
+ :time => '%H:%M',
+ :short => '%d %b %H:%M',
+ :long => '%B %d, %Y %H:%M',
+ :long_ordinal => lambda { |time|
+ day_format = ActiveSupport::Inflector.ordinalize(time.day)
+ time.strftime("%B #{day_format}, %Y %H:%M")
+ },
+ :rfc822 => lambda { |time|
+ offset_format = time.formatted_offset(false)
+ time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
+ }
}
# Converts to a formatted string. See DATE_FORMATS for builtin formats.
@@ -34,7 +40,7 @@ class Time
# or Proc instance that takes a time argument as the value.
#
# # config/initializers/time_formats.rb
- # Time::DATE_FORMATS[:month_and_year] = "%B %Y"
+ # Time::DATE_FORMATS[:month_and_year] = '%B %Y'
# Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
def to_formatted_s(format = :default)
if formatter = DATE_FORMATS[format]
diff --git a/activesupport/lib/active_support/core_ext/time/zones.rb b/activesupport/lib/active_support/core_ext/time/zones.rb
index b4ed74a7b0..e48866abe3 100644
--- a/activesupport/lib/active_support/core_ext/time/zones.rb
+++ b/activesupport/lib/active_support/core_ext/time/zones.rb
@@ -51,13 +51,21 @@ class Time
# Returns a TimeZone instance or nil, or raises an ArgumentError for invalid timezones.
def find_zone!(time_zone)
- return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone)
- # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
- unless time_zone.respond_to?(:period_for_local)
- time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
+ if !time_zone || time_zone.is_a?(ActiveSupport::TimeZone)
+ time_zone
+ else
+ # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
+ unless time_zone.respond_to?(:period_for_local)
+ time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
+ end
+
+ # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
+ if time_zone.is_a?(ActiveSupport::TimeZone)
+ time_zone
+ else
+ ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
+ end
end
- # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
- time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
rescue TZInfo::InvalidTimezoneIdentifier
raise ArgumentError, "Invalid Timezone: #{time_zone}"
end
@@ -80,8 +88,10 @@ class Time
#
# Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
def in_time_zone(zone = ::Time.zone)
- return self unless zone
-
- ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
+ if zone
+ ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
+ else
+ self
+ end
end
end
diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb
index 94f8d7133e..73b6a42505 100644
--- a/activesupport/lib/active_support/deprecation/behaviors.rb
+++ b/activesupport/lib/active_support/deprecation/behaviors.rb
@@ -13,6 +13,13 @@ module ActiveSupport
# Sets the behavior to the specified value. Can be a single value or an array.
#
+ # Available behaviors:
+ #
+ # [+:stderr+] Print deprecations to +$stderror+
+ # [+:log+] Send to +Rails.logger+
+ # [+:notify+] Instrument using +ActiveSupport::Notifications+
+ # [+:silence+] Do nothing
+ #
# Examples
#
# ActiveSupport::Deprecation.behavior = :stderr
@@ -41,8 +48,9 @@ module ActiveSupport
},
:notify => Proc.new { |message, callstack|
ActiveSupport::Notifications.instrument("deprecation.rails",
- :message => message, :callstack => callstack)
- }
+ :message => message, :callstack => callstack)
+ },
+ :silence => Proc.new { |message, callstack| }
}
end
end
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index 6c2828b74e..9010a4a716 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -279,6 +279,12 @@ class StringInflectionsTest < ActiveSupport::TestCase
assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, :omission => "[...]", :separator => ' ')
end
+ def test_truncate_with_omission_and_regexp_seperator
+ assert_equal "Hello[...]", "Hello Big World!".truncate(13, :omission => "[...]", :separator => /\s/)
+ assert_equal "Hello Big[...]", "Hello Big World!".truncate(14, :omission => "[...]", :separator => /\s/)
+ assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, :omission => "[...]", :separator => /\s/)
+ end
+
def test_truncate_multibyte
assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'),
"\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8').truncate(10)
diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb
index e821a285d7..e21f3efe36 100644
--- a/activesupport/test/deprecation_test.rb
+++ b/activesupport/test/deprecation_test.rb
@@ -93,6 +93,26 @@ class DeprecationTest < ActiveSupport::TestCase
assert_match(/foo=nil/, @b)
end
+ def test_default_stderr_behavior
+ ActiveSupport::Deprecation.behavior = :stderr
+ behavior = ActiveSupport::Deprecation.behavior.first
+
+ content = capture(:stderr) {
+ assert_nil behavior.call('Some error!', ['call stack!'])
+ }
+ assert_match(/Some error!/, content)
+ assert_match(/call stack!/, content)
+ end
+
+ def test_default_silence_behavior
+ ActiveSupport::Deprecation.behavior = :silence
+ behavior = ActiveSupport::Deprecation.behavior.first
+
+ assert_blank capture(:stderr) {
+ assert_nil behavior.call('Some error!', ['call stack!'])
+ }
+ end
+
def test_deprecated_instance_variable_proxy
assert_not_deprecated { @dtc.request.size }
diff --git a/guides/source/active_record_querying.textile b/guides/source/active_record_querying.textile
index 98937266ba..902ceeb78b 100644
--- a/guides/source/active_record_querying.textile
+++ b/guides/source/active_record_querying.textile
@@ -356,20 +356,6 @@ Client.where("created_at >= :start_date AND created_at <= :end_date",
This makes for clearer readability if you have a large number of variable conditions.
-h5(#array-range_conditions). Range Conditions
-
-If you're looking for a range inside of a table (for example, users created in a certain timeframe) you can use the conditions option coupled with the +IN+ SQL statement for this. If you had two dates coming in from a controller you could do something like this to look for a range:
-
-<ruby>
-Client.where(:created_at => (params[:start_date].to_date)..(params[:end_date].to_date))
-</ruby>
-
-This query will generate something similar to the following SQL:
-
-<sql>
- SELECT "clients".* FROM "clients" WHERE ("clients"."created_at" BETWEEN '2010-09-29' AND '2010-11-30')
-</sql>
-
h4. Hash Conditions
Active Record also allows you to pass in hash conditions which can increase the readability of your conditions syntax. With hash conditions, you pass in a hash with keys of the fields you want conditionalised and the values of how you want to conditionalise them:
@@ -392,8 +378,6 @@ NOTE: The values cannot be symbols. For example, you cannot do +Client.where(:st
h5(#hash-range_conditions). Range Conditions
-The good thing about this is that we can pass in a range for our fields without it generating a large query as shown in the preamble of this section.
-
<ruby>
Client.where(:created_at => (Time.now.midnight - 1.day)..Time.now.midnight)
</ruby>
diff --git a/guides/source/configuring.textile b/guides/source/configuring.textile
index 28c138c714..68426221bf 100644
--- a/guides/source/configuring.textile
+++ b/guides/source/configuring.textile
@@ -362,7 +362,7 @@ h4. Configuring Action View
Proc.new { |html_tag, instance| %Q(<div class="field_with_errors">#{html_tag}</div>).html_safe }
</ruby>
-* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+.
+* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+. If you want your form builder class to be loaded after initialization (so it's reloaded on each request in development), you can pass it as a +String+
* +config.action_view.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then used to log information from Action View. Set to +nil+ to disable logging.
diff --git a/guides/source/layouts_and_rendering.textile b/guides/source/layouts_and_rendering.textile
index c2bba56581..f69afaa281 100644
--- a/guides/source/layouts_and_rendering.textile
+++ b/guides/source/layouts_and_rendering.textile
@@ -1193,6 +1193,16 @@ h5. Spacer Templates
Rails will render the +_product_ruler+ partial (with no data passed in to it) between each pair of +_product+ partials.
+h5. Partial Layouts
+
+When rendering collections it is also possible to use the +:layout+ option:
+
+<erb>
+<%= render :partial => "product", :collection => @products, :layout => "special_layout" %>
+</erb>
+
+The layout will be rendered together with the partial for each item in the collection. The current object and object_counter variables will be available in the layout as well, the same way they do within the partial.
+
h4. Using Nested Layouts
You may find that your application requires a layout that differs slightly from your regular application layout to support one particular controller. Rather than repeating the main layout and editing it, you can accomplish this by using nested layouts (sometimes called sub-templates). Here's an example:
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 1680a6ed00..c7b19c964a 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -66,9 +66,10 @@ module Rails
end
end
- attr_accessor :assets, :sandbox, :queue
+ attr_accessor :assets, :sandbox
alias_method :sandbox?, :sandbox
attr_reader :reloaders
+ attr_writer :queue
delegate :default_url_options, :default_url_options=, :to => :routes
diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb
index 7f9190b01a..19f616ec50 100644
--- a/railties/lib/rails/application/routes_reloader.rb
+++ b/railties/lib/rails/application/routes_reloader.rb
@@ -24,12 +24,11 @@ module Rails
def updater
@updater ||= begin
- dirs = @external_routes.inject({}) do |hash, dir|
- hash.merge(dir.to_s => ["rb"])
+ dirs = @external_routes.each_with_object({}) do |dir, hash|
+ hash[dir.to_s] = %w(rb)
end
updater = ActiveSupport::FileUpdateChecker.new(paths, dirs) { reload! }
-
updater.execute
updater
end
diff --git a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb
index 303331a4f0..d78d97b2b4 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb
+++ b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb
@@ -1,23 +1,27 @@
<h1>Listing <%= plural_table_name %></h1>
<table>
- <tr>
-<% attributes.each do |attribute| -%>
- <th><%= attribute.human_name %></th>
-<% end -%>
- <th></th>
- <th></th>
- <th></th>
- </tr>
+ <thead>
+ <tr>
+ <% attributes.each do |attribute| -%>
+ <th><%= attribute.human_name %></th>
+ <% end -%>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+ </thead>
- <%%= content_tag_for(:tr, @<%= plural_table_name %>) do |<%= singular_table_name %>| %>
-<% attributes.each do |attribute| -%>
- <td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td>
-<% end -%>
- <td><%%= link_to 'Show', <%= singular_table_name %> %></td>
- <td><%%= link_to 'Edit', edit_<%= singular_table_name %>_path(<%= singular_table_name %>) %></td>
- <td><%%= link_to 'Destroy', <%= singular_table_name %>, confirm: 'Are you sure?', method: :delete %></td>
- <%% end %>
+ <tbody>
+ <%%= content_tag_for(:tr, @<%= plural_table_name %>) do |<%= singular_table_name %>| %>
+ <% attributes.each do |attribute| -%>
+ <td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td>
+ <% end -%>
+ <td><%%= link_to 'Show', <%= singular_table_name %> %></td>
+ <td><%%= link_to 'Edit', edit_<%= singular_table_name %>_path(<%= singular_table_name %>) %></td>
+ <td><%%= link_to 'Destroy', <%= singular_table_name %>, confirm: 'Are you sure?', method: :delete %></td>
+ <%% end %>
+ </tbody>
</table>
<br />
diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb
index 4560dcec69..977a5fc7e8 100644
--- a/railties/test/application/routing_test.rb
+++ b/railties/test/application/routing_test.rb
@@ -249,9 +249,7 @@ module ApplicationTests
assert_equal 404, last_response.status
end
end
- end
- {"development" => "baz", "production" => "bar"}.each do |mode, expected|
test "reloads routes when configuration is changed in #{mode}" do
controller :foo, <<-RUBY
class FooController < ApplicationController
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 7957186ba2..f2dc0c71b1 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -18,7 +18,6 @@ RAILS_FRAMEWORK_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../../..")
# These files do not require any others and are needed
# to run the tests
require "#{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/testing/isolation"
-require "#{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/testing/declarative"
require "#{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/core_ext/kernel/reporting"
module TestHelpers
@@ -268,7 +267,6 @@ class ActiveSupport::TestCase
include TestHelpers::Paths
include TestHelpers::Rack
include TestHelpers::Generation
- extend ActiveSupport::Testing::Declarative
end
# Create a scope and build a fixture rails app