diff options
Diffstat (limited to 'activerecord/lib')
25 files changed, 111 insertions, 61 deletions
| diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index f7edfbfb5f..62e867a353 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -217,7 +217,8 @@ module ActiveRecord            unless record.is_a?(reflection.klass)              fresh_class = reflection.class_name.safe_constantize              unless fresh_class && record.is_a?(fresh_class) -              message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})" +              message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, "\ +                "got #{record.inspect} which is an instance of #{record.class}(##{record.class.object_id})"                raise ActiveRecord::AssociationTypeMismatch, message              end            end diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb index 48437a1c9e..15844de0bc 100644 --- a/activerecord/lib/active_record/associations/association_scope.rb +++ b/activerecord/lib/active_record/associations/association_scope.rb @@ -124,8 +124,7 @@ module ActiveRecord          scope = last_chain_scope(scope, table, owner_reflection, owner, association_klass)          reflection = chain_head -        loop do -          break unless reflection +        while reflection            table = reflection.alias_name            unless reflection == chain_tail diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 60373210ec..0eaa0a4f36 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -246,9 +246,12 @@ module ActiveRecord          end        end -      # Count all records using SQL.  Construct options and pass them with -      # scope to the target class's +count+. +      # Returns the number of records. If no arguments are given, it counts all +      # columns using SQL. If one argument is given, it counts only the passed +      # column using SQL. If a block is given, it counts the number of records +      # yielding a true value.        def count(column_name = nil) +        return super if block_given?          relation = scope          if association_scope.distinct_value            # This is needed because 'SELECT count(DISTINCT *)..' is not valid SQL. @@ -280,7 +283,7 @@ module ActiveRecord          _options = records.extract_options!          dependent = _options[:dependent] || options[:dependent] -        records = find(records) if records.any? { |record| record.kind_of?(Fixnum) || record.kind_of?(String) } +        records = find(records) if records.any? { |record| record.kind_of?(Integer) || record.kind_of?(String) }          delete_or_destroy(records, dependent)        end @@ -291,7 +294,7 @@ module ActiveRecord        # +:dependent+ option.        def destroy(*records)          return if records.empty? -        records = find(records) if records.any? { |record| record.kind_of?(Fixnum) || record.kind_of?(String) } +        records = find(records) if records.any? { |record| record.kind_of?(Integer) || record.kind_of?(String) }          delete_or_destroy(records, :destroy)        end diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index b9aed05135..5d1e7ffb73 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -597,7 +597,7 @@ module ActiveRecord        #   Pet.find(1)        #   # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=1        # -      # You can pass +Fixnum+ or +String+ values, it finds the records +      # You can pass +Integer+ or +String+ values, it finds the records        # responding to the +id+ and executes delete on them.        #        #   class Person < ActiveRecord::Base @@ -661,7 +661,7 @@ module ActiveRecord        #        #   Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)        # -      # You can pass +Fixnum+ or +String+ values, it finds the records +      # You can pass +Integer+ or +String+ values, it finds the records        # responding to the +id+ and then deletes them from the database.        #        #   person.pets.size # => 3 @@ -715,12 +715,13 @@ module ActiveRecord        end        alias uniq distinct -      # Count all records using SQL. +      # Count all records.        #        #   class Person < ActiveRecord::Base        #     has_many :pets        #   end        # +      #   # This will perform the count using SQL.        #   person.pets.count # => 3        #   person.pets        #   # => [ @@ -728,8 +729,13 @@ module ActiveRecord        #   #       #<Pet id: 2, name: "Spook", person_id: 1>,        #   #       #<Pet id: 3, name: "Choo-Choo", person_id: 1>        #   #    ] -      def count(column_name = nil) -        @association.count(column_name) +      # +      # Passing a block will select all of a person's pets in SQL and then +      # perform the count using Ruby. +      # +      #   person.pets.count { |pet| pet.name.include?('-') } # => 2 +      def count(column_name = nil, &block) +        @association.count(column_name, &block)        end        # Returns the size of the collection. If the collection hasn't been loaded, diff --git a/activerecord/lib/active_record/attribute.rb b/activerecord/lib/active_record/attribute.rb index 3c4c8f10ec..24231dc9e1 100644 --- a/activerecord/lib/active_record/attribute.rb +++ b/activerecord/lib/active_record/attribute.rb @@ -170,7 +170,7 @@ module ActiveRecord          super(name, nil, Type::Value.new)        end -      def value +      def type_cast(*)          nil        end diff --git a/activerecord/lib/active_record/attribute_assignment.rb b/activerecord/lib/active_record/attribute_assignment.rb index 4c22be8235..b96d8e9352 100644 --- a/activerecord/lib/active_record/attribute_assignment.rb +++ b/activerecord/lib/active_record/attribute_assignment.rb @@ -38,7 +38,7 @@ module ActiveRecord      # by calling new on the column type or aggregation type (through composed_of) object with these parameters.      # So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate      # written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the -    # parentheses to have the parameters typecasted before they're used in the constructor. Use i for Fixnum and +    # parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and      # f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+.      def assign_multiparameter_attributes(pairs)        execute_callstack_for_multiparameter_attributes( diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index e902eb7531..7e19dceaed 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -360,7 +360,7 @@ module ActiveRecord      #   person = Person.new      #   person[:age] = '22'      #   person[:age] # => 22 -    #   person[:age] # => Fixnum +    #   person[:age].class # => Integer      def []=(attr_name, value)        write_attribute(attr_name, value)      end diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index 5599b590ca..70c2d2f25d 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -26,7 +26,7 @@ module ActiveRecord        end        # Updates the attribute identified by <tt>attr_name</tt> with the -      # specified +value+. Empty strings for fixnum and float columns are +      # specified +value+. Empty strings for Integer and Float columns are        # turned into +nil+.        def write_attribute(attr_name, value)          write_attribute_with_type_cast(attr_name, value, true) diff --git a/activerecord/lib/active_record/coders/json.rb b/activerecord/lib/active_record/coders/json.rb index 75d3bfe625..cb185a881e 100644 --- a/activerecord/lib/active_record/coders/json.rb +++ b/activerecord/lib/active_record/coders/json.rb @@ -6,7 +6,7 @@ module ActiveRecord        end        def self.load(json) -        ActiveSupport::JSON.decode(json) unless json.nil? +        ActiveSupport::JSON.decode(json) unless json.blank?        end      end    end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index 4ba8ee2706..f437dafec2 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -298,7 +298,7 @@ module ActiveRecord          def run            return unless frequency            Thread.new(frequency, pool) { |t, p| -            while true +            loop do                sleep t                p.reap              end @@ -618,7 +618,7 @@ module ActiveRecord          timeout_time      = Time.now + (@checkout_timeout * 2)          @available.with_a_bias_for(Thread.current) do -          while true +          loop do              synchronize do                return if collected_conns.size == @connections.size && @now_connecting == 0                remaining_timeout = timeout_time - Time.now @@ -826,9 +826,7 @@ module ActiveRecord      # in order to lookup the correct connection pool.      class ConnectionHandler        def initialize -        # These caches are keyed by klass.name, NOT klass. Keying them by klass -        # alone would lead to memory leaks in development mode as all previous -        # instances of the class would stay in memory. +        # These caches are keyed by spec.name (ConnectionSpecification#name).          @owner_to_pool = Concurrent::Map.new(:initial_capacity => 2) do |h,k|            h[k] = Concurrent::Map.new(:initial_capacity => 2)          end @@ -898,17 +896,13 @@ module ActiveRecord          end        end -      # Retrieving the connection pool happens a lot so we cache it in @class_to_pool. +      # Retrieving the connection pool happens a lot, so we cache it in @owner_to_pool.        # This makes retrieving the connection pool O(1) once the process is warm.        # When a connection is established or removed, we invalidate the cache. -      # -      # Ideally we would use #fetch here, as class_to_pool[klass] may sometimes be nil. -      # However, benchmarking (https://gist.github.com/jonleighton/3552829) showed that -      # #fetch is significantly slower than #[]. So in the nil case, no caching will -      # take place, but that's ok since the nil case is not the common one that we wish -      # to optimise for.        def retrieve_connection_pool(spec_name)          owner_to_pool.fetch(spec_name) do +          # Check if a connection was previously established in an ancestor process, +          # which may have been forked.            if ancestor_pool = pool_from_any_process_for(spec_name)              # A connection was established in an ancestor process that must have              # subsequently forked. We can't reuse the connection, but we can copy 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 4eb009c873..44b4b547f3 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -146,11 +146,11 @@ module ActiveRecord        end        def get_advisory_lock(lock_name, timeout = 0) # :nodoc: -        select_value("SELECT GET_LOCK('#{lock_name}', #{timeout});").to_s == '1' +        select_value("SELECT GET_LOCK(#{quote(lock_name)}, #{timeout})") == 1        end        def release_advisory_lock(lock_name) # :nodoc: -        select_value("SELECT RELEASE_LOCK('#{lock_name}')").to_s == '1' +        select_value("SELECT RELEASE_LOCK(#{quote(lock_name)})") == 1        end        def native_database_types @@ -707,7 +707,7 @@ module ActiveRecord            case length            when Hash              column_names.each {|name| option_strings[name] += "(#{length[name]})" if length.has_key?(name) && length[name].present?} -          when Fixnum +          when Integer              column_names.each {|name| option_strings[name] += "(#{length})"}            end          end @@ -727,14 +727,22 @@ module ActiveRecord          column_names.map {|name| quote_column_name(name) + option_strings[name]}        end +      # See https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html +      ER_DUP_ENTRY            = 1062 +      ER_NO_REFERENCED_ROW_2  = 1452 +      ER_DATA_TOO_LONG        = 1406 +      ER_LOCK_DEADLOCK        = 1213 +        def translate_exception(exception, message)          case error_number(exception) -        when 1062 +        when ER_DUP_ENTRY            RecordNotUnique.new(message) -        when 1452 +        when ER_NO_REFERENCED_ROW_2            InvalidForeignKey.new(message) -        when 1406 +        when ER_DATA_TOO_LONG            ValueTooLong.new(message) +        when ER_LOCK_DEADLOCK +          TransactionSerializationError.new(message)          else            super          end @@ -832,7 +840,7 @@ module ActiveRecord          # Increase timeout so the server doesn't disconnect us.          wait_timeout = @config[:wait_timeout] -        wait_timeout = 2147483 unless wait_timeout.is_a?(Fixnum) +        wait_timeout = 2147483 unless wait_timeout.is_a?(Integer)          variables['wait_timeout'] = self.class.type_cast_config_to_integer(wait_timeout)          defaults = [':default', :default].to_set diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb index 7427a25ad5..4da240edb2 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb @@ -14,6 +14,8 @@ module ActiveRecord            def cast(value)              case value              when ::String +              return if value.blank? +                              if value[0] == '(' && value[-1] == ')'                  value = value[1...-1]                end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index bab80a8890..ddfc560747 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -406,6 +406,7 @@ module ActiveRecord          VALUE_LIMIT_VIOLATION = "22001"          FOREIGN_KEY_VIOLATION = "23503"          UNIQUE_VIOLATION      = "23505" +        SERIALIZATION_FAILURE = "40001"          def translate_exception(exception, message)            return exception unless exception.respond_to?(:result) @@ -417,6 +418,8 @@ module ActiveRecord              InvalidForeignKey.new(message)            when VALUE_LIMIT_VIOLATION              ValueTooLong.new(message) +          when SERIALIZATION_FAILURE +            TransactionSerializationError.new(message)            else              super            end diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb index ba763149cc..f932deb18d 100644 --- a/activerecord/lib/active_record/connection_handling.rb +++ b/activerecord/lib/active_record/connection_handling.rb @@ -45,19 +45,19 @@ module ActiveRecord      # The exceptions AdapterNotSpecified, AdapterNotFound and +ArgumentError+      # may be returned on an error.      def establish_connection(spec = nil) -      raise RuntimeError, "Anonymous class is not allowed." unless name +      raise "Anonymous class is not allowed." unless name        spec     ||= DEFAULT_ENV.call.to_sym        resolver =   ConnectionAdapters::ConnectionSpecification::Resolver.new configurations        # TODO: uses name on establish_connection, for backwards compatibility        spec     =   resolver.spec(spec, self == Base ? "primary" : name) -      self.connection_specification_name = spec.name        unless respond_to?(spec.adapter_method)          raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"        end -      remove_connection +      remove_connection(spec.name) +      self.connection_specification_name = spec.name        connection_handler.establish_connection spec      end @@ -93,11 +93,10 @@ module ActiveRecord      attr_writer :connection_specification_name -    # Return the specification id from this class otherwise look it up -    # in the parent. +    # Return the specification name from the current class or its parent.      def connection_specification_name -      unless defined?(@connection_specification_name) -        @connection_specification_name = self == Base ? "primary" : superclass.connection_specification_name +      if !defined?(@connection_specification_name) || @connection_specification_name.nil? +        return self == Base ? "primary" : superclass.connection_specification_name        end        @connection_specification_name      end @@ -133,7 +132,15 @@ module ActiveRecord        connection_handler.connected?(connection_specification_name)      end -    def remove_connection(name = connection_specification_name) +    def remove_connection(name = nil) +      name ||= @connection_specification_name if defined?(@connection_specification_name) +      # if removing a connection that have a pool, we reset the +      # connection_specification_name so it will use the parent +      # pool. +      if connection_handler.retrieve_connection_pool(name) +        self.connection_specification_name = nil +      end +        connection_handler.remove_connection(name)      end diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb index b8b8684cff..38e4fbec8b 100644 --- a/activerecord/lib/active_record/errors.rb +++ b/activerecord/lib/active_record/errors.rb @@ -285,6 +285,16 @@ module ActiveRecord    class TransactionIsolationError < ActiveRecordError    end +  # TransactionSerializationError will be raised when a transaction is rolled +  # back by the database due to a serialization failure or a deadlock. +  # +  # See the following: +  # +  # * http://www.postgresql.org/docs/current/static/transaction-iso.html +  # * https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html#error_er_lock_deadlock +  class TransactionSerializationError < ActiveRecordError +  end +    # IrreversibleOrderError is raised when a relation's order is too complex for    # +reverse_order+ to automatically reverse.    class IrreversibleOrderError < ActiveRecordError diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb index bb7d8c3031..f33456a744 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -6,9 +6,9 @@ module ActiveRecord    module VERSION      MAJOR = 5 -    MINOR = 0 +    MINOR = 1      TINY  = 0 -    PRE   = "beta4" +    PRE   = "alpha"      STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")    end diff --git a/activerecord/lib/active_record/internal_metadata.rb b/activerecord/lib/active_record/internal_metadata.rb index 81db96bffd..17a5dc1d1b 100644 --- a/activerecord/lib/active_record/internal_metadata.rb +++ b/activerecord/lib/active_record/internal_metadata.rb @@ -19,7 +19,7 @@ module ActiveRecord        end        def []=(key, value) -        first_or_initialize(key: key).update_attributes!(value: value) +        find_or_initialize_by(key: key).update_attributes!(value: value)        end        def [](key) diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index 1e37ffefc6..67b8efac66 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -184,9 +184,12 @@ module ActiveRecord        end      end + +    # In de/serialize we change `nil` to 0, so that we can allow passing +    # `nil` values to `lock_version`, and not result in `ActiveRecord::StaleObjectError` +    # during update record.      class LockingType < DelegateClass(Type::Value) # :nodoc:        def deserialize(value) -        # `nil` *should* be changed to 0          super.to_i        end diff --git a/activerecord/lib/active_record/log_subscriber.rb b/activerecord/lib/active_record/log_subscriber.rb index efa2a4df02..8e32af1c49 100644 --- a/activerecord/lib/active_record/log_subscriber.rb +++ b/activerecord/lib/active_record/log_subscriber.rb @@ -22,7 +22,11 @@ module ActiveRecord      def render_bind(attribute)        value = if attribute.type.binary? && attribute.value -        "<#{attribute.value.bytesize} bytes of binary data>" +        if attribute.value.is_a?(Hash) +          "<#{attribute.value_for_database.to_s.bytesize} bytes of binary data>" +        else +          "<#{attribute.value.bytesize} bytes of binary data>" +        end        else          attribute.value_for_database        end diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index f30861b4d0..81fe053fe1 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -166,13 +166,13 @@ module ActiveRecord    class EnvironmentMismatchError < ActiveRecordError      def initialize(current: nil, stored: nil)        msg =  "You are attempting to modify a database that was last run in `#{ stored }` environment.\n" -      msg << "You are running in `#{ current }` environment." +      msg << "You are running in `#{ current }` environment. "        msg << "If you are sure you want to continue, first set the environment using:\n\n"        msg << "\tbin/rails db:environment:set"        if defined?(Rails.env) -        super("#{msg} RAILS_ENV=#{::Rails.env}") +        super("#{msg} RAILS_ENV=#{::Rails.env}\n\n")        else -        super(msg) +        super("#{msg}\n\n")        end      end    end diff --git a/activerecord/lib/active_record/migration/compatibility.rb b/activerecord/lib/active_record/migration/compatibility.rb index 69bd9ff1cf..74833f938f 100644 --- a/activerecord/lib/active_record/migration/compatibility.rb +++ b/activerecord/lib/active_record/migration/compatibility.rb @@ -11,7 +11,7 @@ module ActiveRecord          const_get(name)        end -      V5_0 = Current +      V5_1 = Current        module FourTwoShared          module TableDefinition @@ -102,6 +102,9 @@ module ActiveRecord          end        end +      class V5_0 < V5_1 +      end +        class V4_2 < V5_0          # 4.2 is defined as a module because it needs to be shared with          # Legacy. When the time comes, V5_0 should be defined straight diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 54c9af4898..d6d92b8607 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -37,7 +37,11 @@ module ActiveRecord      # Note: not all valid {Relation#select}[rdoc-ref:QueryMethods#select] expressions are valid #count expressions. The specifics differ      # between databases. In invalid cases, an error from the database is thrown.      def count(column_name = nil) -      calculate(:count, column_name) +      if block_given? +        to_a.count { |*block_args| yield(*block_args) } +      else +        calculate(:count, column_name) +      end      end      # Calculates the average value on a given column. Returns +nil+ if there's @@ -89,7 +93,7 @@ module ActiveRecord      #      # There are two basic forms of output:      # -    # * Single aggregate value: The single value is type cast to Fixnum for COUNT, Float +    # * Single aggregate value: The single value is type cast to Integer for COUNT, Float      #   for AVG, and the given column's type for everything else.      #      # * Grouped values: This returns an ordered hash of the values and groups them. It diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index 301718b874..d769376d1a 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -50,10 +50,6 @@ module ActiveRecord        def header(stream)          define_params = @version ? "version: #{@version}" : "" -        if stream.respond_to?(:external_encoding) && stream.external_encoding -          stream.puts "# encoding: #{stream.external_encoding.name}" -        end -          stream.puts <<HEADER  # This file is auto-generated from the current state of the database. Instead  # of editing this file, please use the migrations feature of Active Record to diff --git a/activerecord/lib/active_record/suppressor.rb b/activerecord/lib/active_record/suppressor.rb index 8ec4b48d31..d9acb1a1dc 100644 --- a/activerecord/lib/active_record/suppressor.rb +++ b/activerecord/lib/active_record/suppressor.rb @@ -30,10 +30,11 @@ module ActiveRecord      module ClassMethods        def suppress(&block) +        previous_state = SuppressorRegistry.suppressed[name]          SuppressorRegistry.suppressed[name] = true          yield        ensure -        SuppressorRegistry.suppressed[name] = false +        SuppressorRegistry.suppressed[name] = previous_state        end      end diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb index 4ff0740cfb..a3a5241780 100644 --- a/activerecord/lib/active_record/type/serialized.rb +++ b/activerecord/lib/active_record/type/serialized.rb @@ -32,7 +32,7 @@ module ActiveRecord        def changed_in_place?(raw_old_value, value)          return false if value.nil? -        raw_new_value = serialize(value) +        raw_new_value = encoded(value)          raw_old_value.nil? != raw_new_value.nil? ||            subtype.changed_in_place?(raw_old_value, raw_new_value)        end @@ -52,6 +52,12 @@ module ActiveRecord        def default_value?(value)          value == coder.load(nil)        end + +      def encoded(value) +        unless default_value?(value) +          coder.dump(value) +        end +      end      end    end  end | 
