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.
Files changed (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +134 -0
  3. data/Rakefile +1 -1
  4. data/doc/release_notes/4.48.0.txt +293 -0
  5. data/lib/sequel/adapters/ado/access.rb +2 -1
  6. data/lib/sequel/adapters/do/postgres.rb +5 -2
  7. data/lib/sequel/adapters/ibmdb.rb +24 -7
  8. data/lib/sequel/adapters/jdbc.rb +36 -22
  9. data/lib/sequel/adapters/jdbc/db2.rb +12 -3
  10. data/lib/sequel/adapters/jdbc/derby.rb +4 -5
  11. data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
  12. data/lib/sequel/adapters/jdbc/postgresql.rb +43 -18
  13. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
  14. data/lib/sequel/adapters/jdbc/sqlserver.rb +11 -4
  15. data/lib/sequel/adapters/mock.rb +24 -19
  16. data/lib/sequel/adapters/mysql.rb +17 -16
  17. data/lib/sequel/adapters/mysql2.rb +4 -5
  18. data/lib/sequel/adapters/oracle.rb +5 -9
  19. data/lib/sequel/adapters/postgres.rb +89 -102
  20. data/lib/sequel/adapters/shared/db2.rb +22 -6
  21. data/lib/sequel/adapters/shared/mssql.rb +5 -4
  22. data/lib/sequel/adapters/shared/mysql.rb +75 -24
  23. data/lib/sequel/adapters/shared/postgres.rb +196 -94
  24. data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
  25. data/lib/sequel/adapters/shared/sqlite.rb +72 -82
  26. data/lib/sequel/adapters/sqlanywhere.rb +4 -1
  27. data/lib/sequel/adapters/sqlite.rb +5 -3
  28. data/lib/sequel/adapters/swift/postgres.rb +5 -2
  29. data/lib/sequel/adapters/tinytds.rb +0 -5
  30. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
  31. data/lib/sequel/adapters/utils/pg_types.rb +2 -76
  32. data/lib/sequel/core.rb +2 -2
  33. data/lib/sequel/database/connecting.rb +5 -5
  34. data/lib/sequel/database/dataset.rb +6 -3
  35. data/lib/sequel/database/misc.rb +1 -1
  36. data/lib/sequel/database/query.rb +3 -0
  37. data/lib/sequel/database/schema_methods.rb +1 -1
  38. data/lib/sequel/dataset/actions.rb +18 -10
  39. data/lib/sequel/dataset/graph.rb +1 -1
  40. data/lib/sequel/dataset/misc.rb +1 -0
  41. data/lib/sequel/dataset/prepared_statements.rb +3 -3
  42. data/lib/sequel/dataset/query.rb +19 -8
  43. data/lib/sequel/extensions/core_extensions.rb +4 -1
  44. data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
  45. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
  46. data/lib/sequel/extensions/filter_having.rb +2 -0
  47. data/lib/sequel/extensions/freeze_datasets.rb +2 -0
  48. data/lib/sequel/extensions/from_block.rb +1 -1
  49. data/lib/sequel/extensions/graph_each.rb +2 -2
  50. data/lib/sequel/extensions/hash_aliases.rb +2 -0
  51. data/lib/sequel/extensions/identifier_mangling.rb +0 -7
  52. data/lib/sequel/extensions/meta_def.rb +2 -0
  53. data/lib/sequel/extensions/migration.rb +6 -6
  54. data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
  55. data/lib/sequel/extensions/pagination.rb +1 -1
  56. data/lib/sequel/extensions/pg_array.rb +207 -130
  57. data/lib/sequel/extensions/pg_hstore.rb +38 -20
  58. data/lib/sequel/extensions/pg_inet.rb +18 -6
  59. data/lib/sequel/extensions/pg_interval.rb +19 -12
  60. data/lib/sequel/extensions/pg_json.rb +25 -14
  61. data/lib/sequel/extensions/pg_json_ops.rb +2 -2
  62. data/lib/sequel/extensions/pg_range.rb +133 -100
  63. data/lib/sequel/extensions/pg_range_ops.rb +4 -3
  64. data/lib/sequel/extensions/pg_row.rb +68 -39
  65. data/lib/sequel/extensions/pg_row_ops.rb +11 -5
  66. data/lib/sequel/extensions/query_literals.rb +2 -0
  67. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
  68. data/lib/sequel/extensions/s.rb +1 -1
  69. data/lib/sequel/extensions/schema_dumper.rb +24 -24
  70. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
  71. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
  72. data/lib/sequel/extensions/set_overrides.rb +2 -2
  73. data/lib/sequel/extensions/string_agg.rb +0 -1
  74. data/lib/sequel/extensions/symbol_aref.rb +0 -4
  75. data/lib/sequel/model.rb +25 -57
  76. data/lib/sequel/model/associations.rb +14 -5
  77. data/lib/sequel/model/base.rb +96 -32
  78. data/lib/sequel/plugins/association_pks.rb +73 -46
  79. data/lib/sequel/plugins/association_proxies.rb +1 -1
  80. data/lib/sequel/plugins/auto_validations.rb +6 -2
  81. data/lib/sequel/plugins/boolean_readers.rb +1 -1
  82. data/lib/sequel/plugins/caching.rb +19 -13
  83. data/lib/sequel/plugins/class_table_inheritance.rb +19 -10
  84. data/lib/sequel/plugins/column_conflicts.rb +7 -2
  85. data/lib/sequel/plugins/column_select.rb +1 -1
  86. data/lib/sequel/plugins/csv_serializer.rb +8 -8
  87. data/lib/sequel/plugins/defaults_setter.rb +10 -0
  88. data/lib/sequel/plugins/eager_each.rb +1 -1
  89. data/lib/sequel/plugins/force_encoding.rb +2 -2
  90. data/lib/sequel/plugins/hook_class_methods.rb +9 -12
  91. data/lib/sequel/plugins/identifier_columns.rb +2 -0
  92. data/lib/sequel/plugins/instance_filters.rb +3 -1
  93. data/lib/sequel/plugins/instance_hooks.rb +17 -9
  94. data/lib/sequel/plugins/json_serializer.rb +17 -10
  95. data/lib/sequel/plugins/lazy_attributes.rb +8 -7
  96. data/lib/sequel/plugins/modification_detection.rb +3 -0
  97. data/lib/sequel/plugins/nested_attributes.rb +5 -1
  98. data/lib/sequel/plugins/pg_array_associations.rb +5 -0
  99. data/lib/sequel/plugins/prepared_statements.rb +1 -0
  100. data/lib/sequel/plugins/rcte_tree.rb +4 -4
  101. data/lib/sequel/plugins/serialization.rb +3 -10
  102. data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
  103. data/lib/sequel/plugins/split_values.rb +6 -5
  104. data/lib/sequel/plugins/static_cache.rb +31 -25
  105. data/lib/sequel/plugins/subset_conditions.rb +3 -1
  106. data/lib/sequel/plugins/table_select.rb +1 -1
  107. data/lib/sequel/plugins/touch.rb +2 -1
  108. data/lib/sequel/plugins/validation_class_methods.rb +5 -6
  109. data/lib/sequel/plugins/validation_helpers.rb +2 -4
  110. data/lib/sequel/plugins/xml_serializer.rb +4 -4
  111. data/lib/sequel/sql.rb +2 -2
  112. data/lib/sequel/version.rb +1 -1
  113. data/spec/adapters/db2_spec.rb +115 -14
  114. data/spec/adapters/mysql_spec.rb +78 -28
  115. data/spec/adapters/oracle_spec.rb +24 -24
  116. data/spec/adapters/postgres_spec.rb +38 -24
  117. data/spec/adapters/sqlanywhere_spec.rb +88 -86
  118. data/spec/adapters/sqlite_spec.rb +29 -24
  119. data/spec/core/connection_pool_spec.rb +17 -0
  120. data/spec/core/database_spec.rb +6 -0
  121. data/spec/core/dataset_spec.rb +46 -36
  122. data/spec/core/schema_spec.rb +16 -0
  123. data/spec/core/spec_helper.rb +1 -0
  124. data/spec/core_extensions_spec.rb +6 -2
  125. data/spec/extensions/active_model_spec.rb +1 -1
  126. data/spec/extensions/arbitrary_servers_spec.rb +1 -1
  127. data/spec/extensions/association_pks_spec.rb +34 -2
  128. data/spec/extensions/auto_literal_strings_spec.rb +5 -1
  129. data/spec/extensions/auto_validations_spec.rb +2 -0
  130. data/spec/extensions/boolean_readers_spec.rb +1 -1
  131. data/spec/extensions/boolean_subsets_spec.rb +1 -1
  132. data/spec/extensions/class_table_inheritance_spec.rb +48 -2
  133. data/spec/extensions/column_conflicts_spec.rb +11 -0
  134. data/spec/extensions/connection_validator_spec.rb +1 -1
  135. data/spec/extensions/dataset_associations_spec.rb +8 -8
  136. data/spec/extensions/defaults_setter_spec.rb +1 -1
  137. data/spec/extensions/filter_having_spec.rb +5 -3
  138. data/spec/extensions/hash_aliases_spec.rb +3 -1
  139. data/spec/extensions/identifier_columns_spec.rb +3 -1
  140. data/spec/extensions/implicit_subquery_spec.rb +4 -2
  141. data/spec/extensions/json_serializer_spec.rb +18 -0
  142. data/spec/extensions/lazy_attributes_spec.rb +3 -3
  143. data/spec/extensions/meta_def_spec.rb +9 -0
  144. data/spec/extensions/migration_spec.rb +3 -3
  145. data/spec/extensions/nested_attributes_spec.rb +14 -3
  146. data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
  147. data/spec/extensions/pg_array_associations_spec.rb +29 -18
  148. data/spec/extensions/pg_array_spec.rb +44 -25
  149. data/spec/extensions/pg_hstore_spec.rb +10 -0
  150. data/spec/extensions/pg_inet_spec.rb +26 -0
  151. data/spec/extensions/pg_interval_spec.rb +20 -0
  152. data/spec/extensions/pg_json_spec.rb +24 -0
  153. data/spec/extensions/pg_range_spec.rb +98 -14
  154. data/spec/extensions/pg_row_spec.rb +14 -4
  155. data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
  156. data/spec/extensions/query_literals_spec.rb +3 -1
  157. data/spec/extensions/schema_dumper_spec.rb +96 -98
  158. data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
  159. data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
  160. data/spec/extensions/single_table_inheritance_spec.rb +1 -1
  161. data/spec/extensions/spec_helper.rb +7 -1
  162. data/spec/extensions/static_cache_spec.rb +75 -24
  163. data/spec/extensions/string_agg_spec.rb +1 -1
  164. data/spec/extensions/touch_spec.rb +9 -0
  165. data/spec/extensions/validation_helpers_spec.rb +9 -3
  166. data/spec/extensions/whitelist_security_spec.rb +26 -0
  167. data/spec/integration/dataset_test.rb +45 -44
  168. data/spec/integration/plugin_test.rb +20 -0
  169. data/spec/integration/prepared_statement_test.rb +3 -0
  170. data/spec/integration/schema_test.rb +21 -1
  171. data/spec/integration/transaction_test.rb +40 -40
  172. data/spec/model/class_dataset_methods_spec.rb +14 -4
  173. data/spec/model/dataset_methods_spec.rb +12 -3
  174. data/spec/model/model_spec.rb +8 -0
  175. metadata +6 -4
  176. data/spec/adapters/firebird_spec.rb +0 -405
  177. 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
  #
@@ -39,7 +39,7 @@ module Sequel
39
39
  end
40
40
 
41
41
  # Call #all instead of #each if eager loading,
42
- # uless #each is being called by #all.
42
+ # unless #each is being called by #all.
43
43
  def each(&block)
44
44
  if use_eager_all?
45
45
  all(&block)
@@ -14,11 +14,11 @@ module Sequel
14
14
  #
15
15
  # Usage:
16
16
  #
17
- # # Force all strings to be UTF8 encoded in a all model subclasses
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 UTF8
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 hook class methods plugin is designed for backwards
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. What this plugin
8
- # allows you to do is, for example:
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
- # return false if super == false
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
- (Model::BEFORE_HOOKS - [:before_save, :before_destroy]).each do |h|
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
- (Model::AFTER_HOOKS - [:after_save, :after_destroy, :after_commit, :after_rollback, :after_destroy_commit, :after_destroy_rollback]).each{|h| class_eval("def #{h}; super; model.hook_blocks(:#{h}){|b| instance_eval(&b)}; end", __FILE__, __LINE__)}
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
@@ -1,5 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
+ Sequel::Deprecation.deprecate("The identifier_columns plugin", "Set Sequel.split_symbols = false instead")
4
+
3
5
  module Sequel
4
6
  module Plugins
5
7
  # The identifier_columns plugin makes Sequel automatically
@@ -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. If any of the instance level before hook blocks return
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::BEFORE_HOOKS
33
- AFTER_HOOKS = Sequel::Model::AFTER_HOOKS
34
- HOOKS = BEFORE_HOOKS + AFTER_HOOKS
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
- (BEFORE_HOOKS - [:before_destroy, :before_save]).each{|h| class_eval("def #{h}; (@instance_hooks && run_before_instance_hooks(:#{h}) == false) ? false : super end", __FILE__, __LINE__)}
54
- (AFTER_HOOKS - [:after_validation, :after_save, :after_destroy, :after_commit, :after_destroy_commit, :after_destroy_rollback, :after_rollback]).each{|h| class_eval(<<-END, __FILE__, __LINE__ + 1)}
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(BEFORE_HOOKS.include?(hook) ? :unshift : :push, block)
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 || {}).merge(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
- Sequel.object_to_json({collection_root => res}, *a)
415
- else
416
- Sequel.object_to_json(res, *a)
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
- unless table = opts[:table]
96
- table = model.table_name
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.dup.get(selection)
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.select(*(Array(primary_key).map{|k| Sequel.qualify(table, k)} + [selection])).where(predicate_key=>id_map.keys).naked.each do |row|
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] ||= opts.delete(:strict) == false ? :ignore : :raise
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.
@@ -225,6 +225,7 @@ module Sequel
225
225
  case type
226
226
  when :insert, :insert_select, :update
227
227
  true
228
+ # SEQUEL5: Remove :delete/:refresh
228
229
  when :delete
229
230
  return true unless model.fast_instance_delete_sql
230
231
 
@@ -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].collect do |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].collect do |ds|
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].collect do |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].collect do |ds|
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
- begin
101
- Marshal.load(v.unpack('m')[0])
102
- rescue => e
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] = [ ] unless h.key?(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] = [ ] unless h.key?(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.each do |k|
61
- unless columns.include?(k)
62
- (@noncolumn_values ||= {})[k] = @values.delete(k)
63
- end
64
- end
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