aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG.md2
-rwxr-xr-xactionpack/Rakefile16
-rw-r--r--actionpack/lib/action_controller.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/mime_types.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/selector.rb4
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb18
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb6
-rw-r--r--actionpack/lib/action_view/helpers/tags/collection_select.rb9
-rw-r--r--actionpack/lib/action_view/helpers/tags/select.rb27
-rw-r--r--actionpack/lib/action_view/renderer/partial_renderer.rb3
-rw-r--r--actionpack/test/fixtures/developers.yml2
-rw-r--r--actionpack/test/template/asset_tag_helper_test.rb2
-rw-r--r--actionpack/test/template/date_helper_i18n_test.rb6
-rw-r--r--activerecord/CHANGELOG.md19
-rwxr-xr-xactiverecord/Rakefile16
-rw-r--r--activerecord/lib/active_record/associations.rb8
-rw-r--r--activerecord/lib/active_record/associations/builder/association.rb31
-rw-r--r--activerecord/lib/active_record/associations/builder/has_many.rb8
-rw-r--r--activerecord/lib/active_record/associations/builder/has_one.rb12
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb2
-rw-r--r--activerecord/lib/active_record/core.rb10
-rw-r--r--activerecord/lib/active_record/dynamic_finder_match.rb82
-rw-r--r--activerecord/lib/active_record/dynamic_matchers.rb2
-rw-r--r--activerecord/lib/active_record/dynamic_scope_match.rb4
-rw-r--r--activerecord/lib/active_record/locale/en.yml1
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb2
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb9
-rw-r--r--activerecord/lib/active_record/validations/uniqueness.rb3
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb66
-rw-r--r--activerecord/test/cases/associations/has_one_associations_test.rb43
-rw-r--r--activerecord/test/cases/base_test.rb5
-rw-r--r--activerecord/test/cases/helper.rb3
-rw-r--r--activerecord/test/cases/identity_map_test.rb8
-rw-r--r--activerecord/test/cases/primary_keys_test.rb16
-rw-r--r--activerecord/test/cases/reflection_test.rb4
-rw-r--r--activerecord/test/cases/serialization_test.rb6
-rw-r--r--activerecord/test/fixtures/developers.yml2
-rw-r--r--activerecord/test/models/company.rb1
-rwxr-xr-xactiveresource/Rakefile2
-rw-r--r--activeresource/test/cases/format_test.rb6
-rw-r--r--activesupport/lib/active_support/testing/performance/ruby.rb34
-rw-r--r--activesupport/lib/active_support/testing/performance/ruby/yarv.rb48
-rw-r--r--activesupport/lib/active_support/xml_mini/jdom.rb8
-rw-r--r--railties/lib/rails/code_statistics.rb30
-rw-r--r--railties/lib/rails/generators/actions.rb2
-rw-r--r--railties/lib/rails/generators/app_base.rb2
-rw-r--r--railties/lib/rails/generators/base.rb8
-rw-r--r--railties/lib/rails/generators/generated_attribute.rb4
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/application.rb5
-rw-r--r--railties/lib/rails/rubyprof_ext.rb2
-rw-r--r--railties/test/application/assets_test.rb2
-rw-r--r--railties/test/generators/app_generator_test.rb11
56 files changed, 412 insertions, 223 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 1ffb7f32a0..0dafef90ae 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -26,6 +26,8 @@
This is a behavior change, previously the hidden tag had a value of the disabled checkbox.
*Tadas Tamosauskas*
+* `favicon_link_tag` helper will now use the favicon in app/assets by default. *Lucas Caton*
+
## Rails 3.2.0 (January 20, 2012) ##
* Add `config.action_dispatch.default_charset` to configure default charset for ActionDispatch::Response. *Carlos Antonio da Silva*
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index effb6badfc..bb1e704767 100755
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -55,15 +55,15 @@ end
task :lines do
lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
- for file_name in FileList["lib/**/*.rb"]
+ FileList["lib/**/*.rb"].each do |file_name|
next if file_name =~ /vendor/
- f = File.open(file_name)
-
- while line = f.gets
- lines += 1
- next if line =~ /^\s*$/
- next if line =~ /^\s*#/
- codelines += 1
+ File.open(file_name, 'r') do |f|
+ while line = f.gets
+ lines += 1
+ next if line =~ /^\s*$/
+ next if line =~ /^\s*#/
+ codelines += 1
+ end
end
puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index f4eaa2fd1b..a0c54dbd84 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -40,7 +40,6 @@ module ActionController
autoload :Integration, 'action_controller/deprecated/integration_test'
autoload :IntegrationTest, 'action_controller/deprecated/integration_test'
autoload :PerformanceTest, 'action_controller/deprecated/performance_test'
- autoload :UrlWriter, 'action_controller/deprecated'
autoload :Routing, 'action_controller/deprecated'
autoload :TestCase, 'action_controller/test_case'
autoload :TemplateAssertions, 'action_controller/test_case'
diff --git a/actionpack/lib/action_dispatch/http/mime_types.rb b/actionpack/lib/action_dispatch/http/mime_types.rb
index 3da4f91051..a6b3aee5e7 100644
--- a/actionpack/lib/action_dispatch/http/mime_types.rb
+++ b/actionpack/lib/action_dispatch/http/mime_types.rb
@@ -9,7 +9,7 @@ Mime::Type.register "text/calendar", :ics
Mime::Type.register "text/csv", :csv
Mime::Type.register "image/png", :png, [], %w(png)
-Mime::Type.register "image/jpeg", :jpeg, [], %w(jpg jpeg jpe)
+Mime::Type.register "image/jpeg", :jpeg, [], %w(jpg jpeg jpe pjpeg)
Mime::Type.register "image/gif", :gif, [], %w(gif)
Mime::Type.register "image/bmp", :bmp, [], %w(bmp)
Mime::Type.register "image/tiff", :tiff, [], %w(tif tiff)
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index e2d7a29079..a17a39bed3 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -491,7 +491,7 @@ module ActionDispatch
map_method(:put, args, &block)
end
- # Define a route that only recognizes HTTP PUT.
+ # Define a route that only recognizes HTTP DELETE.
# For supported arguments, see <tt>Base#match</tt>.
#
# Example:
diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb
index 4d963803e6..33796008bd 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb
@@ -417,8 +417,8 @@ module ActionDispatch
deliveries = ActionMailer::Base.deliveries
assert !deliveries.empty?, "No e-mail in delivery list"
- for delivery in deliveries
- for part in (delivery.parts.empty? ? [delivery] : delivery.parts)
+ deliveries.each do |delivery|
+ (delivery.parts.empty? ? [delivery] : delivery.parts).each do |part|
if part["Content-Type"].to_s =~ /^text\/html\W/
root = HTML::Document.new(part.body.to_s).root
assert_select root, ":root", &block
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 280e51549e..40a950c644 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -234,7 +234,7 @@ module ActionView
#
# generates
#
- # <link href="/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />
+ # <link href="/assets/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />
#
# You may specify a different file in the first argument:
#
@@ -252,7 +252,7 @@ module ActionView
#
# <%= favicon_link_tag 'mb-icon.png', :rel => 'apple-touch-icon', :type => 'image/png' %>
#
- def favicon_link_tag(source='/favicon.ico', options={})
+ def favicon_link_tag(source='favicon.ico', options={})
tag('link', {
:rel => 'shortcut icon',
:type => 'image/vnd.microsoft.icon',
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index ea71889519..2d37923825 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -508,7 +508,7 @@ module ActionView
# Returns a select tag with options for each of the days 1 through 31 with the current day selected.
# The <tt>date</tt> can also be substituted for a day number.
- # If you want to display days with a leading zero set the <tt>:use_two_digit_numbers</tt> key in +options+ to true.
+ # If you want to display days with a leading zero set the <tt>:use_two_digit_numbers</tt> key in +options+ to true.
# Override the field name using the <tt>:field_name</tt> option, 'day' by default.
#
# ==== Examples
@@ -854,7 +854,7 @@ module ActionView
end
def translated_date_order
- date_order = I18n.translate(:'date.order', :locale => @options[:locale]) || []
+ date_order = I18n.translate(:'date.order', :locale => @options[:locale], :default => [])
forbidden_elements = date_order - [:year, :month, :day]
if forbidden_elements.any?
@@ -990,18 +990,12 @@ module ActionView
# Returns the separator for a given datetime component.
def separator(type)
case type
- when :year
- @options[:discard_year] ? "" : @options[:date_separator]
- when :month
- @options[:discard_month] ? "" : @options[:date_separator]
- when :day
- @options[:discard_day] ? "" : @options[:date_separator]
+ when :year, :month, :day
+ @options[:"discard_#{type}"] ? "" : @options[:date_separator]
when :hour
(@options[:discard_year] && @options[:discard_day]) ? "" : @options[:datetime_separator]
- when :minute
- @options[:discard_minute] ? "" : @options[:time_separator]
- when :second
- @options[:include_seconds] ? @options[:time_separator] : ""
+ when :minute, :second
+ @options[:"discard_#{type}"] ? "" : @options[:time_separator]
end
end
end
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index c8811e3b10..c4cdfef4a2 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -334,7 +334,7 @@ module ActionView
end.join("\n").html_safe
end
- # Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning
+ # Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning
# the result of a call to the +value_method+ as the option value and the +text_method+ as the option text.
# Example:
# options_from_collection_for_select(@people, 'id', 'name')
@@ -418,9 +418,9 @@ module ActionView
# wrap the output in an appropriate <tt><select></tt> tag.
def option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)
collection.map do |group|
- group_label_string = eval("group.#{group_label_method}")
+ group_label_string = group.send(group_label_method)
"<optgroup label=\"#{ERB::Util.html_escape(group_label_string)}\">" +
- options_from_collection_for_select(eval("group.#{group_method}"), option_key_method, option_value_method, selected_key) +
+ options_from_collection_for_select(group.send(group_method), option_key_method, option_value_method, selected_key) +
'</optgroup>'
end.join.html_safe
end
diff --git a/actionpack/lib/action_view/helpers/tags/collection_select.rb b/actionpack/lib/action_view/helpers/tags/collection_select.rb
index f84140d8d0..ec78e6e5f9 100644
--- a/actionpack/lib/action_view/helpers/tags/collection_select.rb
+++ b/actionpack/lib/action_view/helpers/tags/collection_select.rb
@@ -12,9 +12,14 @@ module ActionView
end
def render
- selected_value = @options.has_key?(:selected) ? @options[:selected] : value(@object)
+ option_tags_options = {
+ :selected => @options.fetch(:selected) { value(@object) },
+ :disabled => @options[:disabled]
+ }
+
select_content_tag(
- options_from_collection_for_select(@collection, @value_method, @text_method, :selected => selected_value, :disabled => @options[:disabled]), @options, @html_options
+ options_from_collection_for_select(@collection, @value_method, @text_method, option_tags_options),
+ @options, @html_options
)
end
end
diff --git a/actionpack/lib/action_view/helpers/tags/select.rb b/actionpack/lib/action_view/helpers/tags/select.rb
index 02b790db4e..53a108b7e6 100644
--- a/actionpack/lib/action_view/helpers/tags/select.rb
+++ b/actionpack/lib/action_view/helpers/tags/select.rb
@@ -11,21 +11,30 @@ module ActionView
end
def render
- selected_value = @options.has_key?(:selected) ? @options[:selected] : value(@object)
+ option_tags_options = {
+ :selected => @options.fetch(:selected) { value(@object) },
+ :disabled => @options[:disabled]
+ }
- # Grouped choices look like this:
- #
- # [nil, []]
- # { nil => [] }
- #
- if !@choices.empty? && @choices.first.respond_to?(:last) && Array === @choices.first.last
- option_tags = grouped_options_for_select(@choices, :selected => selected_value, :disabled => @options[:disabled])
+ option_tags = if grouped_choices?
+ grouped_options_for_select(@choices, option_tags_options)
else
- option_tags = options_for_select(@choices, :selected => selected_value, :disabled => @options[:disabled])
+ options_for_select(@choices, option_tags_options)
end
select_content_tag(option_tags, @options, @html_options)
end
+
+ private
+
+ # Grouped choices look like this:
+ #
+ # [nil, []]
+ # { nil => [] }
+ #
+ def grouped_choices?
+ !@choices.empty? && @choices.first.respond_to?(:last) && Array === @choices.first.last
+ end
end
end
end
diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb
index e231aade01..3033294883 100644
--- a/actionpack/lib/action_view/renderer/partial_renderer.rb
+++ b/actionpack/lib/action_view/renderer/partial_renderer.rb
@@ -85,8 +85,7 @@ module ActionView
# == Rendering objects that respond to `to_partial_path`
#
# Instead of explicitly naming the location of a partial, you can also let PartialRenderer do the work
- # and pick the proper path by checking `to_proper_path` method. If the object passed to render is a collection,
- # all objects must return the same path.
+ # and pick the proper path by checking `to_partial_path` method.
#
# # @account.to_partial_path returns 'accounts/account', so it can be used to replace:
# # <%= render :partial => "accounts/account", :locals => { :account => @account} %>
diff --git a/actionpack/test/fixtures/developers.yml b/actionpack/test/fixtures/developers.yml
index 308bf75de2..3656564f63 100644
--- a/actionpack/test/fixtures/developers.yml
+++ b/actionpack/test/fixtures/developers.yml
@@ -8,7 +8,7 @@ jamis:
name: Jamis
salary: 150000
-<% for digit in 3..10 %>
+<% (3..10).each do |digit| %>
dev_<%= digit %>:
id: <%= digit %>
name: fixture_<%= digit %>
diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb
index 3422a5efbd..90c2ca7a3d 100644
--- a/actionpack/test/template/asset_tag_helper_test.rb
+++ b/actionpack/test/template/asset_tag_helper_test.rb
@@ -168,7 +168,7 @@ class AssetTagHelperTest < ActionView::TestCase
}
FaviconLinkToTag = {
- %(favicon_link_tag) => %(<link href="/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />),
+ %(favicon_link_tag) => %(<link href="/images/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />),
%(favicon_link_tag 'favicon.ico') => %(<link href="/images/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />),
%(favicon_link_tag 'favicon.ico', :rel => 'foo') => %(<link href="/images/favicon.ico" rel="foo" type="image/vnd.microsoft.icon" />),
%(favicon_link_tag 'favicon.ico', :rel => 'foo', :type => 'bar') => %(<link href="/images/favicon.ico" rel="foo" type="bar" />),
diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb
index ef3d7d97ee..82b62e64f3 100644
--- a/actionpack/test/template/date_helper_i18n_test.rb
+++ b/actionpack/test/template/date_helper_i18n_test.rb
@@ -103,7 +103,7 @@ class DateHelperSelectTagsI18nTests < ActiveSupport::TestCase
I18n.expects(:translate).with(('datetime.prompts.' + key.to_s).to_sym, :locale => 'en').returns prompt
end
- I18n.expects(:translate).with(:'date.order', :locale => 'en').returns [:year, :month, :day]
+ I18n.expects(:translate).with(:'date.order', :locale => 'en', :default => []).returns [:year, :month, :day]
datetime_select('post', 'updated_at', :locale => 'en', :include_seconds => true, :prompt => true)
end
@@ -115,12 +115,12 @@ class DateHelperSelectTagsI18nTests < ActiveSupport::TestCase
end
def test_date_or_time_select_given_no_order_options_translates_order
- I18n.expects(:translate).with(:'date.order', :locale => 'en').returns [:year, :month, :day]
+ I18n.expects(:translate).with(:'date.order', :locale => 'en', :default => []).returns [:year, :month, :day]
datetime_select('post', 'updated_at', :locale => 'en')
end
def test_date_or_time_select_given_invalid_order
- I18n.expects(:translate).with(:'date.order', :locale => 'en').returns [:invalid, :month, :day]
+ I18n.expects(:translate).with(:'date.order', :locale => 'en', :default => []).returns [:invalid, :month, :day]
assert_raise StandardError do
datetime_select('post', 'updated_at', :locale => 'en')
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index b45aba6bb1..e9e97f5d62 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,24 @@
## Rails 4.0.0 (unreleased) ##
+* Added deprecation for the `:dependent => :restrict` association option.
+
+ Please note:
+
+ * Up until now `has_many` and `has_one`, `:dependent => :restrict`
+ option raised a `DeleteRestrictionError` at the time of destroying
+ the object. Instead, it will add an error on the model.
+
+ * To fix this warning, make sure your code isn't relying on a
+ `DeleteRestrictionError` and then add
+ `config.active_record.dependent_restrict_raises = false` to your
+ application config.
+
+ * New rails application would be generated with the
+ `config.active_record.dependent_restrict_raises = false` in the
+ application config.
+
+ *Manoj Kumar*
+
* Added `create_join_table` migration helper to create HABTM join tables
create_join_table :products, :categories
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index d769a73dba..98020ad3ab 100755
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -187,15 +187,15 @@ end
task :lines do
lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
- for file_name in FileList["lib/active_record/**/*.rb"]
+ FileList["lib/active_record/**/*.rb"].each do |file_name|
next if file_name =~ /vendor/
- f = File.open(file_name)
-
- while line = f.gets
- lines += 1
- next if line =~ /^\s*$/
- next if line =~ /^\s*#/
- codelines += 1
+ File.open(file_name, 'r') do |f|
+ while line = f.gets
+ lines += 1
+ next if line =~ /^\s*$/
+ next if line =~ /^\s*#/
+ codelines += 1
+ end
end
puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 58725246c8..958821add6 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1097,8 +1097,8 @@ module ActiveRecord
# alongside this object by calling their +destroy+ method. If set to <tt>:delete_all</tt> all associated
# objects are deleted *without* calling their +destroy+ method. If set to <tt>:nullify</tt> all associated
# objects' foreign keys are set to +NULL+ *without* calling their +save+ callbacks. If set to
- # <tt>:restrict</tt> this object raises an <tt>ActiveRecord::DeleteRestrictionError</tt> exception and
- # cannot be deleted if it has any associated objects.
+ # <tt>:restrict</tt> an error will be added to the object, preventing its deletion, if any associated
+ # objects are present.
#
# If using with the <tt>:through</tt> option, the association on the join model must be
# a +belongs_to+, and the records which get deleted are the join records, rather than
@@ -1251,8 +1251,8 @@ module ActiveRecord
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
# If set to <tt>:nullify</tt>, the associated object's foreign key is set to +NULL+.
- # Also, association is assigned. If set to <tt>:restrict</tt> this object raises an
- # <tt>ActiveRecord::DeleteRestrictionError</tt> exception and cannot be deleted if it has any associated object.
+ # If set to <tt>:restrict</tt>, an error will be added to the object, preventing its deletion, if an
+ # associated object is present.
# [:foreign_key]
# Specify the foreign key used for the association. By default this is guessed to be the name
# of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_one+ association
diff --git a/activerecord/lib/active_record/associations/builder/association.rb b/activerecord/lib/active_record/associations/builder/association.rb
index 6e2e5f9de0..666926ff51 100644
--- a/activerecord/lib/active_record/associations/builder/association.rb
+++ b/activerecord/lib/active_record/associations/builder/association.rb
@@ -51,5 +51,34 @@ module ActiveRecord::Associations::Builder
association(name).writer(value)
end
end
- end
+
+ def dependent_restrict_raises?
+ ActiveRecord::Base.dependent_restrict_raises == true
+ end
+
+ def dependent_restrict_deprecation_warning
+ if dependent_restrict_raises?
+ msg = "In the next release, `:dependent => :restrict` will not raise a `DeleteRestrictionError`. "\
+ "Instead, it will add an error on the model. To fix this warning, make sure your code " \
+ "isn't relying on a `DeleteRestrictionError` and then add " \
+ "`config.active_record.dependent_restrict_raises = false` to your application config."
+ ActiveSupport::Deprecation.warn msg
+ end
+ end
+
+ def define_restrict_dependency_method
+ name = self.name
+ mixin.redefine_method(dependency_method_name) do
+ # has_many or has_one associations
+ if send(name).respond_to?(:exists?) ? send(name).exists? : !send(name).nil?
+ if dependent_restrict_raises?
+ raise ActiveRecord::DeleteRestrictionError.new(name)
+ else
+ errors.add(:base, :restrict_dependent_destroy, :model => name.to_s.singularize)
+ return false
+ end
+ end
+ end
+ end
+ end
end
diff --git a/activerecord/lib/active_record/associations/builder/has_many.rb b/activerecord/lib/active_record/associations/builder/has_many.rb
index fc6799fb15..9ddfd433e4 100644
--- a/activerecord/lib/active_record/associations/builder/has_many.rb
+++ b/activerecord/lib/active_record/associations/builder/has_many.rb
@@ -21,6 +21,7 @@ module ActiveRecord::Associations::Builder
":nullify or :restrict (#{options[:dependent].inspect})"
end
+ dependent_restrict_deprecation_warning if options[:dependent] == :restrict
send("define_#{options[:dependent]}_dependency_method")
model.before_destroy dependency_method_name
end
@@ -52,13 +53,6 @@ module ActiveRecord::Associations::Builder
end
end
- def define_restrict_dependency_method
- name = self.name
- mixin.redefine_method(dependency_method_name) do
- raise ActiveRecord::DeleteRestrictionError.new(name) unless send(name).empty?
- end
- end
-
def dependency_method_name
"has_many_dependent_for_#{name}"
end
diff --git a/activerecord/lib/active_record/associations/builder/has_one.rb b/activerecord/lib/active_record/associations/builder/has_one.rb
index 7a6cd3890f..bc8a212bee 100644
--- a/activerecord/lib/active_record/associations/builder/has_one.rb
+++ b/activerecord/lib/active_record/associations/builder/has_one.rb
@@ -34,15 +34,12 @@ module ActiveRecord::Associations::Builder
":nullify or :restrict (#{options[:dependent].inspect})"
end
+ dependent_restrict_deprecation_warning if options[:dependent] == :restrict
send("define_#{options[:dependent]}_dependency_method")
model.before_destroy dependency_method_name
end
end
- def dependency_method_name
- "has_one_dependent_#{options[:dependent]}_for_#{name}"
- end
-
def define_destroy_dependency_method
name = self.name
mixin.redefine_method(dependency_method_name) do
@@ -52,11 +49,8 @@ module ActiveRecord::Associations::Builder
alias :define_delete_dependency_method :define_destroy_dependency_method
alias :define_nullify_dependency_method :define_destroy_dependency_method
- def define_restrict_dependency_method
- name = self.name
- mixin.redefine_method(dependency_method_name) do
- raise ActiveRecord::DeleteRestrictionError.new(name) unless send(name).nil?
- end
+ def dependency_method_name
+ "has_one_dependent_#{options[:dependent]}_for_#{name}"
end
end
end
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 7aed64d48c..b2136605e1 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -58,7 +58,7 @@ module ActiveRecord
end
end
- relation.uniq.pluck(column)
+ relation.pluck(column)
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb
index 27ff13ad89..52f09efd53 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb
@@ -69,7 +69,7 @@ module ActiveRecord
result =
if @query_cache[sql].key?(binds)
ActiveSupport::Notifications.instrument("sql.active_record",
- :sql => sql, :name => "CACHE", :connection_id => object_id)
+ :sql => sql, :binds => binds, :name => "CACHE", :connection_id => object_id)
@query_cache[sql][binds]
else
@query_cache[sql][binds] = yield
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 201c05d8f5..9d9dbcc355 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -505,7 +505,7 @@ module ActiveRecord
execute_and_free("SHOW CREATE TABLE #{quote_table_name(table)}", 'SCHEMA') do |result|
create_table = each_hash(result).first[:"Create Table"]
if create_table.to_s =~ /PRIMARY KEY\s+\((.+)\)/
- keys = $1.split(",").map { |key| key.gsub(/`/, "") }
+ keys = $1.split(",").map { |key| key.gsub(/[`"]/, "") }
keys.length == 1 ? [keys.first, nil] : nil
else
nil
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index a774af6024..a2ce620354 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -72,6 +72,16 @@ module ActiveRecord
# The connection handler
config_attribute :connection_handler
self.connection_handler = ConnectionAdapters::ConnectionHandler.new
+
+ ##
+ # :singleton-method:
+ # Specifies wether or not has_many or has_one association option
+ # :dependent => :restrict raises an exception. If set to true, the
+ # ActiveRecord::DeleteRestrictionError exception will be raised
+ # along with a DEPRECATION WARNING. If set to false, an error would
+ # be added to the model instead.
+ config_attribute :dependent_restrict_raises, :global => true
+ self.dependent_restrict_raises = true
end
module ClassMethods
diff --git a/activerecord/lib/active_record/dynamic_finder_match.rb b/activerecord/lib/active_record/dynamic_finder_match.rb
index b309df9b1b..38dbbef5fc 100644
--- a/activerecord/lib/active_record/dynamic_finder_match.rb
+++ b/activerecord/lib/active_record/dynamic_finder_match.rb
@@ -6,33 +6,23 @@ module ActiveRecord
#
class DynamicFinderMatch
def self.match(method)
- finder = :first
- bang = false
- instantiator = nil
-
- case method.to_s
- when /^find_(all_|last_)?by_([_a-zA-Z]\w*)$/
- finder = :last if $1 == 'last_'
- finder = :all if $1 == 'all_'
- names = $2
- when /^find_by_([_a-zA-Z]\w*)\!$/
- bang = true
- names = $1
- when /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/
- instantiator = $1 == 'initialize' ? :new : :create
- names = $2
- else
- return nil
+ method = method.to_s
+ klass = [FindBy, FindByBang, FindOrInitializeCreateBy].find do |_klass|
+ _klass.matches?(method)
end
+ klass.new(method) if klass
+ end
- new(finder, instantiator, bang, names.split('_and_'))
+ def self.matches?(method)
+ method =~ self::METHOD_PATTERN
end
- def initialize(finder, instantiator, bang, attribute_names)
- @finder = finder
- @instantiator = instantiator
- @bang = bang
- @attribute_names = attribute_names
+ def initialize(method)
+ @finder = :first
+ @instantiator = nil
+ match_data = method.match(self.class::METHOD_PATTERN)
+ @attribute_names = match_data[-1].split("_and_")
+ initialize_from_match_data(match_data)
end
attr_reader :finder, :attribute_names, :instantiator
@@ -41,16 +31,54 @@ module ActiveRecord
@finder && !@instantiator
end
+ def creator?
+ @finder == :first && @instantiator == :create
+ end
+
def instantiator?
- @finder == :first && @instantiator
+ @instantiator
end
- def creator?
- @finder == :first && @instantiator == :create
+ def bang?
+ false
+ end
+
+ def valid_arguments?(arguments)
+ arguments.size >= @attribute_names.size
end
+ private
+
+ def initialize_from_match_data(match_data)
+ end
+ end
+
+ class FindBy < DynamicFinderMatch
+ METHOD_PATTERN = /^find_(all_|last_)?by_([_a-zA-Z]\w*)$/
+
+ def initialize_from_match_data(match_data)
+ @finder = :last if match_data[1] == 'last_'
+ @finder = :all if match_data[1] == 'all_'
+ end
+ end
+
+ class FindByBang < DynamicFinderMatch
+ METHOD_PATTERN = /^find_by_([_a-zA-Z]\w*)\!$/
+
def bang?
- @bang
+ true
+ end
+ end
+
+ class FindOrInitializeCreateBy < DynamicFinderMatch
+ METHOD_PATTERN = /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/
+
+ def initialize_from_match_data(match_data)
+ @instantiator = match_data[1] == 'initialize' ? :new : :create
+ end
+
+ def valid_arguments?(arguments)
+ arguments.size == 1 && arguments.first.is_a?(Hash) || super
end
end
end
diff --git a/activerecord/lib/active_record/dynamic_matchers.rb b/activerecord/lib/active_record/dynamic_matchers.rb
index b6b8e24436..60ce3dd4f1 100644
--- a/activerecord/lib/active_record/dynamic_matchers.rb
+++ b/activerecord/lib/active_record/dynamic_matchers.rb
@@ -25,7 +25,7 @@ module ActiveRecord
if match = (DynamicFinderMatch.match(method_id) || DynamicScopeMatch.match(method_id))
attribute_names = match.attribute_names
super unless all_attributes_exists?(attribute_names)
- if !(match.is_a?(DynamicFinderMatch) && match.instantiator? && arguments.first.is_a?(Hash)) && arguments.size < attribute_names.size
+ unless match.valid_arguments?(arguments)
method_trace = "#{__FILE__}:#{__LINE__}:in `#{method_id}'"
backtrace = [method_trace] + caller
raise ArgumentError, "wrong number of arguments (#{arguments.size} for #{attribute_names.size})", backtrace
diff --git a/activerecord/lib/active_record/dynamic_scope_match.rb b/activerecord/lib/active_record/dynamic_scope_match.rb
index c832e927d6..a502155aac 100644
--- a/activerecord/lib/active_record/dynamic_scope_match.rb
+++ b/activerecord/lib/active_record/dynamic_scope_match.rb
@@ -19,5 +19,9 @@ module ActiveRecord
attr_reader :scope, :attribute_names
alias :scope? :scope
+
+ def valid_arguments?(arguments)
+ arguments.size >= @attribute_names.size
+ end
end
end
diff --git a/activerecord/lib/active_record/locale/en.yml b/activerecord/lib/active_record/locale/en.yml
index 44328f63b6..8892f7ef2f 100644
--- a/activerecord/lib/active_record/locale/en.yml
+++ b/activerecord/lib/active_record/locale/en.yml
@@ -10,6 +10,7 @@ en:
messages:
taken: "has already been taken"
record_invalid: "Validation failed: %{errors}"
+ restrict_dependent_destroy: "Cannot delete record because dependent %{model} exists"
# Append your own errors here or at the model/attributes scope.
# You can define own errors for models or model attributes.
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index bf9b4bf1c9..6bf3050af9 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -333,7 +333,7 @@ module ActiveRecord
def select_for_count
if @select_values.present?
select = @select_values.join(", ")
- select if select !~ /(,|\*)/
+ select if select !~ /[,*]/
end
end
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index f1ac421a50..b54a167dc3 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -318,7 +318,8 @@ module ActiveRecord
def find_one(id)
id = id.id if ActiveRecord::Base === id
- if IdentityMap.enabled? && where_values.blank? &&
+ if IdentityMap.enabled? &&
+ (where_values.blank? || contains_only_subclass_constraint?(where_values)) &&
limit_value.blank? && order_values.blank? &&
includes_values.blank? && preload_values.blank? &&
readonly_value.nil? && joins_values.blank? &&
@@ -394,5 +395,11 @@ module ActiveRecord
def using_limitable_reflections?(reflections)
reflections.none? { |r| r.collection? }
end
+
+ def contains_only_subclass_constraint?(where_values)
+ where_values.length == 1 &&
+ !where_values[0].left.nil? && where_values[0].left.relation.name == table_name &&
+ !where_values[0].right.nil? && where_values[0].right.length == 1 && where_values[0].right[0] == @klass.name
+ end
end
end
diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb
index 3a741ba600..7fd5d76ba5 100644
--- a/activerecord/lib/active_record/validations/uniqueness.rb
+++ b/activerecord/lib/active_record/validations/uniqueness.rb
@@ -57,8 +57,7 @@ module ActiveRecord
def build_relation(klass, table, attribute, value) #:nodoc:
reflection = klass.reflect_on_association(attribute)
- column = nil
- if(reflection)
+ if reflection
column = klass.columns_hash[reflection.foreign_key]
attribute = reflection.foreign_key
value = value.attributes[reflection.primary_key_column.name]
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index f1a341437f..ab1e821aab 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1140,16 +1140,42 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_nil companies(:leetsoft).reload.client_of
assert_nil companies(:jadedpixel).reload.client_of
-
assert_equal num_accounts, Account.count
end
def test_restrict
- firm = RestrictedFirm.new(:name => 'restrict')
- firm.save!
+ option_before = ActiveRecord::Base.dependent_restrict_raises
+ ActiveRecord::Base.dependent_restrict_raises = true
+
+ firm = RestrictedFirm.create!(:name => 'restrict')
firm.companies.create(:name => 'child')
+
assert !firm.companies.empty?
assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy }
+ assert RestrictedFirm.exists?(:name => 'restrict')
+ assert firm.companies.exists?(:name => 'child')
+ ensure
+ ActiveRecord::Base.dependent_restrict_raises = option_before
+ end
+
+ def test_restrict_when_dependent_restrict_raises_config_set_to_false
+ option_before = ActiveRecord::Base.dependent_restrict_raises
+ ActiveRecord::Base.dependent_restrict_raises = false
+
+ firm = RestrictedFirm.create!(:name => 'restrict')
+ firm.companies.create(:name => 'child')
+
+ assert !firm.companies.empty?
+
+ firm.destroy
+
+ assert !firm.errors.empty?
+
+ assert_equal "Cannot delete record because dependent company exists", firm.errors[:base].first
+ assert RestrictedFirm.exists?(:name => 'restrict')
+ assert firm.companies.exists?(:name => 'child')
+ ensure
+ ActiveRecord::Base.dependent_restrict_raises = option_before
end
def test_included_in_collection
@@ -1253,6 +1279,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert company.clients_using_sql.loaded?
end
+ def test_get_ids_for_ordered_association
+ assert_equal [companies(:second_client).id, companies(:first_client).id], companies(:first_firm).clients_ordered_by_name_ids
+ end
+
def test_assign_ids_ignoring_blanks
firm = Firm.create!(:name => 'Apple')
firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
@@ -1401,29 +1431,29 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
firm.clients.last
end
end
-
+
def test_custom_primary_key_on_new_record_should_fetch_with_query
author = Author.new(:name => "David")
assert !author.essays.loaded?
-
- assert_queries 1 do
+
+ assert_queries 1 do
assert_equal 1, author.essays.size
end
-
+
assert_equal author.essays, Essay.find_all_by_writer_id("David")
-
+
end
-
+
def test_has_many_custom_primary_key
david = authors(:david)
assert_equal david.essays, Essay.find_all_by_writer_id("David")
end
-
+
def test_blank_custom_primary_key_on_new_record_should_not_run_queries
author = Author.new
assert !author.essays.loaded?
-
- assert_queries 0 do
+
+ assert_queries 0 do
assert_equal 0, author.essays.size
end
end
@@ -1649,4 +1679,16 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal [bulb2], car.bulbs
assert_equal [bulb2], car.reload.bulbs
end
+
+ def test_building_has_many_association_with_restrict_dependency
+ option_before = ActiveRecord::Base.dependent_restrict_raises
+ ActiveRecord::Base.dependent_restrict_raises = true
+
+ klass = Class.new(ActiveRecord::Base)
+
+ assert_deprecated { klass.has_many :companies, :dependent => :restrict }
+ assert_not_deprecated { klass.has_many :companies }
+ ensure
+ ActiveRecord::Base.dependent_restrict_raises = option_before
+ end
end
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index 26931e3e85..37be6a279d 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -157,11 +157,38 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
end
def test_dependence_with_restrict
- firm = RestrictedFirm.new(:name => 'restrict')
- firm.save!
+ option_before = ActiveRecord::Base.dependent_restrict_raises
+ ActiveRecord::Base.dependent_restrict_raises = true
+
+ firm = RestrictedFirm.create!(:name => 'restrict')
firm.create_account(:credit_limit => 10)
+
assert_not_nil firm.account
+
assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy }
+ assert RestrictedFirm.exists?(:name => 'restrict')
+ assert firm.account.present?
+ ensure
+ ActiveRecord::Base.dependent_restrict_raises = option_before
+ end
+
+ def test_dependence_with_restrict_with_dependent_restrict_raises_config_set_to_false
+ option_before = ActiveRecord::Base.dependent_restrict_raises
+ ActiveRecord::Base.dependent_restrict_raises = false
+
+ firm = RestrictedFirm.create!(:name => 'restrict')
+ firm.create_account(:credit_limit => 10)
+
+ assert_not_nil firm.account
+
+ firm.destroy
+
+ assert !firm.errors.empty?
+ assert_equal "Cannot delete record because dependent account exists", firm.errors[:base].first
+ assert RestrictedFirm.exists?(:name => 'restrict')
+ assert firm.account.present?
+ ensure
+ ActiveRecord::Base.dependent_restrict_raises = option_before
end
def test_successful_build_association
@@ -456,4 +483,16 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
assert_equal car.id, bulb.attributes_after_initialize['car_id']
end
+
+ def test_building_has_one_association_with_dependent_restrict
+ option_before = ActiveRecord::Base.dependent_restrict_raises
+ ActiveRecord::Base.dependent_restrict_raises = true
+
+ klass = Class.new(ActiveRecord::Base)
+
+ assert_deprecated { klass.has_one :account, :dependent => :restrict }
+ assert_not_deprecated { klass.has_one :account }
+ ensure
+ ActiveRecord::Base.dependent_restrict_raises = option_before
+ end
end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 59d786622e..6c3e4fc6d0 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1104,7 +1104,10 @@ class BasicsTest < ActiveRecord::TestCase
# TODO: extend defaults tests to other databases!
if current_adapter?(:PostgreSQLAdapter)
def test_default
+ tz = Default.default_timezone
+ Default.default_timezone = :local
default = Default.new
+ Default.default_timezone = tz
# fixed dates / times
assert_equal Date.new(2004, 1, 1), default.fixed_date
@@ -1579,7 +1582,7 @@ class BasicsTest < ActiveRecord::TestCase
Developer.find(:all)
end
assert developers.size >= 2
- for i in 1...developers.size
+ (1...developers.size).each do |i|
assert developers[i-1].salary >= developers[i].salary
end
end
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index b4598ab32a..359cabd016 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -22,6 +22,9 @@ ActiveSupport::Deprecation.debug = true
# Enable Identity Map only when ENV['IM'] is set to "true"
ActiveRecord::IdentityMap.enabled = (ENV['IM'] == "true")
+# Avoid deprecation warning setting dependent_restric_raises to false. The default is true
+ActiveRecord::Base.dependent_restrict_raises = false
+
# Connect to the database
ARTest.connect
diff --git a/activerecord/test/cases/identity_map_test.rb b/activerecord/test/cases/identity_map_test.rb
index 3efc8bf559..0d031d433c 100644
--- a/activerecord/test/cases/identity_map_test.rb
+++ b/activerecord/test/cases/identity_map_test.rb
@@ -162,6 +162,14 @@ class IdentityMapTest < ActiveRecord::TestCase
c2 = Comment.find(c.id)
assert_same(c1, c2)
end
+
+ def test_queries_are_not_executed_when_finding_inherited_class_by_id
+ c = comments(:sub_special_comment)
+ SubSpecialComment.find(c.id)
+ assert_no_queries do
+ SubSpecialComment.find(c.id)
+ end
+ end
##############################################################################
# Tests checking dirty attribute behavior with IM #
diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb
index b4d1a631fa..e6e50a4cd4 100644
--- a/activerecord/test/cases/primary_keys_test.rb
+++ b/activerecord/test/cases/primary_keys_test.rb
@@ -200,3 +200,19 @@ class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase
assert_equal 'foo', model.primary_key
end
end
+
+if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ class PrimaryKeyWithAnsiQuotesTest < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false
+
+ def test_primaery_key_method_with_ansi_quotes
+ con = ActiveRecord::Base.connection
+ con.execute("SET SESSION sql_mode='ANSI_QUOTES'")
+ assert_equal "id", con.primary_key("topics")
+ ensure
+ con.reconnect!
+ end
+
+ end
+end
+
diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb
index 297fb56570..16f05f2198 100644
--- a/activerecord/test/cases/reflection_test.rb
+++ b/activerecord/test/cases/reflection_test.rb
@@ -189,8 +189,8 @@ class ReflectionTest < ActiveRecord::TestCase
def test_reflection_of_all_associations
# FIXME these assertions bust a lot
- assert_equal 38, Firm.reflect_on_all_associations.size
- assert_equal 28, Firm.reflect_on_all_associations(:has_many).size
+ assert_equal 39, Firm.reflect_on_all_associations.size
+ assert_equal 29, Firm.reflect_on_all_associations(:has_many).size
assert_equal 10, Firm.reflect_on_all_associations(:has_one).size
assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
end
diff --git a/activerecord/test/cases/serialization_test.rb b/activerecord/test/cases/serialization_test.rb
index 31ba99a8ff..a4c065e667 100644
--- a/activerecord/test/cases/serialization_test.rb
+++ b/activerecord/test/cases/serialization_test.rb
@@ -25,7 +25,7 @@ class SerializationTest < ActiveRecord::TestCase
end
def test_serialize_should_be_reversible
- for format in FORMATS
+ FORMATS.each do |format|
@serialized = Contact.new.send("to_#{format}")
contact = Contact.new.send("from_#{format}", @serialized)
@@ -34,7 +34,7 @@ class SerializationTest < ActiveRecord::TestCase
end
def test_serialize_should_allow_attribute_only_filtering
- for format in FORMATS
+ FORMATS.each do |format|
@serialized = Contact.new(@contact_attributes).send("to_#{format}", :only => [ :age, :name ])
contact = Contact.new.send("from_#{format}", @serialized)
assert_equal @contact_attributes[:name], contact.name, "For #{format}"
@@ -43,7 +43,7 @@ class SerializationTest < ActiveRecord::TestCase
end
def test_serialize_should_allow_attribute_except_filtering
- for format in FORMATS
+ FORMATS.each do |format|
@serialized = Contact.new(@contact_attributes).send("to_#{format}", :except => [ :age, :name ])
contact = Contact.new.send("from_#{format}", @serialized)
assert_nil contact.name, "For #{format}"
diff --git a/activerecord/test/fixtures/developers.yml b/activerecord/test/fixtures/developers.yml
index 308bf75de2..3656564f63 100644
--- a/activerecord/test/fixtures/developers.yml
+++ b/activerecord/test/fixtures/developers.yml
@@ -8,7 +8,7 @@ jamis:
name: Jamis
salary: 150000
-<% for digit in 3..10 %>
+<% (3..10).each do |digit| %>
dev_<%= digit %>:
id: <%= digit %>
name: fixture_<%= digit %>
diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb
index d1a8a82786..fbdfaa2c29 100644
--- a/activerecord/test/models/company.rb
+++ b/activerecord/test/models/company.rb
@@ -45,6 +45,7 @@ class Firm < Company
has_many :unsorted_clients_with_symbol, :class_name => :Client
has_many :clients_sorted_desc, :class_name => "Client", :order => "id DESC"
has_many :clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id"
+ has_many :clients_ordered_by_name, :order => "name", :class_name => "Client"
has_many :unvalidated_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :validate => false
has_many :dependent_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :destroy
has_many :exclusively_dependent_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :delete_all
diff --git a/activeresource/Rakefile b/activeresource/Rakefile
index b1c18ff189..042d9fb0c7 100755
--- a/activeresource/Rakefile
+++ b/activeresource/Rakefile
@@ -33,7 +33,7 @@ end
task :lines do
lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
- for file_name in FileList["lib/active_resource/**/*.rb"]
+ FileList["lib/active_resource/**/*.rb"].each do |file_name|
next if file_name =~ /vendor/
f = File.open(file_name)
diff --git a/activeresource/test/cases/format_test.rb b/activeresource/test/cases/format_test.rb
index 21fdc24832..30342ecc74 100644
--- a/activeresource/test/cases/format_test.rb
+++ b/activeresource/test/cases/format_test.rb
@@ -19,7 +19,7 @@ class FormatTest < ActiveSupport::TestCase
end
def test_formats_on_single_element
- for format in [ :json, :xml ]
+ [ :json, :xml ].each do |format|
using_format(Person, format) do
ActiveResource::HttpMock.respond_to.get "/people/1.#{format}", {'Accept' => ActiveResource::Formats[format].mime_type}, ActiveResource::Formats[format].encode(@david)
assert_equal @david[:name], Person.find(1).name
@@ -28,7 +28,7 @@ class FormatTest < ActiveSupport::TestCase
end
def test_formats_on_collection
- for format in [ :json, :xml ]
+ [ :json, :xml ].each do |format|
using_format(Person, format) do
ActiveResource::HttpMock.respond_to.get "/people.#{format}", {'Accept' => ActiveResource::Formats[format].mime_type}, ActiveResource::Formats[format].encode(@programmers)
remote_programmers = Person.find(:all)
@@ -39,7 +39,7 @@ class FormatTest < ActiveSupport::TestCase
end
def test_formats_on_custom_collection_method
- for format in [ :json, :xml ]
+ [ :json, :xml ].each do |format|
using_format(Person, format) do
ActiveResource::HttpMock.respond_to.get "/people/retrieve.#{format}?name=David", {'Accept' => ActiveResource::Formats[format].mime_type}, ActiveResource::Formats[format].encode([@david])
remote_programmers = Person.get(:retrieve, :name => 'David')
diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb
index 26731c6bd7..b7a34ea279 100644
--- a/activesupport/lib/active_support/testing/performance/ruby.rb
+++ b/activesupport/lib/active_support/testing/performance/ruby.rb
@@ -86,9 +86,12 @@ module ActiveSupport
end
protected
- # overridden by each implementation
def with_gc_stats
+ GC::Profiler.enable
+ GC.start
yield
+ ensure
+ GC::Profiler.disable
end
end
@@ -124,27 +127,42 @@ module ActiveSupport
class Memory < DigitalInformationUnit
Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY)
+
+ # Ruby 1.9 + GCdata patch
+ if GC.respond_to?(:malloc_allocated_size)
+ def measure
+ GC.malloc_allocated_size
+ end
+ end
end
class Objects < Amount
Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS)
+
+ # Ruby 1.9 + GCdata patch
+ if GC.respond_to?(:malloc_allocations)
+ def measure
+ GC.malloc_allocations
+ end
+ end
end
class GcRuns < Amount
Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS)
+
+ def measure
+ GC.count
+ end
end
class GcTime < Time
Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME)
+
+ def measure
+ GC::Profiler.total_time
+ end
end
end
end
end
end
-
-if RUBY_VERSION.between?('1.9.2', '2.0')
- require 'active_support/testing/performance/ruby/yarv'
-else
- $stderr.puts 'Update your ruby interpreter to be able to run benchmarks.'
- exit
-end
diff --git a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb
deleted file mode 100644
index c34d31bf10..0000000000
--- a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-module ActiveSupport
- module Testing
- module Performance
- module Metrics
- class Base
- protected
- def with_gc_stats
- GC::Profiler.enable
- GC.start
- yield
- ensure
- GC::Profiler.disable
- end
- end
-
- class Memory < DigitalInformationUnit
- # Ruby 1.9 + GCdata patch
- if GC.respond_to?(:malloc_allocated_size)
- def measure
- GC.malloc_allocated_size
- end
- end
- end
-
- class Objects < Amount
- # Ruby 1.9 + GCdata patch
- if GC.respond_to?(:malloc_allocations)
- def measure
- GC.malloc_allocations
- end
- end
- end
-
- class GcRuns < Amount
- def measure
- GC.count
- end
- end
-
- class GcTime < Time
- def measure
- GC::Profiler.total_time
- end
- end
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb
index 6c222b83ba..dbb6c71907 100644
--- a/activesupport/lib/active_support/xml_mini/jdom.rb
+++ b/activesupport/lib/active_support/xml_mini/jdom.rb
@@ -71,7 +71,7 @@ module ActiveSupport
child_nodes = element.child_nodes
if child_nodes.length > 0
- for i in 0...child_nodes.length
+ (0...child_nodes.length).each do |i|
child = child_nodes.item(i)
merge_element!(hash, child) unless child.node_type == Node.TEXT_NODE
end
@@ -133,7 +133,7 @@ module ActiveSupport
def get_attributes(element)
attribute_hash = {}
attributes = element.attributes
- for i in 0...attributes.length
+ (0...attributes.length).each do |i|
attribute_hash[CONTENT_KEY] ||= ''
attribute_hash[attributes.item(i).name] = attributes.item(i).value
end
@@ -147,7 +147,7 @@ module ActiveSupport
def texts(element)
texts = []
child_nodes = element.child_nodes
- for i in 0...child_nodes.length
+ (0...child_nodes.length).each do |i|
item = child_nodes.item(i)
if item.node_type == Node.TEXT_NODE
texts << item.get_data
@@ -163,7 +163,7 @@ module ActiveSupport
def empty_content?(element)
text = ''
child_nodes = element.child_nodes
- for i in 0...child_nodes.length
+ (0...child_nodes.length).each do |i|
item = child_nodes.item(i)
if item.node_type == Node.TEXT_NODE
text << item.get_data.strip
diff --git a/railties/lib/rails/code_statistics.rb b/railties/lib/rails/code_statistics.rb
index 435ea83ad8..03538b2422 100644
--- a/railties/lib/rails/code_statistics.rb
+++ b/railties/lib/rails/code_statistics.rb
@@ -37,24 +37,26 @@ class CodeStatistics #:nodoc:
next unless file_name =~ pattern
- f = File.open(directory + "/" + file_name)
comment_started = false
- while line = f.gets
- stats["lines"] += 1
- if(comment_started)
- if line =~ /^=end/
- comment_started = false
- end
- next
- else
- if line =~ /^=begin/
- comment_started = true
+
+ File.open(directory + "/" + file_name) do |f|
+ while line = f.gets
+ stats["lines"] += 1
+ if(comment_started)
+ if line =~ /^=end/
+ comment_started = false
+ end
next
+ else
+ if line =~ /^=begin/
+ comment_started = true
+ next
+ end
end
+ stats["classes"] += 1 if line =~ /^\s*class\s+[_A-Z]/
+ stats["methods"] += 1 if line =~ /^\s*def\s+[_a-z]/
+ stats["codelines"] += 1 unless line =~ /^\s*$/ || line =~ /^\s*#/
end
- stats["classes"] += 1 if line =~ /^\s*class\s+[_A-Z]/
- stats["methods"] += 1 if line =~ /^\s*def\s+[_a-z]/
- stats["codelines"] += 1 unless line =~ /^\s*$/ || line =~ /^\s*#/
end
end
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index 45f55a2a0a..32793b1a70 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -246,7 +246,7 @@ module Rails
sentinel = /\.routes\.draw do\s*$/
in_root do
- inject_into_file 'config/routes.rb', "\n #{routing_code}\n", { :after => sentinel, :verbose => false }
+ inject_into_file 'config/routes.rb', "\n #{routing_code}", { :after => sentinel, :verbose => false }
end
end
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index d3420a6a3c..6677850a11 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -248,7 +248,7 @@ module Rails
end
def run_bundle
- bundle_command('install') unless options[:skip_gemfile] || options[:skip_bundle]
+ bundle_command('install') unless options[:skip_gemfile] || options[:skip_bundle] || options[:pretend]
end
def empty_directory_with_gitkeep(destination, config = {})
diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb
index a98244c525..8f779316c1 100644
--- a/railties/lib/rails/generators/base.rb
+++ b/railties/lib/rails/generators/base.rb
@@ -254,17 +254,13 @@ module Rails
nesting = class_name.split('::')
last_name = nesting.pop
- # Hack to limit const_defined? to non-inherited on 1.9
- extra = []
- extra << false unless Object.method(:const_defined?).arity == 1
-
# Extract the last Module in the nesting
last = nesting.inject(Object) do |last_module, nest|
- break unless last_module.const_defined?(nest, *extra)
+ break unless last_module.const_defined?(nest, false)
last_module.const_get(nest)
end
- if last && last.const_defined?(last_name.camelize, *extra)
+ if last && last.const_defined?(last_name.camelize, false)
raise Error, "The name '#{class_name}' is either already used in your application " <<
"or reserved by Ruby on Rails. Please choose an alternative and run " <<
"this generator again."
diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb
index 29a2ad3111..7dfc1aa599 100644
--- a/railties/lib/rails/generators/generated_attribute.rb
+++ b/railties/lib/rails/generators/generated_attribute.rb
@@ -32,8 +32,8 @@ module Rails
case type
when /(string|text|binary|integer)\{(\d+)\}/
return $1, :limit => $2.to_i
- when /decimal\{(\d+)(,|\.|\-)(\d+)\}/
- return :decimal, :precision => $1.to_i, :scale => $3.to_i
+ when /decimal\{(\d+)[,.-](\d+)\}/
+ return :decimal, :precision => $1.to_i, :scale => $2.to_i
else
return type, {}
end
diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb
index 3517956e4a..acf47a03e5 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/application.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb
@@ -56,6 +56,11 @@ module <%= app_const_base %>
# parameters by using an attr_accessible or attr_protected declaration.
# config.active_record.whitelist_attributes = true
+ # Specifies wether or not has_many or has_one association option :dependent => :restrict raises
+ # an exception. If set to true, then an ActiveRecord::DeleteRestrictionError exception would be
+ # raised. If set to false, then an error will be added on the model instead.
+ <%= comment_if :skip_active_record %>config.active_record.dependent_restrict_raises = false
+
<% unless options.skip_sprockets? -%>
# Enable the asset pipeline.
config.assets.enabled = true
diff --git a/railties/lib/rails/rubyprof_ext.rb b/railties/lib/rails/rubyprof_ext.rb
index f6e90357ce..017eba3a76 100644
--- a/railties/lib/rails/rubyprof_ext.rb
+++ b/railties/lib/rails/rubyprof_ext.rb
@@ -12,7 +12,7 @@ module Prof #:nodoc:
io.puts " time seconds seconds calls ms/call ms/call name"
sum = 0.0
- for r in results
+ results.each do |r|
sum += r.self_time
name = if r.method_class.nil?
diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb
index 01156e1b83..1469c9af4d 100644
--- a/railties/test/application/assets_test.rb
+++ b/railties/test/application/assets_test.rb
@@ -64,7 +64,7 @@ module ApplicationTests
files << Dir["#{app_path}/public/assets/foo/application.js"].first
files.each do |file|
assert_not_nil file, "Expected application.js asset to be generated, but none found"
- assert_equal "alert()", File.read(file)
+ assert_equal "alert();", File.read(file)
end
end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index f3071843e2..a3c24c392b 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -202,6 +202,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
run_generator [destination_root, "--skip-active-record"]
assert_no_file "config/database.yml"
assert_file "config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
+ assert_file "config/application.rb", /#\s+config\.active_record\.dependent_restrict_raises = false/
assert_file "test/test_helper.rb" do |helper_content|
assert_no_match(/fixtures :all/, helper_content)
end
@@ -349,6 +350,16 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_active_record_dependent_restrict_raises_is_present_application_config
+ run_generator
+ assert_file "config/application.rb", /config\.active_record\.dependent_restrict_raises = false/
+ end
+
+ def test_pretend_option
+ output = run_generator [File.join(destination_root, "myapp"), "--pretend"]
+ assert_no_match(/run bundle install/, output)
+ end
+
protected
def action(*args, &block)