activerecord 3.1.12 → 3.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG.md +6263 -103
- data/README.rdoc +2 -2
- data/examples/performance.rb +55 -31
- data/lib/active_record.rb +28 -2
- data/lib/active_record/aggregations.rb +2 -2
- data/lib/active_record/associations.rb +82 -69
- data/lib/active_record/associations/association.rb +2 -37
- data/lib/active_record/associations/association_scope.rb +3 -30
- data/lib/active_record/associations/builder/association.rb +6 -4
- data/lib/active_record/associations/builder/belongs_to.rb +3 -3
- data/lib/active_record/associations/builder/collection_association.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +5 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -16
- data/lib/active_record/associations/collection_association.rb +55 -28
- data/lib/active_record/associations/collection_proxy.rb +1 -35
- data/lib/active_record/associations/has_many_association.rb +5 -1
- data/lib/active_record/associations/has_many_through_association.rb +11 -8
- data/lib/active_record/associations/join_dependency.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +3 -1
- data/lib/active_record/attribute_assignment.rb +221 -0
- data/lib/active_record/attribute_methods.rb +212 -32
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
- data/lib/active_record/attribute_methods/dirty.rb +3 -3
- data/lib/active_record/attribute_methods/primary_key.rb +62 -25
- data/lib/active_record/attribute_methods/read.rb +69 -80
- data/lib/active_record/attribute_methods/serialization.rb +89 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +9 -14
- data/lib/active_record/attribute_methods/write.rb +27 -5
- data/lib/active_record/autosave_association.rb +23 -8
- data/lib/active_record/base.rb +223 -1712
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +98 -132
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +82 -29
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +13 -42
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +7 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +36 -25
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -13
- data/lib/active_record/connection_adapters/abstract_adapter.rb +78 -43
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +653 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +138 -578
- data/lib/active_record/connection_adapters/mysql_adapter.rb +86 -658
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +144 -94
- data/lib/active_record/connection_adapters/schema_cache.rb +50 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -6
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +43 -22
- data/lib/active_record/counter_cache.rb +1 -1
- data/lib/active_record/dynamic_matchers.rb +79 -0
- data/lib/active_record/errors.rb +11 -1
- data/lib/active_record/explain.rb +83 -0
- data/lib/active_record/explain_subscriber.rb +21 -0
- data/lib/active_record/fixtures.rb +31 -76
- data/lib/active_record/fixtures/file.rb +65 -0
- data/lib/active_record/identity_map.rb +1 -7
- data/lib/active_record/inheritance.rb +167 -0
- data/lib/active_record/integration.rb +49 -0
- data/lib/active_record/locking/optimistic.rb +19 -11
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +3 -3
- data/lib/active_record/migration.rb +38 -29
- data/lib/active_record/migration/command_recorder.rb +7 -7
- data/lib/active_record/model_schema.rb +362 -0
- data/lib/active_record/nested_attributes.rb +3 -2
- data/lib/active_record/persistence.rb +51 -1
- data/lib/active_record/querying.rb +58 -0
- data/lib/active_record/railtie.rb +24 -28
- data/lib/active_record/railties/controller_runtime.rb +3 -1
- data/lib/active_record/railties/databases.rake +133 -77
- data/lib/active_record/readonly_attributes.rb +26 -0
- data/lib/active_record/reflection.rb +7 -15
- data/lib/active_record/relation.rb +78 -35
- data/lib/active_record/relation/batches.rb +5 -2
- data/lib/active_record/relation/calculations.rb +27 -6
- data/lib/active_record/relation/delegation.rb +49 -0
- data/lib/active_record/relation/finder_methods.rb +5 -4
- data/lib/active_record/relation/predicate_builder.rb +13 -16
- data/lib/active_record/relation/query_methods.rb +59 -4
- data/lib/active_record/result.rb +1 -1
- data/lib/active_record/sanitization.rb +194 -0
- data/lib/active_record/schema_dumper.rb +5 -2
- data/lib/active_record/scoping.rb +152 -0
- data/lib/active_record/scoping/default.rb +140 -0
- data/lib/active_record/scoping/named.rb +202 -0
- data/lib/active_record/serialization.rb +1 -43
- data/lib/active_record/serializers/xml_serializer.rb +2 -44
- data/lib/active_record/session_store.rb +11 -11
- data/lib/active_record/store.rb +50 -0
- data/lib/active_record/test_case.rb +11 -7
- data/lib/active_record/timestamp.rb +16 -3
- data/lib/active_record/transactions.rb +5 -5
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/validations.rb +1 -1
- data/lib/active_record/validations/associated.rb +5 -4
- data/lib/active_record/validations/uniqueness.rb +4 -4
- data/lib/active_record/version.rb +3 -3
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +1 -5
- metadata +48 -38
- checksums.yaml +0 -7
- data/lib/active_record/named_scope.rb +0 -200
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_support/deprecation'
|
3
|
+
|
4
|
+
module ActiveRecord
|
5
|
+
module AttributeMethods
|
6
|
+
module DeprecatedUnderscoreRead
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
attribute_method_prefix "_"
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
protected
|
15
|
+
|
16
|
+
def define_method__attribute(attr_name)
|
17
|
+
# Do nothing, let it hit method missing instead.
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def _attribute(attr_name)
|
24
|
+
ActiveSupport::Deprecation.warn(
|
25
|
+
"You have called '_#{attr_name}'. This is deprecated. Please use " \
|
26
|
+
"either '#{attr_name}' or read_attribute('#{attr_name}')."
|
27
|
+
)
|
28
|
+
read_attribute(attr_name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -34,9 +34,9 @@ module ActiveRecord
|
|
34
34
|
@previously_changed = changes
|
35
35
|
@changed_attributes.clear
|
36
36
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
rescue
|
38
|
+
IdentityMap.remove(self) if IdentityMap.enabled?
|
39
|
+
raise
|
40
40
|
end
|
41
41
|
|
42
42
|
# <tt>reload</tt> the record and clears changed attributes.
|
@@ -5,11 +5,44 @@ module ActiveRecord
|
|
5
5
|
|
6
6
|
# Returns this record's primary key value wrapped in an Array if one is available
|
7
7
|
def to_key
|
8
|
-
key =
|
8
|
+
key = self.id
|
9
9
|
[key] if key
|
10
10
|
end
|
11
11
|
|
12
|
+
# Returns the primary key value
|
13
|
+
def id
|
14
|
+
read_attribute(self.class.primary_key)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Sets the primary key value
|
18
|
+
def id=(value)
|
19
|
+
write_attribute(self.class.primary_key, value)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Queries the primary key value
|
23
|
+
def id?
|
24
|
+
query_attribute(self.class.primary_key)
|
25
|
+
end
|
26
|
+
|
12
27
|
module ClassMethods
|
28
|
+
def define_method_attribute(attr_name)
|
29
|
+
super
|
30
|
+
|
31
|
+
if attr_name == primary_key && attr_name != 'id'
|
32
|
+
generated_attribute_methods.send(:alias_method, :id, primary_key)
|
33
|
+
generated_external_attribute_methods.module_eval <<-CODE, __FILE__, __LINE__
|
34
|
+
def id(v, attributes, attributes_cache, attr_name)
|
35
|
+
attr_name = '#{primary_key}'
|
36
|
+
send(attr_name, attributes[attr_name], attributes, attributes_cache, attr_name)
|
37
|
+
end
|
38
|
+
CODE
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def dangerous_attribute_method?(method_name)
|
43
|
+
super && !['id', 'id=', 'id?'].include?(method_name)
|
44
|
+
end
|
45
|
+
|
13
46
|
# Defines the primary key field -- can be overridden in subclasses. Overwriting will negate any effect of the
|
14
47
|
# primary_key_prefix_type setting, though.
|
15
48
|
def primary_key
|
@@ -23,11 +56,11 @@ module ActiveRecord
|
|
23
56
|
end
|
24
57
|
|
25
58
|
def reset_primary_key #:nodoc:
|
26
|
-
|
27
|
-
base_class.
|
28
|
-
|
29
|
-
|
30
|
-
|
59
|
+
if self == base_class
|
60
|
+
self.primary_key = get_primary_key(base_class.name)
|
61
|
+
else
|
62
|
+
self.primary_key = base_class.primary_key
|
63
|
+
end
|
31
64
|
end
|
32
65
|
|
33
66
|
def get_primary_key(base_name) #:nodoc:
|
@@ -39,37 +72,41 @@ module ActiveRecord
|
|
39
72
|
when :table_name_with_underscore
|
40
73
|
base_name.foreign_key
|
41
74
|
else
|
42
|
-
if ActiveRecord::Base != self &&
|
43
|
-
connection.
|
75
|
+
if ActiveRecord::Base != self && table_exists?
|
76
|
+
connection.schema_cache.primary_keys[table_name]
|
44
77
|
else
|
45
78
|
'id'
|
46
79
|
end
|
47
80
|
end
|
48
81
|
end
|
49
82
|
|
50
|
-
|
51
|
-
|
52
|
-
# Attribute writer for the primary key column
|
53
|
-
def primary_key=(value)
|
54
|
-
@quoted_primary_key = nil
|
55
|
-
@primary_key = value
|
56
|
-
|
57
|
-
connection_pool.primary_keys[table_name] = @primary_key if connected?
|
83
|
+
def original_primary_key #:nodoc:
|
84
|
+
deprecated_original_property_getter :primary_key
|
58
85
|
end
|
59
86
|
|
60
|
-
# Sets the name of the primary key column
|
61
|
-
# or (if the value is nil or false) to the value returned by the given
|
62
|
-
# block.
|
87
|
+
# Sets the name of the primary key column.
|
63
88
|
#
|
64
89
|
# class Project < ActiveRecord::Base
|
65
|
-
#
|
90
|
+
# self.primary_key = "sysid"
|
66
91
|
# end
|
67
|
-
|
92
|
+
#
|
93
|
+
# You can also define the primary_key method yourself:
|
94
|
+
#
|
95
|
+
# class Project < ActiveRecord::Base
|
96
|
+
# def self.primary_key
|
97
|
+
# "foo_" + super
|
98
|
+
# end
|
99
|
+
# end
|
100
|
+
# Project.primary_key # => "foo_id"
|
101
|
+
def primary_key=(value)
|
102
|
+
@original_primary_key = @primary_key if defined?(@primary_key)
|
103
|
+
@primary_key = value && value.to_s
|
104
|
+
@quoted_primary_key = nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def set_primary_key(value = nil, &block) #:nodoc:
|
108
|
+
deprecated_property_setter :primary_key, value, block
|
68
109
|
@quoted_primary_key = nil
|
69
|
-
@primary_key ||= ''
|
70
|
-
self.original_primary_key = @primary_key
|
71
|
-
value &&= value.to_s
|
72
|
-
self.primary_key = block_given? ? instance_eval(&block) : value
|
73
110
|
end
|
74
111
|
end
|
75
112
|
end
|
@@ -6,13 +6,8 @@ module ActiveRecord
|
|
6
6
|
ATTRIBUTE_TYPES_CACHED_BY_DEFAULT = [:datetime, :timestamp, :time, :date]
|
7
7
|
|
8
8
|
included do
|
9
|
-
attribute_method_suffix ""
|
10
|
-
|
11
9
|
cattr_accessor :attribute_types_cached_by_default, :instance_writer => false
|
12
10
|
self.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
|
13
|
-
|
14
|
-
# Undefine id so it can be used as an attribute name
|
15
|
-
undef_method(:id) if method_defined?(:id)
|
16
11
|
end
|
17
12
|
|
18
13
|
module ClassMethods
|
@@ -34,109 +29,103 @@ module ActiveRecord
|
|
34
29
|
cached_attributes.include?(attr_name)
|
35
30
|
end
|
36
31
|
|
32
|
+
def undefine_attribute_methods
|
33
|
+
if base_class == self
|
34
|
+
generated_external_attribute_methods.module_eval do
|
35
|
+
instance_methods.each { |m| undef_method(m) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
37
42
|
protected
|
43
|
+
# We want to generate the methods via module_eval rather than define_method,
|
44
|
+
# because define_method is slower on dispatch and uses more memory (because it
|
45
|
+
# creates a closure).
|
46
|
+
#
|
47
|
+
# But sometimes the database might return columns with characters that are not
|
48
|
+
# allowed in normal method names (like 'my_column(omg)'. So to work around this
|
49
|
+
# we first define with the __temp__ identifier, and then use alias method to
|
50
|
+
# rename it to what we want.
|
38
51
|
def define_method_attribute(attr_name)
|
39
|
-
|
40
|
-
define_read_method_for_serialized_attribute(attr_name)
|
41
|
-
else
|
42
|
-
define_read_method(attr_name, attr_name, columns_hash[attr_name])
|
43
|
-
end
|
52
|
+
cast_code = attribute_cast_code(attr_name)
|
44
53
|
|
45
|
-
|
46
|
-
|
47
|
-
|
54
|
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
55
|
+
def __temp__
|
56
|
+
#{internal_attribute_access_code(attr_name, cast_code)}
|
57
|
+
end
|
58
|
+
alias_method '#{attr_name}', :__temp__
|
59
|
+
undef_method :__temp__
|
60
|
+
STR
|
61
|
+
|
62
|
+
generated_external_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
63
|
+
def __temp__(v, attributes, attributes_cache, attr_name)
|
64
|
+
#{external_attribute_access_code(attr_name, cast_code)}
|
65
|
+
end
|
66
|
+
alias_method '#{attr_name}', :__temp__
|
67
|
+
undef_method :__temp__
|
68
|
+
STR
|
48
69
|
end
|
49
70
|
|
50
71
|
private
|
51
72
|
def cacheable_column?(column)
|
52
|
-
|
53
|
-
end
|
54
|
-
|
55
|
-
# Define read method for serialized attribute.
|
56
|
-
def define_read_method_for_serialized_attribute(attr_name)
|
57
|
-
access_code = "@attributes_cache['#{attr_name}'] ||= @attributes['#{attr_name}']"
|
58
|
-
generated_attribute_methods.module_eval("def _#{attr_name}; #{access_code}; end; alias #{attr_name} _#{attr_name}", __FILE__, __LINE__)
|
73
|
+
attribute_types_cached_by_default.include?(column.type)
|
59
74
|
end
|
60
75
|
|
61
|
-
|
62
|
-
|
63
|
-
# we still define #id as an accessor for the key
|
64
|
-
def define_read_method(method_name, attr_name, column)
|
65
|
-
cast_code = column.type_cast_code('v')
|
66
|
-
access_code = "(v=@attributes['#{attr_name}']) && #{cast_code}"
|
76
|
+
def internal_attribute_access_code(attr_name, cast_code)
|
77
|
+
access_code = "(v=@attributes[attr_name]) && #{cast_code}"
|
67
78
|
|
68
|
-
unless attr_name
|
69
|
-
access_code.insert(0, "missing_attribute(
|
79
|
+
unless attr_name == primary_key
|
80
|
+
access_code.insert(0, "missing_attribute(attr_name, caller) unless @attributes.has_key?(attr_name); ")
|
70
81
|
end
|
71
82
|
|
72
83
|
if cache_attribute?(attr_name)
|
73
|
-
access_code = "@attributes_cache[
|
84
|
+
access_code = "@attributes_cache[attr_name] ||= (#{access_code})"
|
74
85
|
end
|
75
86
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
if
|
83
|
-
|
84
|
-
def _#{method_name}
|
85
|
-
#{access_code}
|
86
|
-
end
|
87
|
-
|
88
|
-
alias #{method_name} _#{method_name}
|
89
|
-
STR
|
90
|
-
else
|
91
|
-
generated_attribute_methods.module_eval do
|
92
|
-
define_method("_#{method_name}") { eval(access_code) }
|
93
|
-
alias_method(method_name, "_#{method_name}")
|
94
|
-
end
|
87
|
+
"attr_name = '#{attr_name}'; #{access_code}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def external_attribute_access_code(attr_name, cast_code)
|
91
|
+
access_code = "v && #{cast_code}"
|
92
|
+
|
93
|
+
if cache_attribute?(attr_name)
|
94
|
+
access_code = "attributes_cache[attr_name] ||= (#{access_code})"
|
95
95
|
end
|
96
|
+
|
97
|
+
access_code
|
98
|
+
end
|
99
|
+
|
100
|
+
def attribute_cast_code(attr_name)
|
101
|
+
columns_hash[attr_name].type_cast_code('v')
|
96
102
|
end
|
97
103
|
end
|
98
104
|
|
99
105
|
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
|
100
106
|
# "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
|
101
107
|
def read_attribute(attr_name)
|
102
|
-
|
103
|
-
if respond_to? method
|
104
|
-
send method if @attributes.has_key?(attr_name.to_s)
|
105
|
-
else
|
106
|
-
_read_attribute attr_name
|
107
|
-
end
|
108
|
-
end
|
108
|
+
return unless attr_name
|
109
109
|
|
110
|
-
def _read_attribute(attr_name)
|
111
110
|
attr_name = attr_name.to_s
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
if
|
116
|
-
|
117
|
-
unserialize_attribute(attr_name)
|
118
|
-
else
|
119
|
-
column.type_cast(value)
|
120
|
-
end
|
121
|
-
else
|
122
|
-
value
|
111
|
+
methods = self.class.generated_external_attribute_methods
|
112
|
+
|
113
|
+
if methods.method_defined?(attr_name)
|
114
|
+
if @attributes.has_key?(attr_name) || attr_name == 'id'
|
115
|
+
methods.send(attr_name, @attributes[attr_name], @attributes, @attributes_cache, attr_name)
|
123
116
|
end
|
117
|
+
elsif !self.class.attribute_methods_generated?
|
118
|
+
# If we haven't generated the caster methods yet, do that and
|
119
|
+
# then try again
|
120
|
+
self.class.define_attribute_methods
|
121
|
+
read_attribute(attr_name)
|
122
|
+
else
|
123
|
+
# If we get here, the attribute has no associated DB column, so
|
124
|
+
# just return it verbatim.
|
125
|
+
@attributes[attr_name]
|
124
126
|
end
|
125
127
|
end
|
126
128
|
|
127
|
-
# Returns true if the attribute is of a text column and marked for serialization.
|
128
|
-
def unserializable_attribute?(attr_name, column)
|
129
|
-
column.text? && self.class.serialized_attributes.include?(attr_name)
|
130
|
-
end
|
131
|
-
|
132
|
-
# Returns the unserialized object of the attribute.
|
133
|
-
def unserialize_attribute(attr_name)
|
134
|
-
coder = self.class.serialized_attributes[attr_name]
|
135
|
-
unserialized_object = coder.load(@attributes[attr_name])
|
136
|
-
|
137
|
-
@attributes.frozen? ? unserialized_object : @attributes[attr_name] = unserialized_object
|
138
|
-
end
|
139
|
-
|
140
129
|
private
|
141
130
|
def attribute(attribute_name)
|
142
131
|
read_attribute(attribute_name)
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module AttributeMethods
|
3
|
+
module Serialization
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
# Returns a hash of all the attributes that have been specified for serialization as
|
8
|
+
# keys and their class restriction as values.
|
9
|
+
class_attribute :serialized_attributes
|
10
|
+
self.serialized_attributes = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
class Attribute < Struct.new(:coder, :value, :state)
|
14
|
+
def unserialized_value
|
15
|
+
state == :serialized ? unserialize : value
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialized_value
|
19
|
+
state == :unserialized ? serialize : value
|
20
|
+
end
|
21
|
+
|
22
|
+
def unserialize
|
23
|
+
self.state = :unserialized
|
24
|
+
self.value = coder.load(value)
|
25
|
+
end
|
26
|
+
|
27
|
+
def serialize
|
28
|
+
self.state = :serialized
|
29
|
+
self.value = coder.dump(value)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module ClassMethods
|
34
|
+
# If you have an attribute that needs to be saved to the database as an object, and retrieved as the same object,
|
35
|
+
# then specify the name of that attribute using this method and it will be handled automatically.
|
36
|
+
# The serialization is done through YAML. If +class_name+ is specified, the serialized object must be of that
|
37
|
+
# class on retrieval or SerializationTypeMismatch will be raised.
|
38
|
+
#
|
39
|
+
# ==== Parameters
|
40
|
+
#
|
41
|
+
# * +attr_name+ - The field name that should be serialized.
|
42
|
+
# * +class_name+ - Optional, class name that the object type should be equal to.
|
43
|
+
#
|
44
|
+
# ==== Example
|
45
|
+
# # Serialize a preferences attribute
|
46
|
+
# class User < ActiveRecord::Base
|
47
|
+
# serialize :preferences
|
48
|
+
# end
|
49
|
+
def serialize(attr_name, class_name = Object)
|
50
|
+
coder = if [:load, :dump].all? { |x| class_name.respond_to?(x) }
|
51
|
+
class_name
|
52
|
+
else
|
53
|
+
Coders::YAMLColumn.new(class_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
# merge new serialized attribute and create new hash to ensure that each class in inheritance hierarchy
|
57
|
+
# has its own hash of own serialized attributes
|
58
|
+
self.serialized_attributes = serialized_attributes.merge(attr_name.to_s => coder)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def attribute_cast_code(attr_name)
|
64
|
+
if serialized_attributes.include?(attr_name)
|
65
|
+
"v.unserialized_value"
|
66
|
+
else
|
67
|
+
super
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def set_serialized_attributes
|
73
|
+
self.class.serialized_attributes.each do |key, coder|
|
74
|
+
if @attributes.key?(key)
|
75
|
+
@attributes[key] = Attribute.new(coder, @attributes[key], :serialized)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def type_cast_attribute_for_write(column, value)
|
81
|
+
if column && coder = self.class.serialized_attributes[column.name]
|
82
|
+
Attribute.new(coder, value, :unserialized)
|
83
|
+
else
|
84
|
+
super
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|