From f2e0925ab7279c5a7c0a5ba7574a09d9e5550fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 21 Dec 2012 14:15:33 -0300 Subject: [PATCH] Serialized attribute can be serialized in an integer column Fix #8575 --- activerecord/CHANGELOG.md | 9 ++++++-- .../attribute_methods/serialization.rb | 8 +++++++ .../test/cases/serialized_attribute_test.rb | 11 +++++++++- activerecord/test/models/person.rb | 21 +++++++++++++++++++ activerecord/test/schema/schema.rb | 1 + 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 959a88876d..442b11dad9 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,12 +1,17 @@ ## Rails 4.0.0 (unreleased) ## +* Serialized attributes can be serialized in integer columns. + Fix #8575. + + *Rafael Mendonça França* + * Keep index names when using `alter_table` with sqlite3. - Fix #3489 + Fix #3489. *Yves Senn* * Add ability for postgresql adapter to disable user triggers in `disable_referential_integrity`. - Fix #5523 + Fix #5523. *Gary S. Weaver* diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb index 47d4a938af..25d62fdb85 100644 --- a/activerecord/lib/active_record/attribute_methods/serialization.rb +++ b/activerecord/lib/active_record/attribute_methods/serialization.rb @@ -112,6 +112,14 @@ def type_cast_attribute_for_write(column, value) end end + def _field_changed?(attr, old, value) + if self.class.serialized_attributes.include?(attr) + old != value + else + super + end + end + def read_attribute_before_type_cast(attr_name) if self.class.serialized_attributes.include?(attr_name) super.unserialized_value diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb index 6962da298e..295c7e13fa 100644 --- a/activerecord/test/cases/serialized_attribute_test.rb +++ b/activerecord/test/cases/serialized_attribute_test.rb @@ -1,5 +1,6 @@ -require "cases/helper" +require 'cases/helper' require 'models/topic' +require 'models/person' require 'bcrypt' class SerializedAttributeTest < ActiveRecord::TestCase @@ -225,4 +226,12 @@ def test_serialize_attribute_via_select_method_when_time_zone_available ensure ActiveRecord::Base.time_zone_aware_attributes = false end + + def test_serialize_attribute_can_be_serialized_in_an_integer_column + insures = ['life'] + person = SerializedPerson.new(first_name: 'David', insures: insures) + assert person.save + person = person.reload + assert_equal(insures, person.insures) + end end diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb index 6ad0cf6987..f9684b0bcd 100644 --- a/activerecord/test/models/person.rb +++ b/activerecord/test/models/person.rb @@ -100,3 +100,24 @@ def best_friend_first_name=(new_name) assign_attributes({ :best_friend_attributes => { :first_name => new_name } }) end end + +class Insure + INSURES = %W{life annuality} + + def self.load mask + INSURES.select do |insure| + (1 << INSURES.index(insure)) & mask > 0 + end + end + + def self.dump insures + numbers = insures.map { |insure| INSURES.index(insure) } + numbers.inject(0) { |sum, n| sum + (1 << n) } + end +end + +class SerializedPerson < ActiveRecord::Base + self.table_name = 'people' + + serialize :insures, Insure +end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index af14bc7bd5..46219c53db 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -494,6 +494,7 @@ def create_table(*args, &block) t.integer :followers_count, :default => 0 t.references :best_friend t.references :best_friend_of + t.integer :insures, null: false, default: 0 t.timestamps end