sequel 3.45.0 → 3.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG +34 -0
- data/README.rdoc +6 -0
- data/Rakefile +46 -33
- data/doc/release_notes/3.46.0.txt +122 -0
- data/doc/schema_modification.rdoc +42 -6
- data/doc/security.rdoc +379 -0
- data/doc/transactions.rdoc +1 -1
- data/lib/sequel/adapters/jdbc/as400.rb +1 -0
- data/lib/sequel/adapters/jdbc/h2.rb +11 -0
- data/lib/sequel/adapters/mysql2.rb +3 -9
- data/lib/sequel/adapters/postgres.rb +34 -2
- data/lib/sequel/adapters/shared/cubrid.rb +5 -0
- data/lib/sequel/adapters/shared/mssql.rb +27 -3
- data/lib/sequel/adapters/shared/mysql.rb +25 -4
- data/lib/sequel/adapters/shared/sqlite.rb +12 -1
- data/lib/sequel/connection_pool.rb +3 -3
- data/lib/sequel/connection_pool/sharded_threaded.rb +7 -8
- data/lib/sequel/connection_pool/threaded.rb +7 -8
- data/lib/sequel/core.rb +5 -2
- data/lib/sequel/database.rb +1 -1
- data/lib/sequel/database/connecting.rb +7 -7
- data/lib/sequel/database/features.rb +88 -0
- data/lib/sequel/database/misc.rb +14 -64
- data/lib/sequel/database/query.rb +0 -332
- data/lib/sequel/database/schema_generator.rb +36 -3
- data/lib/sequel/database/schema_methods.rb +48 -12
- data/lib/sequel/database/transactions.rb +344 -0
- data/lib/sequel/dataset/actions.rb +24 -9
- data/lib/sequel/dataset/mutation.rb +20 -0
- data/lib/sequel/dataset/query.rb +0 -17
- data/lib/sequel/dataset/sql.rb +7 -0
- data/lib/sequel/exceptions.rb +10 -6
- data/lib/sequel/extensions/_pretty_table.rb +2 -2
- data/lib/sequel/extensions/looser_typecasting.rb +10 -0
- data/lib/sequel/extensions/migration.rb +5 -2
- data/lib/sequel/model.rb +1 -1
- data/lib/sequel/model/associations.rb +16 -14
- data/lib/sequel/model/base.rb +14 -2
- data/lib/sequel/plugins/composition.rb +3 -3
- data/lib/sequel/plugins/dirty.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +3 -0
- data/lib/sequel/plugins/serialization.rb +7 -17
- data/lib/sequel/plugins/string_stripper.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +1 -1
- data/lib/sequel/sql.rb +3 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +21 -0
- data/spec/adapters/postgres_spec.rb +35 -8
- data/spec/core/database_spec.rb +4 -0
- data/spec/core/dataset_spec.rb +48 -2
- data/spec/core/schema_generator_spec.rb +10 -1
- data/spec/core/schema_spec.rb +69 -0
- data/spec/extensions/composition_spec.rb +21 -2
- data/spec/extensions/dirty_spec.rb +17 -10
- data/spec/extensions/eager_each_spec.rb +4 -1
- data/spec/extensions/looser_typecasting_spec.rb +16 -19
- data/spec/extensions/migration_spec.rb +7 -1
- data/spec/extensions/serialization_spec.rb +22 -0
- data/spec/extensions/single_table_inheritance_spec.rb +3 -2
- data/spec/extensions/validation_helpers_spec.rb +6 -0
- data/spec/integration/dataset_test.rb +5 -0
- data/spec/integration/schema_test.rb +16 -0
- data/spec/model/associations_spec.rb +40 -0
- data/spec/model/base_spec.rb +21 -1
- data/spec/model/record_spec.rb +3 -0
- metadata +14 -10
@@ -10,7 +10,7 @@ module Sequel
|
|
10
10
|
# Action methods defined by Sequel that execute code on the database.
|
11
11
|
ACTION_METHODS = (<<-METHS).split.map{|x| x.to_sym}
|
12
12
|
<< [] []= all avg count columns columns! delete each
|
13
|
-
empty? fetch_rows first get import insert insert_multiple interval last
|
13
|
+
empty? fetch_rows first first! get import insert insert_multiple interval last
|
14
14
|
map max min multi_insert paged_each range select_hash select_hash_groups select_map select_order_map
|
15
15
|
set single_record single_value sum to_csv to_hash to_hash_groups truncate update
|
16
16
|
METHS
|
@@ -176,8 +176,13 @@ module Sequel
|
|
176
176
|
# matching records up to that limit. If no argument is passed,
|
177
177
|
# it returns the first matching record. If any other type of
|
178
178
|
# argument(s) is passed, it is given to filter and the
|
179
|
-
# first matching record is returned.
|
180
|
-
# to filter the dataset before returning anything.
|
179
|
+
# first matching record is returned. If a block is given, it is used
|
180
|
+
# to filter the dataset before returning anything.
|
181
|
+
#
|
182
|
+
# If there are no records in the dataset, returns nil (or an empty
|
183
|
+
# array if an integer argument is given).
|
184
|
+
#
|
185
|
+
# Examples:
|
181
186
|
#
|
182
187
|
# DB[:table].first # SELECT * FROM table LIMIT 1
|
183
188
|
# # => {:id=>7}
|
@@ -217,6 +222,12 @@ module Sequel
|
|
217
222
|
end
|
218
223
|
end
|
219
224
|
|
225
|
+
# Calls first. If first returns nil (signaling that no
|
226
|
+
# row matches), raise a Sequel::NoMatchingRow exception.
|
227
|
+
def first!(*args, &block)
|
228
|
+
first(*args, &block) || raise(Sequel::NoMatchingRow)
|
229
|
+
end
|
230
|
+
|
220
231
|
# Return the column value for the first matching record in the dataset.
|
221
232
|
# Raises an error if both an argument and block is given.
|
222
233
|
#
|
@@ -869,21 +880,25 @@ module Sequel
|
|
869
880
|
# Return a plain symbol given a potentially qualified or aliased symbol,
|
870
881
|
# specifying the symbol that is likely to be used as the hash key
|
871
882
|
# for the column when records are returned.
|
872
|
-
def hash_key_symbol(s)
|
883
|
+
def hash_key_symbol(s, recursing=false)
|
873
884
|
case s
|
874
885
|
when Symbol
|
875
886
|
_, c, a = split_symbol(s)
|
876
887
|
(a || c).to_sym
|
877
888
|
when SQL::Identifier, SQL::Wrapper
|
878
|
-
hash_key_symbol(s.value)
|
889
|
+
hash_key_symbol(s.value, true)
|
879
890
|
when SQL::QualifiedIdentifier
|
880
|
-
hash_key_symbol(s.column)
|
891
|
+
hash_key_symbol(s.column, true)
|
881
892
|
when SQL::AliasedExpression
|
882
|
-
hash_key_symbol(s.aliaz)
|
893
|
+
hash_key_symbol(s.aliaz, true)
|
883
894
|
when String
|
884
|
-
|
895
|
+
if recursing
|
896
|
+
s.to_sym
|
897
|
+
else
|
898
|
+
raise(Error, "#{s.inspect} is not supported, should be a Symbol, SQL::Identifier, SQL::QualifiedIdentifier, or SQL::AliasedExpression")
|
899
|
+
end
|
885
900
|
else
|
886
|
-
raise(Error, "#{s.inspect} is not supported, should be a Symbol,
|
901
|
+
raise(Error, "#{s.inspect} is not supported, should be a Symbol, SQL::Identifier, SQL::QualifiedIdentifier, or SQL::AliasedExpression")
|
887
902
|
end
|
888
903
|
end
|
889
904
|
|
@@ -11,6 +11,9 @@ module Sequel
|
|
11
11
|
# Setup mutation (e.g. filter!) methods. These operate the same as the
|
12
12
|
# non-! methods, but replace the options of the current dataset with the
|
13
13
|
# options of the resulting dataset.
|
14
|
+
#
|
15
|
+
# Do not call this method with untrusted input, as that can result in
|
16
|
+
# arbitrary code execution.
|
14
17
|
def self.def_mutation_method(*meths)
|
15
18
|
options = meths.pop if meths.last.is_a?(Hash)
|
16
19
|
mod = options[:module] if options
|
@@ -36,6 +39,23 @@ module Sequel
|
|
36
39
|
# a single hash argument and returns the object you want #each to return.
|
37
40
|
attr_accessor :row_proc
|
38
41
|
|
42
|
+
# Load an extension into the receiver. In addition to requiring the extension file, this
|
43
|
+
# also modifies the dataset to work with the extension (usually extending it with a
|
44
|
+
# module defined in the extension file). If no related extension file exists or the
|
45
|
+
# extension does not have specific support for Database objects, an Error will be raised.
|
46
|
+
# Returns self.
|
47
|
+
def extension!(*exts)
|
48
|
+
Sequel.extension(*exts)
|
49
|
+
exts.each do |ext|
|
50
|
+
if pr = Sequel.synchronize{EXTENSIONS[ext]}
|
51
|
+
pr.call(self)
|
52
|
+
else
|
53
|
+
raise(Error, "Extension #{ext} does not have specific support handling individual datasets")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
39
59
|
# Avoid self-referential dataset by cloning.
|
40
60
|
def from_self!(*args, &block)
|
41
61
|
@opts.merge!(clone.from_self(*args, &block).opts)
|
data/lib/sequel/dataset/query.rb
CHANGED
@@ -161,23 +161,6 @@ module Sequel
|
|
161
161
|
clone.extension!(*exts)
|
162
162
|
end
|
163
163
|
|
164
|
-
# Load an extension into the receiver. In addition to requiring the extension file, this
|
165
|
-
# also modifies the dataset to work with the extension (usually extending it with a
|
166
|
-
# module defined in the extension file). If no related extension file exists or the
|
167
|
-
# extension does not have specific support for Database objects, an Error will be raised.
|
168
|
-
# Returns self.
|
169
|
-
def extension!(*exts)
|
170
|
-
Sequel.extension(*exts)
|
171
|
-
exts.each do |ext|
|
172
|
-
if pr = Sequel.synchronize{EXTENSIONS[ext]}
|
173
|
-
pr.call(self)
|
174
|
-
else
|
175
|
-
raise(Error, "Extension #{ext} does not have specific support handling individual datasets")
|
176
|
-
end
|
177
|
-
end
|
178
|
-
self
|
179
|
-
end
|
180
|
-
|
181
164
|
# Returns a copy of the dataset with the given conditions imposed upon it.
|
182
165
|
# If the query already has a HAVING clause, then the conditions are imposed in the
|
183
166
|
# HAVING clause. If not, then they are imposed in the WHERE clause.
|
data/lib/sequel/dataset/sql.rb
CHANGED
@@ -326,6 +326,13 @@ module Sequel
|
|
326
326
|
subselect_sql
|
327
327
|
table_ref
|
328
328
|
END
|
329
|
+
|
330
|
+
# For each of the methods in the given array, define a method with
|
331
|
+
# that name that returns a string with the SQL fragment that the
|
332
|
+
# related *_append method would add.
|
333
|
+
#
|
334
|
+
# Do not call this method with untrusted input, as that can result in
|
335
|
+
# arbitrary code execution.
|
329
336
|
def self.def_append_methods(meths)
|
330
337
|
meths.each do |meth|
|
331
338
|
class_eval(<<-END, __FILE__, __LINE__ + 1)
|
data/lib/sequel/exceptions.rb
CHANGED
@@ -7,8 +7,8 @@ module Sequel
|
|
7
7
|
attr_accessor :wrapped_exception
|
8
8
|
end
|
9
9
|
|
10
|
-
#
|
11
|
-
class AdapterNotFound < Error
|
10
|
+
# Error raised when the adapter requested doesn't exist or can't be loaded.
|
11
|
+
class AdapterNotFound < Error; end
|
12
12
|
|
13
13
|
# Generic error raised by the database adapters, indicating a
|
14
14
|
# problem originating from the database server. Usually raised
|
@@ -48,19 +48,23 @@ module Sequel
|
|
48
48
|
class InvalidOperation < Error; end
|
49
49
|
|
50
50
|
# Error raised when attempting an invalid type conversion.
|
51
|
-
class InvalidValue < Error
|
51
|
+
class InvalidValue < Error; end
|
52
|
+
|
53
|
+
# Error raised when the user requests a record via the first! or similar
|
54
|
+
# method, and the dataset does not yield any rows.
|
55
|
+
class NoMatchingRow < Error; end
|
52
56
|
|
53
57
|
# Error raised when the adapter adapter hasn't implemented a method such as +tables+:
|
54
58
|
class NotImplemented < Error; end
|
55
59
|
|
56
60
|
# Error raised when the connection pool cannot acquire a database connection
|
57
61
|
# before the timeout.
|
58
|
-
class PoolTimeout < Error
|
62
|
+
class PoolTimeout < Error; end
|
59
63
|
|
60
|
-
#
|
64
|
+
# Error that you should raise to signal a rollback of the current transaction.
|
61
65
|
# The transaction block will catch this exception, rollback the current transaction,
|
62
66
|
# and won't reraise it (unless a reraise is requested).
|
63
|
-
class Rollback < Error
|
67
|
+
class Rollback < Error; end
|
64
68
|
|
65
69
|
# Error raised when unbinding a dataset that has multiple different values
|
66
70
|
# for a given variable.
|
@@ -39,12 +39,12 @@ module Sequel
|
|
39
39
|
sizes = Hash.new {0}
|
40
40
|
columns.each do |c|
|
41
41
|
s = c.to_s.size
|
42
|
-
sizes[c
|
42
|
+
sizes[c] = s if s > sizes[c]
|
43
43
|
end
|
44
44
|
records.each do |r|
|
45
45
|
columns.each do |c|
|
46
46
|
s = r[c].to_s.size
|
47
|
-
sizes[c
|
47
|
+
sizes[c] = s if s > sizes[c]
|
48
48
|
end
|
49
49
|
end
|
50
50
|
sizes
|
@@ -15,6 +15,16 @@ module Sequel
|
|
15
15
|
def typecast_value_integer(value)
|
16
16
|
value.to_i
|
17
17
|
end
|
18
|
+
|
19
|
+
# Typecast the value to a BigDecimal, without checking if strings
|
20
|
+
# have a valid format.
|
21
|
+
def typecast_value_decimal(value)
|
22
|
+
if value.is_a?(String)
|
23
|
+
BigDecimal.new(value)
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
18
28
|
end
|
19
29
|
|
20
30
|
Database.register_extension(:looser_typecasting, LooserTypecasting)
|
@@ -241,11 +241,14 @@ module Sequel
|
|
241
241
|
@actions << [:drop_constraint, args.first]
|
242
242
|
end
|
243
243
|
|
244
|
-
def add_foreign_key(*args)
|
244
|
+
def add_foreign_key(key, table, *args)
|
245
|
+
@actions << [:drop_foreign_key, key, *args]
|
246
|
+
end
|
247
|
+
|
248
|
+
def add_primary_key(*args)
|
245
249
|
raise if args.first.is_a?(Array)
|
246
250
|
@actions << [:drop_column, args.first]
|
247
251
|
end
|
248
|
-
alias add_primary_key add_foreign_key
|
249
252
|
|
250
253
|
def add_index(*args)
|
251
254
|
@actions << [:drop_index, *args]
|
data/lib/sequel/model.rb
CHANGED
@@ -72,7 +72,7 @@ module Sequel
|
|
72
72
|
|
73
73
|
# Class methods added to model that call the method of the same name on the dataset
|
74
74
|
DATASET_METHODS = (Dataset::ACTION_METHODS + Dataset::QUERY_METHODS +
|
75
|
-
[:
|
75
|
+
[:each_page, :each_server, :print]) - [:and, :or, :[], :[]=, :columns, :columns!]
|
76
76
|
|
77
77
|
# Class instance variables to set to nil when a subclass is created, for -w compliance
|
78
78
|
EMPTY_INSTANCE_VARIABLES = [:@overridable_methods_module, :@db]
|
@@ -1438,6 +1438,12 @@ module Sequel
|
|
1438
1438
|
super
|
1439
1439
|
end
|
1440
1440
|
|
1441
|
+
# Clear the associations cache when refreshing
|
1442
|
+
def set_values(hash)
|
1443
|
+
@associations.clear if @associations
|
1444
|
+
super
|
1445
|
+
end
|
1446
|
+
|
1441
1447
|
# Formally used internally by the associations code, like pk but doesn't raise
|
1442
1448
|
# an Error if the model has no primary key. Not used any longer, deprecated.
|
1443
1449
|
def pk_or_nil
|
@@ -1510,12 +1516,6 @@ module Sequel
|
|
1510
1516
|
end
|
1511
1517
|
end
|
1512
1518
|
|
1513
|
-
# Clear the associations cache when refreshing
|
1514
|
-
def _refresh(dataset)
|
1515
|
-
associations.clear
|
1516
|
-
super
|
1517
|
-
end
|
1518
|
-
|
1519
1519
|
# Add the given associated object to the given association
|
1520
1520
|
def add_associated_object(opts, o, *args)
|
1521
1521
|
klass = opts.associated_class
|
@@ -1833,13 +1833,14 @@ module Sequel
|
|
1833
1833
|
opt = opt ? opt.dup : {}
|
1834
1834
|
associations.flatten.each do |association|
|
1835
1835
|
case association
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
|
1836
|
+
when Symbol
|
1837
|
+
check_association(model, association)
|
1838
|
+
opt[association] = nil
|
1839
|
+
when Hash
|
1840
|
+
association.keys.each{|assoc| check_association(model, assoc)}
|
1841
|
+
opt.merge!(association)
|
1842
|
+
else
|
1843
|
+
raise(Sequel::Error, 'Associations must be in the form of a symbol or hash')
|
1843
1844
|
end
|
1844
1845
|
end
|
1845
1846
|
clone(:eager=>opt)
|
@@ -1956,7 +1957,8 @@ module Sequel
|
|
1956
1957
|
ds = ds.eager_graph_association(ds, model, ta, requirements, eager_graph_check_association(model, assoc), assoc_assocs)
|
1957
1958
|
end
|
1958
1959
|
ds
|
1959
|
-
else
|
1960
|
+
else
|
1961
|
+
raise(Sequel::Error, 'Associations must be in the form of a symbol or hash')
|
1960
1962
|
end
|
1961
1963
|
end
|
1962
1964
|
ds
|
data/lib/sequel/model/base.rb
CHANGED
@@ -869,6 +869,9 @@ module Sequel
|
|
869
869
|
# Define instance method(s) that calls class method(s) of the
|
870
870
|
# same name, caching the result in an instance variable. Define
|
871
871
|
# standard attr_writer method for modifying that instance variable.
|
872
|
+
#
|
873
|
+
# Do not call this method with untrusted input, as that can result in
|
874
|
+
# arbitrary code execution.
|
872
875
|
def self.class_attr_overridable(*meths) # :nodoc:
|
873
876
|
meths.each{|meth| class_eval("def #{meth}; !defined?(@#{meth}) ? (frozen? ? self.class.#{meth} : (@#{meth} = self.class.#{meth})) : @#{meth} end", __FILE__, __LINE__)}
|
874
877
|
attr_writer(*meths)
|
@@ -878,6 +881,9 @@ module Sequel
|
|
878
881
|
# same name. Replaces the construct:
|
879
882
|
#
|
880
883
|
# define_method(meth){self.class.send(meth)}
|
884
|
+
#
|
885
|
+
# Do not call this method with untrusted input, as that can result in
|
886
|
+
# arbitrary code execution.
|
881
887
|
def self.class_attr_reader(*meths) # :nodoc:
|
882
888
|
meths.each{|meth| class_eval("def #{meth}; self.class.#{meth} end", __FILE__, __LINE__)}
|
883
889
|
end
|
@@ -1187,7 +1193,7 @@ module Sequel
|
|
1187
1193
|
end
|
1188
1194
|
end
|
1189
1195
|
|
1190
|
-
# Returns a hash
|
1196
|
+
# Returns a hash mapping the receivers primary key column(s) to their values.
|
1191
1197
|
#
|
1192
1198
|
# Artist[1].pk_hash # => {:id=>1}
|
1193
1199
|
# Artist[[1, 2]].pk_hash # => {:id1=>1, :id2=>2}
|
@@ -1983,7 +1989,7 @@ module Sequel
|
|
1983
1989
|
end
|
1984
1990
|
|
1985
1991
|
# Given a primary key value, return the first record in the dataset with that primary key
|
1986
|
-
# value.
|
1992
|
+
# value. If no records matches, returns nil.
|
1987
1993
|
#
|
1988
1994
|
# # Single primary key
|
1989
1995
|
# Artist.dataset.with_pk(1) # SELECT * FROM artists WHERE (id = 1) LIMIT 1
|
@@ -1994,6 +2000,12 @@ module Sequel
|
|
1994
2000
|
def with_pk(pk)
|
1995
2001
|
first(model.qualified_primary_key_hash(pk))
|
1996
2002
|
end
|
2003
|
+
|
2004
|
+
# Same as with_pk, but raises NoMatchingRow instead of returning nil if no
|
2005
|
+
# row matches.
|
2006
|
+
def with_pk!(pk)
|
2007
|
+
with_pk(pk) || raise(NoMatchingRow)
|
2008
|
+
end
|
1997
2009
|
end
|
1998
2010
|
|
1999
2011
|
extend ClassMethods
|
@@ -148,10 +148,10 @@ module Sequel
|
|
148
148
|
end
|
149
149
|
|
150
150
|
module InstanceMethods
|
151
|
-
# Clear the cached compositions when
|
152
|
-
def
|
151
|
+
# Clear the cached compositions when setting values.
|
152
|
+
def set_values(hash)
|
153
|
+
@compositions.clear if @compositions
|
153
154
|
super
|
154
|
-
compositions.clear
|
155
155
|
end
|
156
156
|
|
157
157
|
# For each composition, set the columns in the model class based
|
data/lib/sequel/plugins/dirty.rb
CHANGED
@@ -115,6 +115,12 @@ module Sequel
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
+
# Reset the initial values when setting values.
|
119
|
+
def set_values(hash)
|
120
|
+
reset_initial_values
|
121
|
+
super
|
122
|
+
end
|
123
|
+
|
118
124
|
# Manually specify that a column will change. This should only be used
|
119
125
|
# if you plan to modify a column value in place, which is not recommended.
|
120
126
|
#
|
@@ -157,12 +163,6 @@ module Sequel
|
|
157
163
|
@previous_changes = column_changes
|
158
164
|
end
|
159
165
|
|
160
|
-
# Reset the initial values when refreshing.
|
161
|
-
def _refresh(dataset)
|
162
|
-
super
|
163
|
-
reset_initial_values
|
164
|
-
end
|
165
|
-
|
166
166
|
# When changing the column value, save the initial column value. If the column
|
167
167
|
# value is changed back to the initial value, update changed columns to remove
|
168
168
|
# the column.
|
@@ -69,6 +69,9 @@ module Sequel
|
|
69
69
|
# # move MyModel object to there
|
70
70
|
# end
|
71
71
|
# end
|
72
|
+
#
|
73
|
+
# Do not call this method with untrusted input, as that can result in
|
74
|
+
# arbitrary code execution.
|
72
75
|
def add_hook_type(*hooks)
|
73
76
|
Model::HOOKS.concat(hooks)
|
74
77
|
hooks.each do |hook|
|
@@ -168,35 +168,25 @@ module Sequel
|
|
168
168
|
end
|
169
169
|
|
170
170
|
module InstanceMethods
|
171
|
-
# Hash of deserialized values, used as a cache.
|
172
|
-
attr_reader :deserialized_values
|
173
|
-
|
174
|
-
# Set @deserialized_values to the empty hash
|
175
|
-
def initialize_set(values)
|
176
|
-
@deserialized_values = {}
|
177
|
-
super
|
178
|
-
end
|
179
|
-
|
180
171
|
# Serialize deserialized values before saving
|
181
172
|
def before_save
|
182
173
|
serialize_deserialized_values
|
183
174
|
super
|
184
175
|
end
|
185
176
|
|
186
|
-
#
|
187
|
-
def
|
177
|
+
# Hash of deserialized values, used as a cache.
|
178
|
+
def deserialized_values
|
188
179
|
@deserialized_values ||= {}
|
189
|
-
super
|
190
180
|
end
|
191
181
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
def _refresh(*)
|
196
|
-
@deserialized_values = {}
|
182
|
+
# Initialization the deserialized values for objects retrieved from the database.
|
183
|
+
def set_values(hash)
|
184
|
+
@deserialized_values.clear if @deserialized_values
|
197
185
|
super
|
198
186
|
end
|
199
187
|
|
188
|
+
private
|
189
|
+
|
200
190
|
# Deserialize the column value. Called when the model column accessor is called to
|
201
191
|
# return a deserialized value.
|
202
192
|
def deserialize_value(column, v)
|