sequel 3.44.0 → 3.45.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +44 -0
- data/Rakefile +12 -4
- data/doc/reflection.rdoc +3 -3
- data/doc/release_notes/3.45.0.txt +179 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/transactions.rdoc +23 -0
- data/lib/sequel/adapters/db2.rb +1 -0
- data/lib/sequel/adapters/ibmdb.rb +19 -3
- data/lib/sequel/adapters/jdbc.rb +15 -0
- data/lib/sequel/adapters/jdbc/derby.rb +1 -5
- data/lib/sequel/adapters/jdbc/h2.rb +1 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -1
- data/lib/sequel/adapters/jdbc/jtds.rb +5 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +5 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +7 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
- data/lib/sequel/adapters/jdbc/transactions.rb +28 -1
- data/lib/sequel/adapters/mysql.rb +4 -0
- data/lib/sequel/adapters/mysql2.rb +5 -1
- data/lib/sequel/adapters/oracle.rb +18 -0
- data/lib/sequel/adapters/postgres.rb +11 -1
- data/lib/sequel/adapters/shared/access.rb +14 -2
- data/lib/sequel/adapters/shared/cubrid.rb +1 -11
- data/lib/sequel/adapters/shared/db2.rb +11 -6
- data/lib/sequel/adapters/shared/mssql.rb +10 -10
- data/lib/sequel/adapters/shared/mysql.rb +11 -1
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +17 -1
- data/lib/sequel/adapters/shared/oracle.rb +16 -15
- data/lib/sequel/adapters/shared/postgres.rb +91 -59
- data/lib/sequel/adapters/shared/sqlite.rb +1 -4
- data/lib/sequel/adapters/tinytds.rb +15 -0
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/core.rb +10 -0
- data/lib/sequel/database/connecting.rb +2 -0
- data/lib/sequel/database/misc.rb +46 -4
- data/lib/sequel/database/query.rb +33 -14
- data/lib/sequel/database/schema_methods.rb +0 -5
- data/lib/sequel/dataset/misc.rb +9 -0
- data/lib/sequel/dataset/mutation.rb +9 -7
- data/lib/sequel/dataset/sql.rb +13 -0
- data/lib/sequel/exceptions.rb +3 -0
- data/lib/sequel/extensions/connection_validator.rb +1 -1
- data/lib/sequel/extensions/date_arithmetic.rb +0 -8
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/named_timezones.rb +18 -2
- data/lib/sequel/extensions/pg_array.rb +5 -1
- data/lib/sequel/extensions/pg_array_ops.rb +2 -0
- data/lib/sequel/extensions/pg_hstore.rb +2 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -0
- data/lib/sequel/extensions/pg_json.rb +3 -1
- data/lib/sequel/extensions/pg_range.rb +2 -0
- data/lib/sequel/extensions/pg_range_ops.rb +2 -0
- data/lib/sequel/extensions/pg_row.rb +2 -0
- data/lib/sequel/extensions/pg_row_ops.rb +2 -0
- data/lib/sequel/extensions/query.rb +18 -22
- data/lib/sequel/model/associations.rb +3 -4
- data/lib/sequel/model/base.rb +2 -0
- data/lib/sequel/plugins/force_encoding.rb +2 -0
- data/lib/sequel/plugins/json_serializer.rb +155 -39
- data/lib/sequel/plugins/serialization.rb +14 -2
- data/lib/sequel/plugins/unlimited_update.rb +31 -0
- data/lib/sequel/plugins/validation_class_methods.rb +6 -4
- data/lib/sequel/plugins/xml_serializer.rb +133 -30
- data/lib/sequel/sql.rb +2 -0
- data/lib/sequel/timezones.rb +4 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +0 -11
- data/spec/adapters/postgres_spec.rb +86 -54
- data/spec/adapters/spec_helper.rb +6 -0
- data/spec/core/connection_pool_spec.rb +16 -0
- data/spec/core/database_spec.rb +77 -1
- data/spec/core/dataset_spec.rb +30 -15
- data/spec/core/expression_filters_spec.rb +55 -13
- data/spec/core/mock_adapter_spec.rb +4 -0
- data/spec/core/schema_spec.rb +0 -2
- data/spec/core/spec_helper.rb +5 -0
- data/spec/core_extensions_spec.rb +33 -28
- data/spec/extensions/constraint_validations_spec.rb +2 -2
- data/spec/extensions/core_refinements_spec.rb +12 -12
- data/spec/extensions/json_serializer_spec.rb +137 -31
- data/spec/extensions/named_timezones_spec.rb +10 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +5 -0
- data/spec/extensions/pg_json_spec.rb +14 -0
- data/spec/extensions/pg_row_spec.rb +11 -0
- data/spec/extensions/pretty_table_spec.rb +2 -2
- data/spec/extensions/query_spec.rb +11 -8
- data/spec/extensions/serialization_spec.rb +20 -0
- data/spec/extensions/spec_helper.rb +8 -2
- data/spec/extensions/sql_expr_spec.rb +1 -1
- data/spec/extensions/unlimited_update_spec.rb +20 -0
- data/spec/extensions/xml_serializer_spec.rb +68 -16
- data/spec/integration/dataset_test.rb +28 -0
- data/spec/integration/spec_helper.rb +6 -0
- data/spec/integration/transaction_test.rb +39 -0
- data/spec/model/model_spec.rb +1 -1
- data/spec/sequel_coverage.rb +15 -0
- metadata +8 -3
@@ -98,7 +98,7 @@ module Sequel
|
|
98
98
|
# parsing does not yield an array or hash.
|
99
99
|
def self.parse_json(s)
|
100
100
|
begin
|
101
|
-
value =
|
101
|
+
value = Sequel.parse_json(s)
|
102
102
|
rescue JSON::ParserError=>e
|
103
103
|
raise Sequel.convert_exception_class(e, Sequel::InvalidValue)
|
104
104
|
end
|
@@ -192,6 +192,7 @@ module Sequel
|
|
192
192
|
Database.register_extension(:pg_json, Postgres::JSONDatabaseMethods)
|
193
193
|
end
|
194
194
|
|
195
|
+
# :nocov:
|
195
196
|
if Sequel.core_extensions?
|
196
197
|
class Array
|
197
198
|
# Return a Sequel::Postgres::JSONArray proxy to the receiver.
|
@@ -227,3 +228,4 @@ if defined?(Sequel::CoreRefinements)
|
|
227
228
|
end
|
228
229
|
end
|
229
230
|
end
|
231
|
+
# :nocov:
|
@@ -503,6 +503,7 @@ module Sequel
|
|
503
503
|
Database.register_extension(:pg_range, Postgres::PGRange::DatabaseMethods)
|
504
504
|
end
|
505
505
|
|
506
|
+
# :nocov:
|
506
507
|
if Sequel.core_extensions?
|
507
508
|
class Range
|
508
509
|
# Create a new PGRange using the receiver as the input range,
|
@@ -522,3 +523,4 @@ if defined?(Sequel::CoreRefinements)
|
|
522
523
|
end
|
523
524
|
end
|
524
525
|
end
|
526
|
+
# :nocov:
|
@@ -572,6 +572,7 @@ module Sequel
|
|
572
572
|
Database.register_extension(:pg_row, Postgres::PGRow::DatabaseMethods)
|
573
573
|
end
|
574
574
|
|
575
|
+
# :nocov:
|
575
576
|
if Sequel.core_extensions?
|
576
577
|
class Array
|
577
578
|
# Wraps the receiver in an anonymous Sequel::Postgres::PGRow::ArrayRow instance.
|
@@ -590,3 +591,4 @@ if defined?(Sequel::CoreRefinements)
|
|
590
591
|
end
|
591
592
|
end
|
592
593
|
end
|
594
|
+
# :nocov:
|
@@ -176,6 +176,7 @@ module Sequel
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
+
# :nocov:
|
179
180
|
if Sequel.core_extensions?
|
180
181
|
class Symbol
|
181
182
|
include Sequel::Postgres::PGRowOp::ExpressionMethods
|
@@ -189,3 +190,4 @@ if defined?(Sequel::CoreRefinements)
|
|
189
190
|
end
|
190
191
|
end
|
191
192
|
end
|
193
|
+
# :nocov:
|
@@ -1,12 +1,10 @@
|
|
1
1
|
# The query extension adds Sequel::Dataset#query which allows
|
2
2
|
# a different way to construct queries instead of the usual
|
3
|
-
# method chaining.
|
3
|
+
# method chaining. See Sequel::Dataset#query for details.
|
4
4
|
#
|
5
5
|
# To load the extension, do:
|
6
6
|
#
|
7
7
|
# Sequel.extension :query
|
8
|
-
#
|
9
|
-
# This extension uses Object#extend at runtime, which can hurt performance.
|
10
8
|
|
11
9
|
module Sequel
|
12
10
|
class Database
|
@@ -17,8 +15,9 @@ module Sequel
|
|
17
15
|
end
|
18
16
|
|
19
17
|
class Dataset
|
20
|
-
# Translates a query block into a dataset. Query blocks
|
21
|
-
#
|
18
|
+
# Translates a query block into a dataset. Query blocks are an
|
19
|
+
# alternative to Sequel's usual method chaining, by using
|
20
|
+
# instance_eval with a proxy object:
|
22
21
|
#
|
23
22
|
# dataset = DB[:items].query do
|
24
23
|
# select :x, :y, :z
|
@@ -29,28 +28,25 @@ module Sequel
|
|
29
28
|
# Which is the same as:
|
30
29
|
#
|
31
30
|
# dataset = DB[:items].select(:x, :y, :z).filter{(x > 1) & (y > 2)}.reverse(:z)
|
32
|
-
#
|
33
|
-
# Note that inside a call to query, you cannot call each, insert, update,
|
34
|
-
# or delete (or any method that calls those), or Sequel will raise an
|
35
|
-
# error.
|
36
31
|
def query(&block)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
clone(copy.opts)
|
32
|
+
query = Query.new(self)
|
33
|
+
query.instance_eval(&block)
|
34
|
+
query.dataset
|
41
35
|
end
|
42
36
|
|
43
|
-
#
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
37
|
+
# Proxy object used by Dataset#query.
|
38
|
+
class Query < Sequel::BasicObject
|
39
|
+
# The current dataset in the query. This changes on each method call.
|
40
|
+
attr_reader :dataset
|
41
|
+
|
42
|
+
def initialize(dataset)
|
43
|
+
@dataset = dataset
|
48
44
|
end
|
49
45
|
|
50
|
-
#
|
51
|
-
|
52
|
-
|
53
|
-
@
|
46
|
+
# Replace the query's dataset with dataset returned by the method call.
|
47
|
+
def method_missing(method, *args, &block)
|
48
|
+
@dataset = @dataset.send(method, *args, &block)
|
49
|
+
raise(Sequel::Error, "method #{method.inspect} did not return a dataset") unless @dataset.is_a?(Dataset)
|
54
50
|
self
|
55
51
|
end
|
56
52
|
end
|
@@ -254,6 +254,7 @@ module Sequel
|
|
254
254
|
private
|
255
255
|
|
256
256
|
if defined?(RUBY_ENGINE) && RUBY_ENGINE != 'ruby'
|
257
|
+
# :nocov:
|
257
258
|
# On non-GVL rubies, assume the need to synchronize access. Store the key
|
258
259
|
# in a special sub-hash that always uses this method to synchronize access.
|
259
260
|
def cached_fetch(key)
|
@@ -270,6 +271,7 @@ module Sequel
|
|
270
271
|
h = self[:cache]
|
271
272
|
Sequel.synchronize{h[key] = value}
|
272
273
|
end
|
274
|
+
# :nocov:
|
273
275
|
else
|
274
276
|
# On MRI, use a plain fetch, since the GVL will synchronize access.
|
275
277
|
def cached_fetch(key)
|
@@ -1749,10 +1751,7 @@ module Sequel
|
|
1749
1751
|
#
|
1750
1752
|
# Artist.eager(:albums => {proc{|ds| ds.where{year > 1990}}=>{:tracks => :genre}})
|
1751
1753
|
module DatasetMethods
|
1752
|
-
|
1753
|
-
def self.extended(obj)
|
1754
|
-
obj.def_mutation_method(:eager, :eager_graph)
|
1755
|
-
end
|
1754
|
+
Sequel::Dataset.def_mutation_method(:eager, :eager_graph, :module=>self)
|
1756
1755
|
|
1757
1756
|
# If the expression is in the form <tt>x = y</tt> where +y+ is a <tt>Sequel::Model</tt>
|
1758
1757
|
# instance, array of <tt>Sequel::Model</tt> instances, or a <tt>Sequel::Model</tt> dataset,
|
data/lib/sequel/model/base.rb
CHANGED
@@ -36,30 +36,54 @@ module Sequel
|
|
36
36
|
# album.to_json(:root => true)
|
37
37
|
# # => '{"album":{"id":1,"name":"RF","artist_id":2}}'
|
38
38
|
#
|
39
|
+
# Additionally, +to_json+ also exists as a class and dataset method, both
|
40
|
+
# of which return all objects in the dataset:
|
41
|
+
#
|
42
|
+
# Album.to_json
|
43
|
+
# Album.filter(:artist_id=>1).to_json(:include=>:tags)
|
44
|
+
#
|
45
|
+
# If you have an existing array of model instances you want to convert to
|
46
|
+
# JSON, you can call the class to_json method with the :array option:
|
47
|
+
#
|
48
|
+
# Album.to_json(:array=>[Album[1], Album[2]])
|
49
|
+
#
|
39
50
|
# In addition to creating JSON, this plugin also enables Sequel::Model
|
40
|
-
#
|
51
|
+
# classes to create instances directly from JSON using the from_json class
|
52
|
+
# method:
|
41
53
|
#
|
42
54
|
# json = album.to_json
|
43
|
-
# album =
|
55
|
+
# album = Album.from_json(json)
|
56
|
+
#
|
57
|
+
# The array_from_json class method exists to parse arrays of model instances
|
58
|
+
# from json:
|
59
|
+
#
|
60
|
+
# json = Album.filter(:artist_id=>1).to_json
|
61
|
+
# albums = Album.array_from_json(json)
|
62
|
+
#
|
63
|
+
# These does not necessarily round trip, since doing so would let users
|
64
|
+
# create model objects with arbitrary values. By default, from_json will
|
65
|
+
# call set with the values in the hash. If you want to specify the allowed
|
66
|
+
# fields, you can use the :fields option, which will call set_fields with
|
67
|
+
# the given fields:
|
68
|
+
#
|
69
|
+
# Album.from_json(album.to_json, :fields=>%w'id name')
|
44
70
|
#
|
45
|
-
#
|
46
|
-
#
|
71
|
+
# If you want to update an existing instance, you can use the from_json
|
72
|
+
# instance method:
|
47
73
|
#
|
48
74
|
# album.from_json(json)
|
49
75
|
#
|
50
|
-
#
|
51
|
-
#
|
76
|
+
# Both of these allow creation of cached associated objects, if you provide
|
77
|
+
# the :associations option:
|
52
78
|
#
|
53
|
-
#
|
54
|
-
# of which return all objects in the dataset:
|
79
|
+
# album.from_json(json, :associations=>:artist)
|
55
80
|
#
|
56
|
-
#
|
57
|
-
# Album.filter(:artist_id=>1).to_json(:include=>:tags)
|
81
|
+
# You can even provide options when setting up the associated objects:
|
58
82
|
#
|
59
|
-
#
|
60
|
-
# JSON, you can call the class to_json method with the :array option:
|
83
|
+
# album.from_json(json, :associations=>{:artist=>{:fields=>%w'id name', :associations=>:tags}})
|
61
84
|
#
|
62
|
-
#
|
85
|
+
# If the json is trusted and should be allowed to set all column and association
|
86
|
+
# values, you can use the :all_columns and :all_associations options.
|
63
87
|
#
|
64
88
|
# Note that active_support/json makes incompatible changes to the to_json API,
|
65
89
|
# and breaks some aspects of the json_serializer plugin. You can undo the damage
|
@@ -116,29 +140,39 @@ module Sequel
|
|
116
140
|
# The default opts to use when serializing model objects to JSON.
|
117
141
|
attr_reader :json_serializer_opts
|
118
142
|
|
119
|
-
#
|
120
|
-
#
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
143
|
+
# Attempt to parse a single instance from the given JSON string,
|
144
|
+
# with options passed to InstanceMethods#from_json_node.
|
145
|
+
def from_json(json, opts={})
|
146
|
+
v = Sequel.parse_json(json)
|
147
|
+
case v
|
148
|
+
when self
|
149
|
+
v
|
150
|
+
when Hash
|
151
|
+
new.from_json_node(v, opts)
|
152
|
+
else
|
153
|
+
raise Error, "parsed json doesn't return a hash or instance of #{self}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Attempt to parse an array of instances from the given JSON string,
|
158
|
+
# with options passed to InstanceMethods#from_json_node.
|
159
|
+
def array_from_json(json, opts={})
|
160
|
+
v = Sequel.parse_json(json)
|
161
|
+
if v.is_a?(Array)
|
162
|
+
raise(Error, 'parsed json returned an array containing non-hashes') unless v.all?{|ve| ve.is_a?(Hash) || ve.is_a?(self)}
|
163
|
+
v.map{|ve| ve.is_a?(self) ? ve : new.from_json_node(ve, opts)}
|
164
|
+
else
|
165
|
+
raise(Error, 'parsed json did not return an array')
|
140
166
|
end
|
141
|
-
|
167
|
+
end
|
168
|
+
|
169
|
+
# Exists for compatibility with old json library which allows creation
|
170
|
+
# of arbitrary ruby objects by JSON.parse. Creates a new instance
|
171
|
+
# and populates it using InstanceMethods#from_json_node with the
|
172
|
+
# :all_columns and :all_associations options. Not recommended for usage
|
173
|
+
# in new code, consider calling the from_json method directly with the JSON string.
|
174
|
+
def json_create(hash, opts={})
|
175
|
+
new.from_json_node(hash, {:all_columns=>true, :all_associations=>true}.merge(opts))
|
142
176
|
end
|
143
177
|
|
144
178
|
# Call the dataset +to_json+ method.
|
@@ -157,14 +191,96 @@ module Sequel
|
|
157
191
|
|
158
192
|
module InstanceMethods
|
159
193
|
# Parse the provided JSON, which should return a hash,
|
160
|
-
# and
|
194
|
+
# and process the hash with from_json_node.
|
161
195
|
def from_json(json, opts={})
|
162
|
-
|
196
|
+
from_json_node(Sequel.parse_json(json), opts)
|
197
|
+
end
|
198
|
+
|
199
|
+
# Using the provided hash, update the instance with data contained in the hash. By default, just
|
200
|
+
# calls set with the hash values.
|
201
|
+
#
|
202
|
+
# Options:
|
203
|
+
# :all_associations :: Indicates that all associations supported by the model should be tried.
|
204
|
+
# This option also cascades to associations if used. It is better to use the
|
205
|
+
# :associations option instead of this option. This option only exists for
|
206
|
+
# backwards compatibility.
|
207
|
+
# :all_columns :: Overrides the setting logic allowing all setter methods be used,
|
208
|
+
# even if access to the setter method is restricted.
|
209
|
+
# This option cascades to associations if used, and can be reset in those associations
|
210
|
+
# using the :all_columns=>false or :fields options. This option is considered a
|
211
|
+
# security risk, and only exists for backwards compatibility. It is better to use
|
212
|
+
# the :fields option appropriately instead of this option, or no option at all.
|
213
|
+
# :associations :: Indicates that the associations cache should be updated by creating
|
214
|
+
# a new associated object using data from the hash. Should be a Symbol
|
215
|
+
# for a single association, an array of symbols for multiple associations,
|
216
|
+
# or a hash with symbol keys and dependent association option hash values.
|
217
|
+
# :fields :: Changes the behavior to call set_fields using the provided fields, instead of calling set.
|
218
|
+
def from_json_node(hash, opts={})
|
219
|
+
unless hash.is_a?(Hash)
|
220
|
+
raise Error, "parsed json doesn't return a hash"
|
221
|
+
end
|
222
|
+
hash.delete(JSON.create_id)
|
223
|
+
|
224
|
+
unless assocs = opts[:associations]
|
225
|
+
if opts[:all_associations]
|
226
|
+
assocs = {}
|
227
|
+
model.associations.each{|v| assocs[v] = {:all_associations=>true}}
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
if assocs
|
232
|
+
assocs = case assocs
|
233
|
+
when Symbol
|
234
|
+
{assocs=>{}}
|
235
|
+
when Array
|
236
|
+
assocs_tmp = {}
|
237
|
+
assocs.each{|v| assocs_tmp[v] = {}}
|
238
|
+
assocs_tmp
|
239
|
+
when Hash
|
240
|
+
assocs
|
241
|
+
else
|
242
|
+
raise Error, ":associations should be Symbol, Array, or Hash if present"
|
243
|
+
end
|
244
|
+
|
245
|
+
if opts[:all_columns]
|
246
|
+
assocs.each_value do |assoc_opts|
|
247
|
+
assoc_opts[:all_columns] = true unless assoc_opts.has_key?(:fields) || assoc_opts.has_key?(:all_columns)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
assocs.each do |assoc, assoc_opts|
|
252
|
+
if assoc_values = hash.delete(assoc.to_s)
|
253
|
+
unless r = model.association_reflection(assoc)
|
254
|
+
raise Error, "Association #{assoc} is not defined for #{model}"
|
255
|
+
end
|
256
|
+
|
257
|
+
associations[assoc] = if r.returns_array?
|
258
|
+
raise Error, "Attempt to populate array association with a non-array" unless assoc_values.is_a?(Array)
|
259
|
+
assoc_values.map{|v| v.is_a?(r.associated_class) ? v : r.associated_class.new.from_json_node(v, assoc_opts)}
|
260
|
+
else
|
261
|
+
raise Error, "Attempt to populate non-array association with an array" if assoc_values.is_a?(Array)
|
262
|
+
assoc_values.is_a?(r.associated_class) ? assoc_values : r.associated_class.new.from_json_node(assoc_values, assoc_opts)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
163
268
|
if fields = opts[:fields]
|
164
|
-
set_fields(
|
269
|
+
set_fields(hash, fields, opts)
|
270
|
+
elsif opts[:all_columns]
|
271
|
+
meths = methods.collect{|x| x.to_s}.grep(Model::SETTER_METHOD_REGEXP) - Model::RESTRICTED_SETTER_METHODS
|
272
|
+
hash.each do |k, v|
|
273
|
+
if meths.include?(setter_meth = "#{k}=")
|
274
|
+
send(setter_meth, v)
|
275
|
+
else
|
276
|
+
raise Error, "Entry in JSON does not have a matching setter method: #{k}"
|
277
|
+
end
|
278
|
+
end
|
165
279
|
else
|
166
|
-
set(
|
280
|
+
set(hash)
|
167
281
|
end
|
282
|
+
|
283
|
+
self
|
168
284
|
end
|
169
285
|
|
170
286
|
# Return a string in JSON format. Accepts the following
|
@@ -82,9 +82,21 @@ module Sequel
|
|
82
82
|
def self.register_format(format, serializer, deserializer)
|
83
83
|
REGISTERED_FORMATS[format] = [serializer, deserializer]
|
84
84
|
end
|
85
|
-
register_format(:marshal, lambda{|v| [Marshal.dump(v)].pack('m')},
|
85
|
+
register_format(:marshal, lambda{|v| [Marshal.dump(v)].pack('m')},
|
86
|
+
lambda do |v|
|
87
|
+
begin
|
88
|
+
Marshal.load(v.unpack('m')[0])
|
89
|
+
rescue => e
|
90
|
+
begin
|
91
|
+
# Backwards compatibility for unpacked marshal output.
|
92
|
+
Marshal.load(v)
|
93
|
+
rescue
|
94
|
+
raise e
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end)
|
86
98
|
register_format(:yaml, lambda{|v| v.to_yaml}, lambda{|v| YAML.load(v)})
|
87
|
-
register_format(:json, lambda{|v| v.to_json}, lambda{|v|
|
99
|
+
register_format(:json, lambda{|v| v.to_json}, lambda{|v| Sequel.parse_json(v)})
|
88
100
|
|
89
101
|
module ClassMethods
|
90
102
|
# A hash with column name symbols and callable values, with the value
|