diff options
-rw-r--r-- | actionpack/lib/action_controller/metal/mime_responds.rb | 20 | ||||
-rw-r--r-- | actionpack/lib/action_controller/metal/renderers.rb | 3 | ||||
-rw-r--r-- | activerecord/lib/active_record/attribute_set/builder.rb | 21 | ||||
-rw-r--r-- | activerecord/lib/active_record/inheritance.rb | 12 | ||||
-rw-r--r-- | activerecord/lib/active_record/persistence.rb | 28 | ||||
-rw-r--r-- | activerecord/lib/active_record/querying.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/result.rb | 9 | ||||
-rw-r--r-- | activesupport/CHANGELOG.md | 6 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/string/filters.rb | 9 | ||||
-rw-r--r-- | activesupport/test/core_ext/range_ext_test.rb | 4 | ||||
-rw-r--r-- | activesupport/test/core_ext/string_ext_test.rb | 6 | ||||
-rw-r--r-- | guides/source/4_1_release_notes.md | 2 | ||||
-rw-r--r-- | guides/source/4_2_release_notes.md | 15 | ||||
-rw-r--r-- | guides/source/upgrading_ruby_on_rails.md | 4 |
14 files changed, 100 insertions, 41 deletions
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index 591f881a53..ac1f209232 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -135,18 +135,6 @@ module ActionController #:nodoc: # # render json: @people # - # Since this is a common pattern, you can use the class method respond_to - # with the respond_with method to have the same results: - # - # class PeopleController < ApplicationController - # respond_to :html, :xml, :json - # - # def index - # @people = Person.all - # respond_with(@people) - # end - # end - # # Formats can have different variants. # # The request variant is a specialization of the request format, like <tt>:tablet</tt>, @@ -214,8 +202,8 @@ module ActionController #:nodoc: # format.html.phone # this gets rendered # end # - # Be sure to check the documentation of +respond_with+ and - # <tt>ActionController::MimeResponds.respond_to</tt> for more examples. + # Be sure to check the documentation of <tt>ActionController::MimeResponds.respond_to</tt> + # for more examples. def respond_to(*mimes) raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given? @@ -234,8 +222,8 @@ module ActionController #:nodoc: # A container for responses available from the current controller for # requests for different mime-types sent to a particular action. # - # The public controller methods +respond_with+ and +respond_to+ may be called - # with a block that is used to define responses to different mime-types, e.g. + # The public controller methods +respond_to+ may be called with a block + # that is used to define responses to different mime-types, e.g. # for +respond_to+ : # # respond_to do |format| diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb index bc94536c8c..45d3962494 100644 --- a/actionpack/lib/action_controller/metal/renderers.rb +++ b/actionpack/lib/action_controller/metal/renderers.rb @@ -86,8 +86,7 @@ module ActionController # end # end # To use renderers and their mime types in more concise ways, see - # <tt>ActionController::MimeResponds::ClassMethods.respond_to</tt> and - # <tt>ActionController::MimeResponds#respond_with</tt> + # <tt>ActionController::MimeResponds::ClassMethods.respond_to</tt> def self.add(key, &block) define_method(_render_with_renderer_method_name(key), &block) RENDERERS << key.to_sym diff --git a/activerecord/lib/active_record/attribute_set/builder.rb b/activerecord/lib/active_record/attribute_set/builder.rb index d4a787f2fe..0a62c68bfb 100644 --- a/activerecord/lib/active_record/attribute_set/builder.rb +++ b/activerecord/lib/active_record/attribute_set/builder.rb @@ -8,18 +8,33 @@ module ActiveRecord end def build_from_database(values = {}, additional_types = {}) - attributes = build_attributes_from_values(values, additional_types) + build_from_database_pairs(values.keys, values.values, additional_types) + end + + def build_from_database_pairs(columns, values, additional_types) + attributes = build_attributes_from_values(columns, values, additional_types) add_uninitialized_attributes(attributes) AttributeSet.new(attributes) end private - def build_attributes_from_values(values, additional_types) - values.each_with_object({}) do |(name, value), hash| + def build_attributes_from_values(columns, values, additional_types) + # We are performing manual iteration here as this method is a performance + # hotspot + hash = {} + index = 0 + length = columns.length + + while index < length + name = columns[index] + value = values[index] type = additional_types.fetch(name, types[name]) hash[name] = Attribute.from_database(name, value, type) + index += 1 end + + hash end def add_uninitialized_attributes(attributes) diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index f58145ab05..4aad3217cb 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -165,15 +165,19 @@ module ActiveRecord # record instance. For single-table inheritance, we check the record # for a +type+ column and return the corresponding class. def discriminate_class_for_record(record) - if using_single_table_inheritance?(record) - find_sti_class(record[inheritance_column]) + discriminate_class_for_value(record[inheritance_column]) + end + + def discriminate_class_for_value(value) + if using_single_table_inheritance?(value) + find_sti_class(value) else super end end - def using_single_table_inheritance?(record) - record[inheritance_column].present? && columns_hash.include?(inheritance_column) + def using_single_table_inheritance?(value) + value.present? && columns_hash.include?(inheritance_column) end def find_sti_class(type_name) diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 755ff2b2f1..9d2c9d3b9c 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -65,19 +65,41 @@ module ActiveRecord # how this "single-table" inheritance mapping is implemented. def instantiate(attributes, column_types = {}) klass = discriminate_class_for_record(attributes) - attributes = klass.attributes_builder.build_from_database(attributes, column_types) - klass.allocate.init_with('attributes' => attributes, 'new_record' => false) + klass.instantiate_pairs(attributes.keys, attributes.values, column_types) + end + + def instantiate_pairs(columns, values, column_types = {}) # :nodoc: + attributes = attributes_builder.build_from_database_pairs(columns, values, column_types) + allocate.init_with('attributes' => attributes, 'new_record' => false) + end + + def instantiate_result_set(result_set, column_types = {}) # :nodoc: + inheritance_column_index = inheritance_column && result_set.columns.find_index(inheritance_column) + + result_set.each_pair.map do |columns, values| + inheritance_value = inheritance_column_index && values[inheritance_column_index] + klass = discriminate_class_for_value(inheritance_value) + klass.instantiate_pairs(columns, values, column_types) + end end private # Called by +instantiate+ to decide which class to use for a new # record instance. # - # See +ActiveRecord::Inheritance#discriminate_class_for_record+ for + # See +ActiveRecord::Inheritance#discriminate_class_for_value+ for # the single-table inheritance discriminator. + def discriminate_class_for_value(*) + self + end + def discriminate_class_for_record(record) self end + + def inheritance_column + nil + end end # Returns true if this object hasn't been saved yet -- that is, a record diff --git a/activerecord/lib/active_record/querying.rb b/activerecord/lib/active_record/querying.rb index e8de4db3a7..9d4df81b07 100644 --- a/activerecord/lib/active_record/querying.rb +++ b/activerecord/lib/active_record/querying.rb @@ -47,7 +47,7 @@ module ActiveRecord } message_bus.instrument('instantiation.active_record', payload) do - result_set.map { |record| instantiate(record, column_types) } + instantiate_result_set(result_set, column_types) end end diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb index 3a3e65ef32..c84ad586e2 100644 --- a/activerecord/lib/active_record/result.rb +++ b/activerecord/lib/active_record/result.rb @@ -54,6 +54,15 @@ module ActiveRecord end end + def each_pair + return to_enum(__method__) unless block_given? + + columns = @columns.map { |c| c.dup.freeze } + @rows.each do |row| + yield columns, row + end + end + def to_hash hash_rows end diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index b2b3cf4bd4..468b990f39 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -2,12 +2,12 @@ *Pavel Pravosud* -* TimeWithZone#strftime now delegates every directive to Time#strftime except for '%Z', +* `TimeWithZone#strftime` now delegates every directive to `Time#strftime` except for '%Z', it also now correctly handles escaped '%' characters placed just before time zone related directives. *Pablo Herrero* -* Corrected Inflector#underscore handling of multiple successive acroynms. +* Corrected `Inflector#underscore` handling of multiple successive acroynms. *James Le Cuirot* @@ -160,7 +160,7 @@ * Fixed `ActiveSupport::Cache::FileStore` exploding with long paths. - *Adam Panzer / Michael Grosser* + *Adam Panzer*, *Michael Grosser* * Fixed `ActiveSupport::TimeWithZone#-` so precision is not unnecessarily lost when working with objects with a nanosecond component. diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb index 499b9b26bc..096292dc58 100644 --- a/activesupport/lib/active_support/core_ext/string/filters.rb +++ b/activesupport/lib/active_support/core_ext/string/filters.rb @@ -13,6 +13,9 @@ class String end # Performs a destructive squish. See String#squish. + # str = " foo bar \n \t boo" + # str.squish! # => "foo bar boo" + # str # => "foo bar boo" def squish! gsub!(/\A[[:space:]]+/, '') gsub!(/[[:space:]]+\z/, '') @@ -21,11 +24,17 @@ class String end # Returns a new string with all occurrences of the patterns removed. + # str = "foo bar test" + # str.remove(" test") # => "foo bar" + # str # => "foo bar test" def remove(*patterns) dup.remove!(*patterns) end # Alters the string by removing all occurrences of the patterns. + # str = "foo bar test" + # str.remove!(" test") # => "foo bar" + # str # => "foo bar" def remove!(*patterns) patterns.each do |pattern| gsub! pattern, "" diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb index 98c4ec6b5e..f096328cee 100644 --- a/activesupport/test/core_ext/range_ext_test.rb +++ b/activesupport/test/core_ext/range_ext_test.rb @@ -115,11 +115,11 @@ class RangeTest < ActiveSupport::TestCase def test_date_time_with_each datetime = DateTime.now - assert ((datetime - 1.hour)..datetime).each {} + assert(((datetime - 1.hour)..datetime).each {}) end def test_date_time_with_step datetime = DateTime.now - assert ((datetime - 1.hour)..datetime).step(1) {} + assert(((datetime - 1.hour)..datetime).step(1) {}) end end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 119e62369d..e32c178951 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -266,6 +266,12 @@ class StringInflectionsTest < ActiveSupport::TestCase assert_equal "This is a good day to die", original end + def test_remove_for_multiple_occurrences + original = "This is a good day to die to die" + assert_equal "This is a good day", original.remove(" to die") + assert_equal "This is a good day to die to die", original + end + def test_remove! original = "This is a very good day to die" assert_equal "This is a good day to die", original.remove!(" very") diff --git a/guides/source/4_1_release_notes.md b/guides/source/4_1_release_notes.md index 52a5acb75e..c7877a9cb5 100644 --- a/guides/source/4_1_release_notes.md +++ b/guides/source/4_1_release_notes.md @@ -136,7 +136,7 @@ end ### Action Mailer Previews -Action Mailer previews provide a way to visually see how emails look by visiting +Action Mailer previews provide a way to see how emails look by visiting a special URL that renders them. You implement a preview class whose methods return the mail object you'd like diff --git a/guides/source/4_2_release_notes.md b/guides/source/4_2_release_notes.md index 3a9be62865..8553cffa9d 100644 --- a/guides/source/4_2_release_notes.md +++ b/guides/source/4_2_release_notes.md @@ -300,6 +300,9 @@ Please refer to the [Changelog][railties] for detailed changes. ### Removals +* The `--skip-action-view` option has been removed from the + app generator. ([Pull Request](https://github.com/rails/rails/pull/17042)) + * The `rails application` command has been removed without replacement. ([Pull Request](https://github.com/rails/rails/pull/11616)) @@ -575,6 +578,10 @@ Please refer to the [Changelog][active-record] for detailed changes. ### Deprecations +* Deprecated `sanitize_sql_hash_for_conditions` without replacement. Using a + `Relation` for performing queries and updates is the prefered API. + ([Commit](https://github.com/rails/rails/commit/d5902c9e)) + * Deprecated swallowing of errors inside `after_commit` and `after_rollback`. ([Pull Request](https://github.com/rails/rails/pull/16537)) @@ -753,15 +760,15 @@ Please refer to the [Changelog][active-support] for detailed changes. ### Notable changes -* `Object#try` and `Object#try!` can now be used without an explicit receiver. - ([Commit](https://github.com/rails/rails/commit/5e51bdda59c9ba8e5faf86294e3e431bd45f1830), - [Pull Request](https://github.com/rails/rails/pull/17361)) - * Introduced new configuration option `active_support.test_order` for specifying the order test cases are executed. This option currently defaults to `:sorted` but will be changed to `:random` in Rails 5.0. ([Commit](https://github.com/rails/rails/commit/53e877f7d9291b2bf0b8c425f9e32ef35829f35b)) +* `Object#try` and `Object#try!` can now be used without an explicit receiver. + ([Commit](https://github.com/rails/rails/commit/5e51bdda59c9ba8e5faf86294e3e431bd45f1830), + [Pull Request](https://github.com/rails/rails/pull/17361)) + * The `travel_to` test helper now truncates the `usec` component to 0. ([Commit](https://github.com/rails/rails/commit/9f6e82ee4783e491c20f5244a613fdeb4024beb5)) diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index aac2aef615..25759a0c77 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -181,7 +181,7 @@ end There's a new choice for sanitizing HTML fragments in your applications. The venerable html-scanner approach is now officially being deprecated in favor of -[`Rails Html Sanitizer`](https://github.com/rails/rails-html-sanitizer). +[`Rails HTML Sanitizer`](https://github.com/rails/rails-html-sanitizer). This means the methods `sanitize`, `sanitize_css`, `strip_tags` and `strip_links` are backed by a new implementation. @@ -207,7 +207,7 @@ gem 'rails-deprecated_sanitizer' ``` ### Rails DOM Testing -The [`TagAssertions` module](http://api.rubyonrails.org/classes/ActionDispatch/Assertions/TagAssertions.html) (containing methods such as `assert_tag`), [has been deprecated](https://github.com/rails/rails/blob/6061472b8c310158a2a2e8e9a6b81a1aef6b60fe/actionpack/lib/action_dispatch/testing/assertions/dom.rb) in favor of the `assert_select` methods from the `SelectorAssertions` module, which has been extracted into the [rails-dom-testing gem](https://github.com/rails/rails-dom-testing). +The [`TagAssertions` module](http://api.rubyonrails.org/classes/ActionDispatch/Assertions/TagAssertions.html) (containing methods such as `assert_tag`), [has been deprecated](https://github.com/rails/rails/blob/6061472b8c310158a2a2e8e9a6b81a1aef6b60fe/actionpack/lib/action_dispatch/testing/assertions/dom.rb) in favor of the `assert_select` methods from the `SelectorAssertions` module, which has been extracted into the [rails-dom-testing gem](https://github.com/rails/rails-dom-testing). ### Masked Authenticity Tokens |