sequel 4.47.0 → 4.48.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 +4 -4
- data/CHANGELOG +134 -0
- data/Rakefile +1 -1
- data/doc/release_notes/4.48.0.txt +293 -0
- data/lib/sequel/adapters/ado/access.rb +2 -1
- data/lib/sequel/adapters/do/postgres.rb +5 -2
- data/lib/sequel/adapters/ibmdb.rb +24 -7
- data/lib/sequel/adapters/jdbc.rb +36 -22
- data/lib/sequel/adapters/jdbc/db2.rb +12 -3
- data/lib/sequel/adapters/jdbc/derby.rb +4 -5
- data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +43 -18
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
- data/lib/sequel/adapters/jdbc/sqlserver.rb +11 -4
- data/lib/sequel/adapters/mock.rb +24 -19
- data/lib/sequel/adapters/mysql.rb +17 -16
- data/lib/sequel/adapters/mysql2.rb +4 -5
- data/lib/sequel/adapters/oracle.rb +5 -9
- data/lib/sequel/adapters/postgres.rb +89 -102
- data/lib/sequel/adapters/shared/db2.rb +22 -6
- data/lib/sequel/adapters/shared/mssql.rb +5 -4
- data/lib/sequel/adapters/shared/mysql.rb +75 -24
- data/lib/sequel/adapters/shared/postgres.rb +196 -94
- data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
- data/lib/sequel/adapters/shared/sqlite.rb +72 -82
- data/lib/sequel/adapters/sqlanywhere.rb +4 -1
- data/lib/sequel/adapters/sqlite.rb +5 -3
- data/lib/sequel/adapters/swift/postgres.rb +5 -2
- data/lib/sequel/adapters/tinytds.rb +0 -5
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
- data/lib/sequel/adapters/utils/pg_types.rb +2 -76
- data/lib/sequel/core.rb +2 -2
- data/lib/sequel/database/connecting.rb +5 -5
- data/lib/sequel/database/dataset.rb +6 -3
- data/lib/sequel/database/misc.rb +1 -1
- data/lib/sequel/database/query.rb +3 -0
- data/lib/sequel/database/schema_methods.rb +1 -1
- data/lib/sequel/dataset/actions.rb +18 -10
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +1 -0
- data/lib/sequel/dataset/prepared_statements.rb +3 -3
- data/lib/sequel/dataset/query.rb +19 -8
- data/lib/sequel/extensions/core_extensions.rb +4 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
- data/lib/sequel/extensions/filter_having.rb +2 -0
- data/lib/sequel/extensions/freeze_datasets.rb +2 -0
- data/lib/sequel/extensions/from_block.rb +1 -1
- data/lib/sequel/extensions/graph_each.rb +2 -2
- data/lib/sequel/extensions/hash_aliases.rb +2 -0
- data/lib/sequel/extensions/identifier_mangling.rb +0 -7
- data/lib/sequel/extensions/meta_def.rb +2 -0
- data/lib/sequel/extensions/migration.rb +6 -6
- data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +207 -130
- data/lib/sequel/extensions/pg_hstore.rb +38 -20
- data/lib/sequel/extensions/pg_inet.rb +18 -6
- data/lib/sequel/extensions/pg_interval.rb +19 -12
- data/lib/sequel/extensions/pg_json.rb +25 -14
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/extensions/pg_range.rb +133 -100
- data/lib/sequel/extensions/pg_range_ops.rb +4 -3
- data/lib/sequel/extensions/pg_row.rb +68 -39
- data/lib/sequel/extensions/pg_row_ops.rb +11 -5
- data/lib/sequel/extensions/query_literals.rb +2 -0
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
- data/lib/sequel/extensions/s.rb +1 -1
- data/lib/sequel/extensions/schema_dumper.rb +24 -24
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
- data/lib/sequel/extensions/set_overrides.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +0 -1
- data/lib/sequel/extensions/symbol_aref.rb +0 -4
- data/lib/sequel/model.rb +25 -57
- data/lib/sequel/model/associations.rb +14 -5
- data/lib/sequel/model/base.rb +96 -32
- data/lib/sequel/plugins/association_pks.rb +73 -46
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/auto_validations.rb +6 -2
- data/lib/sequel/plugins/boolean_readers.rb +1 -1
- data/lib/sequel/plugins/caching.rb +19 -13
- data/lib/sequel/plugins/class_table_inheritance.rb +19 -10
- data/lib/sequel/plugins/column_conflicts.rb +7 -2
- data/lib/sequel/plugins/column_select.rb +1 -1
- data/lib/sequel/plugins/csv_serializer.rb +8 -8
- data/lib/sequel/plugins/defaults_setter.rb +10 -0
- data/lib/sequel/plugins/eager_each.rb +1 -1
- data/lib/sequel/plugins/force_encoding.rb +2 -2
- data/lib/sequel/plugins/hook_class_methods.rb +9 -12
- data/lib/sequel/plugins/identifier_columns.rb +2 -0
- data/lib/sequel/plugins/instance_filters.rb +3 -1
- data/lib/sequel/plugins/instance_hooks.rb +17 -9
- data/lib/sequel/plugins/json_serializer.rb +17 -10
- data/lib/sequel/plugins/lazy_attributes.rb +8 -7
- data/lib/sequel/plugins/modification_detection.rb +3 -0
- data/lib/sequel/plugins/nested_attributes.rb +5 -1
- data/lib/sequel/plugins/pg_array_associations.rb +5 -0
- data/lib/sequel/plugins/prepared_statements.rb +1 -0
- data/lib/sequel/plugins/rcte_tree.rb +4 -4
- data/lib/sequel/plugins/serialization.rb +3 -10
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/split_values.rb +6 -5
- data/lib/sequel/plugins/static_cache.rb +31 -25
- data/lib/sequel/plugins/subset_conditions.rb +3 -1
- data/lib/sequel/plugins/table_select.rb +1 -1
- data/lib/sequel/plugins/touch.rb +2 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -6
- data/lib/sequel/plugins/validation_helpers.rb +2 -4
- data/lib/sequel/plugins/xml_serializer.rb +4 -4
- data/lib/sequel/sql.rb +2 -2
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +115 -14
- data/spec/adapters/mysql_spec.rb +78 -28
- data/spec/adapters/oracle_spec.rb +24 -24
- data/spec/adapters/postgres_spec.rb +38 -24
- data/spec/adapters/sqlanywhere_spec.rb +88 -86
- data/spec/adapters/sqlite_spec.rb +29 -24
- data/spec/core/connection_pool_spec.rb +17 -0
- data/spec/core/database_spec.rb +6 -0
- data/spec/core/dataset_spec.rb +46 -36
- data/spec/core/schema_spec.rb +16 -0
- data/spec/core/spec_helper.rb +1 -0
- data/spec/core_extensions_spec.rb +6 -2
- data/spec/extensions/active_model_spec.rb +1 -1
- data/spec/extensions/arbitrary_servers_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +34 -2
- data/spec/extensions/auto_literal_strings_spec.rb +5 -1
- data/spec/extensions/auto_validations_spec.rb +2 -0
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/boolean_subsets_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +48 -2
- data/spec/extensions/column_conflicts_spec.rb +11 -0
- data/spec/extensions/connection_validator_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +8 -8
- data/spec/extensions/defaults_setter_spec.rb +1 -1
- data/spec/extensions/filter_having_spec.rb +5 -3
- data/spec/extensions/hash_aliases_spec.rb +3 -1
- data/spec/extensions/identifier_columns_spec.rb +3 -1
- data/spec/extensions/implicit_subquery_spec.rb +4 -2
- data/spec/extensions/json_serializer_spec.rb +18 -0
- data/spec/extensions/lazy_attributes_spec.rb +3 -3
- data/spec/extensions/meta_def_spec.rb +9 -0
- data/spec/extensions/migration_spec.rb +3 -3
- data/spec/extensions/nested_attributes_spec.rb +14 -3
- data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
- data/spec/extensions/pg_array_associations_spec.rb +29 -18
- data/spec/extensions/pg_array_spec.rb +44 -25
- data/spec/extensions/pg_hstore_spec.rb +10 -0
- data/spec/extensions/pg_inet_spec.rb +26 -0
- data/spec/extensions/pg_interval_spec.rb +20 -0
- data/spec/extensions/pg_json_spec.rb +24 -0
- data/spec/extensions/pg_range_spec.rb +98 -14
- data/spec/extensions/pg_row_spec.rb +14 -4
- data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +3 -1
- data/spec/extensions/schema_dumper_spec.rb +96 -98
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/static_cache_spec.rb +75 -24
- data/spec/extensions/string_agg_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +9 -0
- data/spec/extensions/validation_helpers_spec.rb +9 -3
- data/spec/extensions/whitelist_security_spec.rb +26 -0
- data/spec/integration/dataset_test.rb +45 -44
- data/spec/integration/plugin_test.rb +20 -0
- data/spec/integration/prepared_statement_test.rb +3 -0
- data/spec/integration/schema_test.rb +21 -1
- data/spec/integration/transaction_test.rb +40 -40
- data/spec/model/class_dataset_methods_spec.rb +14 -4
- data/spec/model/dataset_methods_spec.rb +12 -3
- data/spec/model/model_spec.rb +8 -0
- metadata +6 -4
- data/spec/adapters/firebird_spec.rb +0 -405
- data/spec/adapters/informix_spec.rb +0 -100
|
@@ -13,6 +13,16 @@ module Sequel
|
|
|
13
13
|
# album = Album.new(:a=>1, :b=>3)
|
|
14
14
|
# album.a # => 1
|
|
15
15
|
# album.b # => 3
|
|
16
|
+
#
|
|
17
|
+
# You can manually set default values as well:
|
|
18
|
+
#
|
|
19
|
+
# Album.default_values[:a] = 4
|
|
20
|
+
# Album.new.a # => 4
|
|
21
|
+
#
|
|
22
|
+
# You can also provide procs to set default values:
|
|
23
|
+
#
|
|
24
|
+
# Album.default_values[:a] = lambda{Date.today}
|
|
25
|
+
# Album.new.a # => Date.today
|
|
16
26
|
#
|
|
17
27
|
# Usage:
|
|
18
28
|
#
|
|
@@ -14,11 +14,11 @@ module Sequel
|
|
|
14
14
|
#
|
|
15
15
|
# Usage:
|
|
16
16
|
#
|
|
17
|
-
# # Force all strings to be
|
|
17
|
+
# # Force all strings to be UTF-8 encoded in a all model subclasses
|
|
18
18
|
# # (called before loading subclasses)
|
|
19
19
|
# Sequel::Model.plugin :force_encoding, 'UTF-8'
|
|
20
20
|
#
|
|
21
|
-
# # Force the encoding for the Album model to
|
|
21
|
+
# # Force the encoding for the Album model to UTF-8
|
|
22
22
|
# Album.plugin :force_encoding
|
|
23
23
|
# Album.forced_encoding = 'UTF-8'
|
|
24
24
|
module ForceEncoding
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
module Sequel
|
|
4
4
|
module Plugins
|
|
5
|
-
# Sequel's built-in
|
|
5
|
+
# Sequel's built-in hook_class_methods plugin is designed for backwards
|
|
6
6
|
# compatibility. Its use is not encouraged, it is recommended to use
|
|
7
|
-
# instance methods and super instead of this plugin.
|
|
8
|
-
#
|
|
7
|
+
# instance methods and super instead of this plugin. This plugin allows
|
|
8
|
+
# calling class methods with blocks to define hooks:
|
|
9
9
|
#
|
|
10
10
|
# # Block only, can cause duplicate hooks if code is reloaded
|
|
11
11
|
# before_save{self.created_at = Time.now}
|
|
@@ -15,17 +15,14 @@ module Sequel
|
|
|
15
15
|
# before_save(:set_created_at)
|
|
16
16
|
#
|
|
17
17
|
# Pretty much anything you can do with a hook class method, you can also
|
|
18
|
-
# do with an instance method instead
|
|
18
|
+
# do with an instance method instead (making sure to call super), which is
|
|
19
|
+
# the recommended way to add hooks in Sequel:
|
|
19
20
|
#
|
|
20
21
|
# def before_save
|
|
21
|
-
#
|
|
22
|
+
# super
|
|
22
23
|
# self.created_at = Time.now
|
|
23
24
|
# end
|
|
24
25
|
#
|
|
25
|
-
# Note that returning false in any before hook block will skip further
|
|
26
|
-
# before hooks and abort the action. So if a before_save hook block returns
|
|
27
|
-
# false, future before_save hook blocks are not called, and the save is aborted.
|
|
28
|
-
#
|
|
29
26
|
# Usage:
|
|
30
27
|
#
|
|
31
28
|
# # Allow use of hook class methods in all model subclasses (called before loading subclasses)
|
|
@@ -91,7 +88,6 @@ module Sequel
|
|
|
91
88
|
# arbitrary code execution.
|
|
92
89
|
def add_hook_type(*hooks)
|
|
93
90
|
Sequel::Deprecation.deprecate("Sequel::Model.add_hook_type", "You should add your own hook types manually")
|
|
94
|
-
Model::HOOKS.concat(hooks)
|
|
95
91
|
hooks.each do |hook|
|
|
96
92
|
@hooks[hook] = []
|
|
97
93
|
instance_eval("def #{hook}(method = nil, &block); add_hook(:#{hook}, method, &block) end", __FILE__, __LINE__)
|
|
@@ -141,7 +137,8 @@ module Sequel
|
|
|
141
137
|
end
|
|
142
138
|
|
|
143
139
|
module InstanceMethods
|
|
144
|
-
|
|
140
|
+
# SEQUEL5: Make :before_save, :before_destroy, :after_save, :after_destroy hooks use metaprogramming instead of specific definitions
|
|
141
|
+
[:before_create, :before_update, :before_validation].each do |h|
|
|
145
142
|
class_eval(<<-END, __FILE__, __LINE__+1)
|
|
146
143
|
def #{h}
|
|
147
144
|
model.hook_blocks(:#{h}) do |b|
|
|
@@ -154,7 +151,7 @@ module Sequel
|
|
|
154
151
|
end
|
|
155
152
|
END
|
|
156
153
|
end
|
|
157
|
-
|
|
154
|
+
[:after_create, :after_update, :after_validation].each{|h| class_eval("def #{h}; super; model.hook_blocks(:#{h}){|b| instance_eval(&b)}; end", __FILE__, __LINE__)}
|
|
158
155
|
|
|
159
156
|
def after_destroy
|
|
160
157
|
super
|
|
@@ -7,7 +7,9 @@ module Sequel
|
|
|
7
7
|
# where you would normally have to drop down to the dataset level
|
|
8
8
|
# to get the necessary control, because you only want to delete or
|
|
9
9
|
# update the rows in certain cases based on the current status of
|
|
10
|
-
# the row in the database.
|
|
10
|
+
# the row in the database. The main purpose of this plugin is to
|
|
11
|
+
# avoid race conditions by relying on the atomic properties of database
|
|
12
|
+
# transactions.
|
|
11
13
|
#
|
|
12
14
|
# class Item < Sequel::Model
|
|
13
15
|
# plugin :instance_filters
|
|
@@ -9,8 +9,7 @@ module Sequel
|
|
|
9
9
|
# All of the standard hooks are supported.
|
|
10
10
|
# Instance level before hooks are executed in reverse order of addition before
|
|
11
11
|
# calling super. Instance level after hooks are executed in order of addition
|
|
12
|
-
# after calling super.
|
|
13
|
-
# false, no more instance level before hooks are called and false is returned.
|
|
12
|
+
# after calling super.
|
|
14
13
|
#
|
|
15
14
|
# Instance level hooks for before and after are cleared after all related
|
|
16
15
|
# after level instance hooks have run. This means that if you add a before_create
|
|
@@ -29,9 +28,12 @@ module Sequel
|
|
|
29
28
|
# # Add the instance hook methods just to Album instances
|
|
30
29
|
# Album.plugin :instance_hooks
|
|
31
30
|
module InstanceHooks
|
|
32
|
-
BEFORE_HOOKS = Sequel::Model::
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
BEFORE_HOOKS, AFTER_HOOKS = Sequel::Model::HOOKS.partition{|l| l.to_s.start_with?('before')}
|
|
32
|
+
Sequel::Deprecation.deprecate_constant(self, :BEFORE_HOOKS)
|
|
33
|
+
Sequel::Deprecation.deprecate_constant(self, :AFTER_HOOKS)
|
|
34
|
+
HOOKS = Sequel::Model::HOOKS
|
|
35
|
+
Sequel::Deprecation.deprecate_constant(self, :HOOKS)
|
|
36
|
+
|
|
35
37
|
# SEQUEL5: Remove
|
|
36
38
|
DEPRECATION_REPLACEMENTS = {
|
|
37
39
|
:after_commit=>"Use obj.after_save_hook{obj.db.after_commit{}} instead",
|
|
@@ -41,7 +43,7 @@ module Sequel
|
|
|
41
43
|
}.freeze
|
|
42
44
|
|
|
43
45
|
module InstanceMethods
|
|
44
|
-
HOOKS.each{|h| class_eval(<<-END , __FILE__, __LINE__+1)}
|
|
46
|
+
Sequel::Model::HOOKS.each{|h| class_eval(<<-END , __FILE__, __LINE__+1)}
|
|
45
47
|
def #{h}_hook(&block)
|
|
46
48
|
#{"Sequel::Deprecation.deprecate('Sequel::Model##{h}_hook in the instance_hooks plugin', #{DEPRECATION_REPLACEMENTS[h].inspect})" if DEPRECATION_REPLACEMENTS[h]}
|
|
47
49
|
raise Sequel::Error, "can't add hooks to frozen object" if frozen?
|
|
@@ -50,8 +52,8 @@ module Sequel
|
|
|
50
52
|
end
|
|
51
53
|
END
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
[:before_create, :before_update, :before_validation].each{|h| class_eval("def #{h}; (@instance_hooks && run_before_instance_hooks(:#{h}) == false) ? false : super end", __FILE__, __LINE__)}
|
|
56
|
+
[:after_create, :after_update].each{|h| class_eval(<<-END, __FILE__, __LINE__ + 1)}
|
|
55
57
|
def #{h}
|
|
56
58
|
super
|
|
57
59
|
return unless @instance_hooks
|
|
@@ -65,6 +67,7 @@ module Sequel
|
|
|
65
67
|
def after_destroy
|
|
66
68
|
super
|
|
67
69
|
return unless @instance_hooks
|
|
70
|
+
# SEQUEL5: Remove commit/rollback
|
|
68
71
|
if ad = @instance_hooks[:after_destroy_commit]
|
|
69
72
|
db.after_commit{ad.each(&:call)}
|
|
70
73
|
end
|
|
@@ -86,6 +89,7 @@ module Sequel
|
|
|
86
89
|
def after_save
|
|
87
90
|
super
|
|
88
91
|
return unless @instance_hooks
|
|
92
|
+
# SEQUEL5: Remove commit/rollback
|
|
89
93
|
if (ac = @instance_hooks[:after_commit])
|
|
90
94
|
db.after_commit{ac.each(&:call)}
|
|
91
95
|
end
|
|
@@ -101,18 +105,22 @@ module Sequel
|
|
|
101
105
|
# Run before_destroy instance hooks.
|
|
102
106
|
def before_destroy
|
|
103
107
|
return super unless @instance_hooks
|
|
108
|
+
# SEQUEL5: Remove commit/rollback
|
|
104
109
|
if adr = @instance_hooks[:after_destroy_rollback]
|
|
105
110
|
db.after_rollback{adr.each(&:call)}
|
|
106
111
|
end
|
|
112
|
+
# SEQUEL5: No false checking
|
|
107
113
|
run_before_instance_hooks(:before_destroy) == false ? false : super
|
|
108
114
|
end
|
|
109
115
|
|
|
110
116
|
# Run before_save instance hooks.
|
|
111
117
|
def before_save
|
|
112
118
|
return super unless @instance_hooks
|
|
119
|
+
# SEQUEL5: Remove commit/rollback
|
|
113
120
|
if ar = @instance_hooks[:after_rollback]
|
|
114
121
|
db.after_rollback{ar.each(&:call)}
|
|
115
122
|
end
|
|
123
|
+
# SEQUEL5: No false checking
|
|
116
124
|
run_before_instance_hooks(:before_save) == false ? false : super
|
|
117
125
|
end
|
|
118
126
|
|
|
@@ -122,7 +130,7 @@ module Sequel
|
|
|
122
130
|
# the beginning of the instance hook's array. For after hooks, add it
|
|
123
131
|
# to the end.
|
|
124
132
|
def add_instance_hook(hook, &block)
|
|
125
|
-
instance_hooks(hook).send(
|
|
133
|
+
instance_hooks(hook).send(hook.to_s.start_with?('before') ? :unshift : :push, block)
|
|
126
134
|
end
|
|
127
135
|
|
|
128
136
|
# An array of instance level hook blocks for the given hook type.
|
|
@@ -62,6 +62,11 @@ module Sequel
|
|
|
62
62
|
#
|
|
63
63
|
# Album.to_json(:array=>[Album[1], Album[2]])
|
|
64
64
|
#
|
|
65
|
+
# All to_json methods take blocks, and if a block is given, it will yield
|
|
66
|
+
# the array or hash before serialization, and will serialize the value
|
|
67
|
+
# the block returns. This allows you to customize the resulting JSON format
|
|
68
|
+
# on a per-call basis.
|
|
69
|
+
#
|
|
65
70
|
# In addition to creating JSON, this plugin also enables Sequel::Model
|
|
66
71
|
# classes to create instances directly from JSON using the from_json class
|
|
67
72
|
# method:
|
|
@@ -126,9 +131,9 @@ module Sequel
|
|
|
126
131
|
module JsonSerializer
|
|
127
132
|
# Set up the column readers to do deserialization and the column writers
|
|
128
133
|
# to save the value in deserialized_values.
|
|
129
|
-
def self.configure(model, opts=
|
|
134
|
+
def self.configure(model, opts=OPTS)
|
|
130
135
|
model.instance_eval do
|
|
131
|
-
@json_serializer_opts = (@json_serializer_opts ||
|
|
136
|
+
@json_serializer_opts = (@json_serializer_opts || OPTS).merge(opts)
|
|
132
137
|
end
|
|
133
138
|
end
|
|
134
139
|
|
|
@@ -222,10 +227,10 @@ module Sequel
|
|
|
222
227
|
if assocs = opts[:associations]
|
|
223
228
|
assocs = case assocs
|
|
224
229
|
when Symbol
|
|
225
|
-
{assocs=>
|
|
230
|
+
{assocs=>OPTS}
|
|
226
231
|
when Array
|
|
227
232
|
assocs_tmp = {}
|
|
228
|
-
assocs.each{|v| assocs_tmp[v] =
|
|
233
|
+
assocs.each{|v| assocs_tmp[v] = OPTS}
|
|
229
234
|
assocs_tmp
|
|
230
235
|
when Hash
|
|
231
236
|
assocs
|
|
@@ -358,6 +363,7 @@ module Sequel
|
|
|
358
363
|
h = {root => h}
|
|
359
364
|
end
|
|
360
365
|
|
|
366
|
+
h = yield h if block_given?
|
|
361
367
|
Sequel.object_to_json(h, *a)
|
|
362
368
|
end
|
|
363
369
|
end
|
|
@@ -370,6 +376,8 @@ module Sequel
|
|
|
370
376
|
#
|
|
371
377
|
# :array :: An array of instances. If this is not provided,
|
|
372
378
|
# calls #all on the receiver to get the array.
|
|
379
|
+
# :instance_block :: A block to pass to #to_json for each
|
|
380
|
+
# value in the dataset (or :array option).
|
|
373
381
|
# :root :: If set to :collection, wraps the collection
|
|
374
382
|
# in a root object using the pluralized, underscored model
|
|
375
383
|
# name as the key. If set to :instance, only wraps
|
|
@@ -405,16 +413,15 @@ module Sequel
|
|
|
405
413
|
else
|
|
406
414
|
all
|
|
407
415
|
end
|
|
408
|
-
array.map{|obj| Literal.new(Sequel.object_to_json(obj, opts))}
|
|
416
|
+
array.map{|obj| Literal.new(Sequel.object_to_json(obj, opts, &opts[:instance_block]))}
|
|
409
417
|
else
|
|
410
418
|
all
|
|
411
419
|
end
|
|
412
420
|
|
|
413
|
-
if collection_root
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
end
|
|
421
|
+
res = {collection_root => res} if collection_root
|
|
422
|
+
res = yield res if block_given?
|
|
423
|
+
|
|
424
|
+
Sequel.object_to_json(res, *a)
|
|
418
425
|
end
|
|
419
426
|
end
|
|
420
427
|
end
|
|
@@ -92,9 +92,8 @@ module Sequel
|
|
|
92
92
|
# the attribute for just the current object. Return the value of
|
|
93
93
|
# the attribute for the current object.
|
|
94
94
|
def lazy_attribute_lookup(a, opts=OPTS)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
end
|
|
95
|
+
table = opts[:table] || model.table_name
|
|
96
|
+
selection = Sequel.qualify(table, a)
|
|
98
97
|
|
|
99
98
|
if base_ds = opts[:dataset]
|
|
100
99
|
ds = base_ds.where(qualified_pk_hash(table))
|
|
@@ -103,10 +102,8 @@ module Sequel
|
|
|
103
102
|
ds = this
|
|
104
103
|
end
|
|
105
104
|
|
|
106
|
-
selection = Sequel.qualify(table, a)
|
|
107
|
-
|
|
108
105
|
if frozen?
|
|
109
|
-
return ds.
|
|
106
|
+
return ds.get(selection)
|
|
110
107
|
end
|
|
111
108
|
|
|
112
109
|
if retrieved_with
|
|
@@ -115,7 +112,11 @@ module Sequel
|
|
|
115
112
|
id_map = {}
|
|
116
113
|
retrieved_with.each{|o| id_map[o.pk] = o unless o.values.has_key?(a) || o.frozen?}
|
|
117
114
|
predicate_key = composite_pk ? primary_key.map{|k| Sequel.qualify(table, k)} : Sequel.qualify(table, primary_key)
|
|
118
|
-
base_ds.
|
|
115
|
+
base_ds.
|
|
116
|
+
select(*(Array(primary_key).map{|k| Sequel.qualify(table, k)} + [selection])).
|
|
117
|
+
where(predicate_key=>id_map.keys).
|
|
118
|
+
naked.
|
|
119
|
+
each do |row|
|
|
119
120
|
obj = id_map[composite_pk ? row.values_at(*primary_key) : row[primary_key]]
|
|
120
121
|
if obj && !obj.values.has_key?(a)
|
|
121
122
|
obj.values[a] = row[a]
|
|
@@ -17,6 +17,9 @@ module Sequel
|
|
|
17
17
|
# Note that for this plugin to work correctly, the column values must
|
|
18
18
|
# correctly implement the #hash method, returning the same value if
|
|
19
19
|
# the object is equal, and a different value if the object is not equal.
|
|
20
|
+
# As this solely uses hash values to check for modification, there may
|
|
21
|
+
# be cases where a modification is made and the hash value is the same,
|
|
22
|
+
# resulting in a false negative.
|
|
20
23
|
#
|
|
21
24
|
# Note that this plugin causes a performance hit for all retrieved
|
|
22
25
|
# objects, so it shouldn't be used in cases where performance is a
|
|
@@ -127,7 +127,11 @@ module Sequel
|
|
|
127
127
|
reflections = associations.map{|a| association_reflection(a) || raise(Error, "no association named #{a} for #{self}")}
|
|
128
128
|
reflections.each do |r|
|
|
129
129
|
r[:nested_attributes] = opts
|
|
130
|
-
r[:nested_attributes][:unmatched_pk] ||=
|
|
130
|
+
r[:nested_attributes][:unmatched_pk] ||= (
|
|
131
|
+
if opts.has_key?(:strict)
|
|
132
|
+
Sequel::Deprecation.deprecate("The nested_attributes :strict option", "Use the :unmatched_pk option instead")
|
|
133
|
+
end
|
|
134
|
+
opts.delete(:strict) == false ? :ignore : :raise)
|
|
131
135
|
r[:nested_attributes][:reject_if] ||= block
|
|
132
136
|
def_nested_attribute_method(r)
|
|
133
137
|
end
|
|
@@ -297,6 +297,11 @@ module Sequel
|
|
|
297
297
|
end
|
|
298
298
|
end
|
|
299
299
|
|
|
300
|
+
# Add the pg_array extension to the database
|
|
301
|
+
def self.apply(model)
|
|
302
|
+
model.db.extension(:pg_array)
|
|
303
|
+
end
|
|
304
|
+
|
|
300
305
|
module ClassMethods
|
|
301
306
|
# Create a many_to_pg_array association, for the case where the associated
|
|
302
307
|
# table contains the array with foreign keys pointing to the current table.
|
|
@@ -133,7 +133,7 @@ module Sequel
|
|
|
133
133
|
base_ds = model.where(prkey_array.zip(key_array.map{|k| get_column_value(k)}))
|
|
134
134
|
recursive_ds = model.join(t, key_array.zip(prkey_array))
|
|
135
135
|
if c = a[:conditions]
|
|
136
|
-
(base_ds, recursive_ds) = [base_ds, recursive_ds].
|
|
136
|
+
(base_ds, recursive_ds) = [base_ds, recursive_ds].map do |ds|
|
|
137
137
|
(c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.where(*c) : ds.where(c)
|
|
138
138
|
end
|
|
139
139
|
end
|
|
@@ -181,7 +181,7 @@ module Sequel
|
|
|
181
181
|
recursive_case = model.join(t, key_array.zip(prkey_array)).
|
|
182
182
|
select(*recursive_case_columns)
|
|
183
183
|
if c = r[:conditions]
|
|
184
|
-
(base_case, recursive_case) = [base_case, recursive_case].
|
|
184
|
+
(base_case, recursive_case) = [base_case, recursive_case].map do |ds|
|
|
185
185
|
(c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.where(*c) : ds.where(c)
|
|
186
186
|
end
|
|
187
187
|
end
|
|
@@ -228,7 +228,7 @@ module Sequel
|
|
|
228
228
|
base_ds = model.where(key_array.zip(prkey_array.map{|k| get_column_value(k)}))
|
|
229
229
|
recursive_ds = model.join(t, prkey_array.zip(key_array))
|
|
230
230
|
if c = d[:conditions]
|
|
231
|
-
(base_ds, recursive_ds) = [base_ds, recursive_ds].
|
|
231
|
+
(base_ds, recursive_ds) = [base_ds, recursive_ds].map do |ds|
|
|
232
232
|
(c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.where(*c) : ds.where(c)
|
|
233
233
|
end
|
|
234
234
|
end
|
|
@@ -279,7 +279,7 @@ module Sequel
|
|
|
279
279
|
recursive_case = model.join(t, prkey_array.zip(key_array)).
|
|
280
280
|
select(*recursive_case_columns)
|
|
281
281
|
if c = r[:conditions]
|
|
282
|
-
(base_case, recursive_case) = [base_case, recursive_case].
|
|
282
|
+
(base_case, recursive_case) = [base_case, recursive_case].map do |ds|
|
|
283
283
|
(c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.where(*c) : ds.where(c)
|
|
284
284
|
end
|
|
285
285
|
end
|
|
@@ -97,16 +97,9 @@ module Sequel
|
|
|
97
97
|
end
|
|
98
98
|
register_format(:marshal, lambda{|v| [Marshal.dump(v)].pack('m')},
|
|
99
99
|
lambda do |v|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
begin
|
|
104
|
-
# Backwards compatibility for unpacked marshal output.
|
|
105
|
-
Marshal.load(v)
|
|
106
|
-
rescue
|
|
107
|
-
raise e
|
|
108
|
-
end
|
|
109
|
-
end
|
|
100
|
+
# Handle unpacked marshalled data for backwards compat
|
|
101
|
+
v = v.unpack('m')[0] unless v[0..1] == "\x04\x08"
|
|
102
|
+
Marshal.load(v)
|
|
110
103
|
end)
|
|
111
104
|
register_format(:yaml, lambda(&:to_yaml), lambda{|v| YAML.load(v)})
|
|
112
105
|
register_format(:json, lambda{|v| Sequel.object_to_json(v)}, lambda{|v| Sequel.parse_json(v)})
|
|
@@ -95,7 +95,7 @@ module Sequel
|
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
97
|
km.each do |k,v|
|
|
98
|
-
h[k.to_s] = [
|
|
98
|
+
h[k.to_s] = [] unless h.key?(k.to_s)
|
|
99
99
|
h[k.to_s].push( *Array(v) )
|
|
100
100
|
end
|
|
101
101
|
h
|
|
@@ -111,7 +111,7 @@ module Sequel
|
|
|
111
111
|
end
|
|
112
112
|
end
|
|
113
113
|
sti_model_map.each do |k,v|
|
|
114
|
-
h[v.to_s] = [
|
|
114
|
+
h[v.to_s] = [] unless h.key?(v.to_s)
|
|
115
115
|
h[v.to_s] << k
|
|
116
116
|
end
|
|
117
117
|
h
|
|
@@ -57,11 +57,12 @@ module Sequel
|
|
|
57
57
|
# Check all entries in the values hash. If any of the keys are not columns,
|
|
58
58
|
# move the entry into the noncolumn_values hash.
|
|
59
59
|
def split_noncolumn_values
|
|
60
|
-
@values.keys
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
cols = (@values.keys - columns)
|
|
61
|
+
return self if cols.empty?
|
|
62
|
+
|
|
63
|
+
nc = @noncolumn_values ||= {}
|
|
64
|
+
vals = @values
|
|
65
|
+
cols.each{|k| nc[k] = vals.delete(k)}
|
|
65
66
|
self
|
|
66
67
|
end
|
|
67
68
|
end
|