diff options
19 files changed, 125 insertions, 139 deletions
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index dde51da497..fd09d3b55b 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -19,7 +19,7 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', version) s.add_dependency('rack-cache', '~> 1.2') - s.add_dependency('builder', '~> 3.0.0') + s.add_dependency('builder', '~> 3.1.0') s.add_dependency('rack', '~> 1.4.1') s.add_dependency('rack-test', '~> 0.6.1') s.add_dependency('journey', '~> 2.0.0') diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb index 0238135bc1..eb3aa05a25 100644 --- a/actionpack/lib/action_controller/caching/actions.rb +++ b/actionpack/lib/action_controller/caching/actions.rb @@ -132,7 +132,7 @@ module ActionController #:nodoc: options.values_at(:cache_path, :store_options, :layout) end - def filter(controller) + def around(controller) cache_layout = @cache_layout.respond_to?(:call) ? @cache_layout.call(controller) : @cache_layout path_options = if @cache_path.respond_to?(:call) diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb index 7521deaaca..12ef68ff26 100644 --- a/actionpack/lib/action_controller/metal/conditional_get.rb +++ b/actionpack/lib/action_controller/metal/conditional_get.rb @@ -22,7 +22,7 @@ module ActionController # # class InvoicesController < ApplicationController # etag { current_user.try :id } - # + # # def show # # Etag will differ even for the same invoice when it's viewed by a different current_user # @invoice = Invoice.find(params[:id]) @@ -71,7 +71,7 @@ module ActionController options.assert_valid_keys(:etag, :last_modified, :public) else record = record_or_options - options = { etag: record, last_modified: record.try(:updated_at) }.merge(additional_options) + options = { etag: record, last_modified: record.try(:updated_at) }.merge!(additional_options) end response.etag = combine_etags(options[:etag]) if options[:etag] @@ -162,8 +162,7 @@ module ActionController def expires_now #:doc: response.cache_control.replace(:no_cache => true) end - - + private def combine_etags(etag) [ etag, *etaggers.map { |etagger| instance_exec(&etagger) }.compact ] diff --git a/actionpack/lib/action_view/routing_url_for.rb b/actionpack/lib/action_view/routing_url_for.rb index 13fb6406e1..d1488e2332 100644 --- a/actionpack/lib/action_view/routing_url_for.rb +++ b/actionpack/lib/action_view/routing_url_for.rb @@ -99,7 +99,7 @@ module ActionView protected :_routes_context def optimize_routes_generation? #:nodoc: - controller.respond_to?(:optimize_routes_generation?) ? + controller.respond_to?(:optimize_routes_generation?, true) ? controller.optimize_routes_generation? : super end protected :optimize_routes_generation? diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index afc00a3c9d..d203601771 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -193,7 +193,7 @@ class FilterTest < ActionController::TestCase end class ConditionalClassFilter - def self.filter(controller) controller.instance_variable_set(:"@ran_class_filter", true) end + def self.before(controller) controller.instance_variable_set(:"@ran_class_filter", true) end end class OnlyConditionClassController < ConditionalFilterController @@ -309,7 +309,7 @@ class FilterTest < ActionController::TestCase end class AuditFilter - def self.filter(controller) + def self.before(controller) controller.instance_variable_set(:"@was_audited", true) end end @@ -449,7 +449,7 @@ class FilterTest < ActionController::TestCase class ErrorToRescue < Exception; end class RescuingAroundFilterWithBlock - def filter(controller) + def around(controller) begin yield rescue ErrorToRescue => ex @@ -894,7 +894,7 @@ end class ControllerWithFilterClass < PostsController class YieldingFilter < DefaultFilter - def self.filter(controller) + def self.around(controller) yield raise After end @@ -905,7 +905,7 @@ end class ControllerWithFilterInstance < PostsController class YieldingFilter < DefaultFilter - def filter(controller) + def around(controller) yield raise After end @@ -916,13 +916,13 @@ end class ControllerWithFilterMethod < PostsController class YieldingFilter < DefaultFilter - def filter(controller) + def around(controller) yield raise After end end - around_filter YieldingFilter.new.method(:filter), :only => :raises_after + around_filter YieldingFilter.new.method(:around), :only => :raises_after end class ControllerWithProcFilter < PostsController diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 9d0ff5ba99..d7041055a4 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,5 +1,16 @@ ## Rails 4.0.0 (unreleased) ## +* Due to a change in builder, nil values and empty strings now generates + closed tags, so instead of this: + + <pseudonyms nil=\"true\"></pseudonyms> + + It generates this: + + <pseudonyms nil=\"true\"/> + + *Carlos Antonio da Silva* + * Changed inclusion and exclusion validators to accept a symbol for `:in` option. This allows to use dynamic inclusion/exclusion values using methods, besides the current lambda/proc support. diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec index 66f324a1a1..be5d5d3ca8 100644 --- a/activemodel/activemodel.gemspec +++ b/activemodel/activemodel.gemspec @@ -18,5 +18,5 @@ Gem::Specification.new do |s| s.require_path = 'lib' s.add_dependency('activesupport', version) - s.add_dependency('builder', '~> 3.0.0') + s.add_dependency('builder', '~> 3.1.0') end diff --git a/activemodel/test/cases/serializers/xml_serialization_test.rb b/activemodel/test/cases/serializers/xml_serialization_test.rb index 8c5a3c5efd..e2bb0dda0b 100755 --- a/activemodel/test/cases/serializers/xml_serialization_test.rb +++ b/activemodel/test/cases/serializers/xml_serialization_test.rb @@ -133,7 +133,7 @@ class XmlSerializationTest < ActiveModel::TestCase end test "should serialize nil" do - assert_match %r{<pseudonyms nil=\"true\"></pseudonyms>}, @contact.to_xml(:methods => :pseudonyms) + assert_match %r{<pseudonyms nil=\"true\"/>}, @contact.to_xml(:methods => :pseudonyms) end test "should serialize integer" do diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index c0c8096084..4c55a3edea 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 4.0.0 (unreleased) ## +* Fix eagerly loading associations without primary keys. Fixes #4976. *Kelley Reynolds* + * Rails now raise an exception when you're trying to run a migration that has an invalid file name. Only lower case letters, numbers, and '_' are allowed in migration's file name. Please see #7419 for more details. @@ -645,104 +647,4 @@ * PostgreSQL hstore types are automatically deserialized from the database. -## Rails 3.2.8 (Aug 9, 2012) ## - -* Do not consider the numeric attribute as changed if the old value is zero and the new value - is not a string. - Fixes #7237. - - *Rafael Mendonça França* - -* Removes the deprecation of `update_attribute`. *fxn* - -* Reverted the deprecation of `composed_of`. *Rafael Mendonça França* - -* Reverted the deprecation of `*_sql` association options. They will - be deprecated in 4.0 instead. *Jon Leighton* - -* Do not eager load AR session store. ActiveRecord::SessionStore depends on the abstract store - in Action Pack. Eager loading this class would break client code that eager loads Active Record - standalone. - Fixes #7160 - - *Xavier Noria* - -* Do not set RAILS_ENV to "development" when using `db:test:prepare` and related rake tasks. - This was causing the truncation of the development database data when using RSpec. - Fixes #7175. - - *Rafael Mendonça França* - - -## Rails 3.2.7 (Jul 26, 2012) ## - -* `:finder_sql` and `:counter_sql` options on collection associations - are deprecated. Please transition to using scopes. - - *Jon Leighton* - -* `:insert_sql` and `:delete_sql` options on `has_and_belongs_to_many` - associations are deprecated. Please transition to using `has_many - :through` - - *Jon Leighton* - -* `composed_of` has been deprecated. You'll have to write your own accessor - and mutator methods if you'd like to use value objects to represent some - portion of your models. - - *Steve Klabnik* - -* `update_attribute` has been deprecated. Use `update_column` if - you want to bypass mass-assignment protection, validations, callbacks, - and touching of updated_at. Otherwise please use `update_attributes`. - - *Steve Klabnik* - - -## Rails 3.2.6 (Jun 12, 2012) ## - -* protect against the nesting of hashes changing the - table context in the next call to build_from_hash. This fix - covers this case as well. - - CVE-2012-2695 - -* Revert earlier 'perf fix' (see 3.2.4 changelog / GH #6289). This - change introduced a regression (GH #6609). assoc.clear and - assoc.delete_all have loaded the association before doing the delete - since at least Rails 2.3. Doing the delete without loading the - records means that the `before_remove` and `after_remove` callbacks do - not get invoked. Therefore, this change was less a fix a more an - optimisation, which should only have gone into master. - - *Jon Leighton* - - -## Rails 3.2.5 (Jun 1, 2012) ## - -* Restore behavior of Active Record 3.2.3 scopes. - A series of commits relating to preloading and scopes caused a regression. - - *Andrew White* - - -## Rails 3.2.4 (May 31, 2012) ## - -* Perf fix: Don't load the records when doing assoc.delete_all. - GH #6289. *Jon Leighton* - -* Association preloading shouldn't be affected by the current scoping. - This could cause infinite recursion and potentially other problems. - See GH #5667. *Jon Leighton* - -* Datetime attributes are forced to be changed. GH #3965 - -* Fix attribute casting. GH #5549 - -* Fix #5667. Preloading should ignore scoping. - -* Predicate builder should not recurse for determining where columns. - Thanks to Ben Murphy for reporting this! CVE-2012-2661 - Please check [3-2-stable](https://github.com/rails/rails/blob/3-2-stable/activerecord/CHANGELOG.md) for previous changes. diff --git a/activerecord/lib/active_record/associations/join_dependency/join_part.rb b/activerecord/lib/active_record/associations/join_dependency/join_part.rb index 2b1d888a9a..711f7b3ce1 100644 --- a/activerecord/lib/active_record/associations/join_dependency/join_part.rb +++ b/activerecord/lib/active_record/associations/join_dependency/join_part.rb @@ -54,7 +54,7 @@ module ActiveRecord unless @column_names_with_alias @column_names_with_alias = [] - ([primary_key] + (column_names - [primary_key])).each_with_index do |column_name, i| + ([primary_key] + (column_names - [primary_key])).compact.each_with_index do |column_name, i| @column_names_with_alias << [column_name, "#{aliased_prefix}_r#{i}"] end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index 4e1f0e1d62..11e4d34de2 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -193,7 +193,8 @@ module ActiveRecord rescue Exception => database_transaction_rollback if transaction_open && !outside_transaction? transaction_open = false - decrement_open_transactions + txn = decrement_open_transactions + txn.aborted! if open_transactions == 0 rollback_db_transaction rollback_transaction_records(true) @@ -208,9 +209,10 @@ module ActiveRecord @transaction_joinable = last_transaction_joinable if outside_transaction? - @open_transactions = 0 + @current_transaction = nil elsif transaction_open - decrement_open_transactions + txn = decrement_open_transactions + txn.committed! begin if open_transactions == 0 commit_db_transaction diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index b3f9187429..27700e4fd2 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -69,6 +69,7 @@ module ActiveRecord @last_use = false @logger = logger @open_transactions = 0 + @current_transaction = nil @pool = pool @query_cache = Hash.new { |h,sql| h[sql] = {} } @query_cache_enabled = false @@ -236,14 +237,30 @@ module ActiveRecord @connection end - attr_reader :open_transactions + def open_transactions + count = 0 + txn = current_transaction + + while txn + count += 1 + txn = txn.next + end + + count + end + + attr_reader :current_transaction def increment_open_transactions - @open_transactions += 1 + @current_transaction = Transaction.new(current_transaction) end def decrement_open_transactions - @open_transactions -= 1 + return unless current_transaction + + txn = current_transaction + @current_transaction = txn.next + txn end def transaction_joinable=(joinable) diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index aad21b8e37..791ff4eaec 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -393,6 +393,7 @@ module ActiveRecord @marked_for_destruction = false @new_record = true @mass_assignment_options = nil + @txn = nil @_start_transaction_state = {} end end diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 09318879d5..e008b32170 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -1,6 +1,32 @@ require 'thread' module ActiveRecord + class Transaction + attr_reader :next + + def initialize(txn = nil) + @next = txn + @committed = false + @aborted = false + end + + def committed! + @committed = true + end + + def aborted! + @aborted = true + end + + def committed? + @committed + end + + def aborted? + @aborted + end + end + # See ActiveRecord::Transactions::ClassMethods for documentation. module Transactions extend ActiveSupport::Concern @@ -307,11 +333,11 @@ module ActiveRecord def with_transaction_returning_status status = nil self.class.transaction do + @txn = self.class.connection.current_transaction add_to_transaction begin status = yield rescue ActiveRecord::Rollback - @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1 status = nil end @@ -327,20 +353,17 @@ module ActiveRecord @_start_transaction_state[:id] = id if has_attribute?(self.class.primary_key) @_start_transaction_state[:new_record] = @new_record @_start_transaction_state[:destroyed] = @destroyed - @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1 end # Clear the new record state and id of a record. def clear_transaction_record_state #:nodoc: - @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1 - @_start_transaction_state.clear if @_start_transaction_state[:level] < 1 + @_start_transaction_state.clear if @txn.committed? end # Restore the new record state and id of a record that was previously saved by a call to save_record_state. def restore_transaction_record_state(force = false) #:nodoc: unless @_start_transaction_state.empty? - @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1 - if @_start_transaction_state[:level] < 1 || force + if @txn.aborted? || force restore_state = @_start_transaction_state was_frozen = @attributes.frozen? @attributes = @attributes.dup if was_frozen diff --git a/activerecord/test/cases/associations/join_dependency_test.rb b/activerecord/test/cases/associations/join_dependency_test.rb new file mode 100644 index 0000000000..08c166dc33 --- /dev/null +++ b/activerecord/test/cases/associations/join_dependency_test.rb @@ -0,0 +1,8 @@ +require "cases/helper" +require 'models/edge' + +class JoinDependencyTest < ActiveRecord::TestCase + def test_column_names_with_alias_handles_nil_primary_key + assert_equal Edge.column_names, ActiveRecord::Associations::JoinDependency::JoinBase.new(Edge).column_names_with_alias.map(&:first) + end +end
\ No newline at end of file diff --git a/activerecord/test/cases/xml_serialization_test.rb b/activerecord/test/cases/xml_serialization_test.rb index 7249ae9e4d..68fa15de50 100644 --- a/activerecord/test/cases/xml_serialization_test.rb +++ b/activerecord/test/cases/xml_serialization_test.rb @@ -185,18 +185,18 @@ class NilXmlSerializationTest < ActiveRecord::TestCase end def test_should_serialize_string - assert_match %r{<name nil="true"></name>}, @xml + assert_match %r{<name nil="true"/>}, @xml end def test_should_serialize_integer - assert %r{<age (.*)></age>}.match(@xml) + assert %r{<age (.*)/>}.match(@xml) attributes = $1 assert_match %r{nil="true"}, attributes assert_match %r{type="integer"}, attributes end def test_should_serialize_binary - assert %r{<avatar (.*)></avatar>}.match(@xml) + assert %r{<avatar (.*)/>}.match(@xml) attributes = $1 assert_match %r{type="binary"}, attributes assert_match %r{encoding="base64"}, attributes @@ -204,21 +204,21 @@ class NilXmlSerializationTest < ActiveRecord::TestCase end def test_should_serialize_datetime - assert %r{<created-at (.*)></created-at>}.match(@xml) + assert %r{<created-at (.*)/>}.match(@xml) attributes = $1 assert_match %r{nil="true"}, attributes assert_match %r{type="dateTime"}, attributes end def test_should_serialize_boolean - assert %r{<awesome (.*)></awesome>}.match(@xml) + assert %r{<awesome (.*)/>}.match(@xml) attributes = $1 assert_match %r{type="boolean"}, attributes assert_match %r{nil="true"}, attributes end def test_should_serialize_yaml - assert_match %r{<preferences nil=\"true\"></preferences>}, @xml + assert_match %r{<preferences nil=\"true\"/>}, @xml end end diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 761780fb8b..47280c3dc8 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,27 @@ ## Rails 4.0.0 (unreleased) ## +* `ActiveSupport::Callbacks`: deprecate monkey patch of object callbacks. + Using the #filter method like this: + + before_filter MyFilter.new + + class MyFilter + def filter(controller) + end + end + + Is now deprecated with recommendation to use the corresponding filter type + (`#before`, `#after` or `#around`): + + before_filter MyFilter.new + + class MyFilter + def before(controller) + end + end + + *Bogdan Gusiev* + * An optional block can be passed to `HashWithIndifferentAccess#update` and `#merge`. The block will be invoked for each duplicated key, and used to resolve the conflict, thus replicating the behaviour of the corresponding methods on the `Hash` class. @@ -21,8 +43,8 @@ *Carlos Antonio da Silva* -* ActiveSupport::JSON::Variable is deprecated. Define your own #as_json and - #encode_json methods for custom JSON string literals. +* `ActiveSupport::JSON::Variable` is deprecated. Define your own `#as_json` and + `#encode_json` methods for custom JSON string literals. *Erich Menge* diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index a55f68497c..7166c21268 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -279,6 +279,7 @@ module ActiveSupport def _normalize_legacy_filter(kind, filter) if !filter.respond_to?(kind) && filter.respond_to?(:filter) + ActiveSupport::Deprecation.warn("Filter object with #filter method is deprecated. Define method corresponding to filter type (#before, #after or #around).") filter.singleton_class.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 def #{kind}(context, &block) filter(context, &block) end RUBY_EVAL diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 37fdf1c0af..94463cc311 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -848,7 +848,7 @@ class HashToXmlTest < ActiveSupport::TestCase assert_equal "<person>", xml.first(8) assert xml.include?(%(<street>Paulina</street>)) assert xml.include?(%(<name>David</name>)) - assert xml.include?(%(<age nil="true"></age>)) + assert xml.include?(%(<age nil="true"/>)) end def test_one_level_with_skipping_types @@ -856,7 +856,7 @@ class HashToXmlTest < ActiveSupport::TestCase assert_equal "<person>", xml.first(8) assert xml.include?(%(<street>Paulina</street>)) assert xml.include?(%(<name>David</name>)) - assert xml.include?(%(<age nil="true"></age>)) + assert xml.include?(%(<age nil="true"/>)) end def test_one_level_with_yielding |