sequel 3.48.0 → 4.0.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 (267) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +114 -0
  3. data/Rakefile +10 -7
  4. data/doc/association_basics.rdoc +25 -23
  5. data/doc/code_order.rdoc +7 -0
  6. data/doc/core_extensions.rdoc +0 -10
  7. data/doc/object_model.rdoc +4 -1
  8. data/doc/querying.rdoc +3 -3
  9. data/doc/release_notes/4.0.0.txt +262 -0
  10. data/doc/security.rdoc +0 -28
  11. data/doc/testing.rdoc +8 -14
  12. data/lib/sequel/adapters/ado.rb +7 -11
  13. data/lib/sequel/adapters/ado/access.rb +8 -8
  14. data/lib/sequel/adapters/ado/mssql.rb +4 -4
  15. data/lib/sequel/adapters/amalgalite.rb +6 -6
  16. data/lib/sequel/adapters/cubrid.rb +7 -7
  17. data/lib/sequel/adapters/db2.rb +5 -9
  18. data/lib/sequel/adapters/dbi.rb +2 -6
  19. data/lib/sequel/adapters/do.rb +4 -4
  20. data/lib/sequel/adapters/firebird.rb +4 -4
  21. data/lib/sequel/adapters/ibmdb.rb +8 -8
  22. data/lib/sequel/adapters/informix.rb +2 -10
  23. data/lib/sequel/adapters/jdbc.rb +17 -17
  24. data/lib/sequel/adapters/jdbc/as400.rb +2 -2
  25. data/lib/sequel/adapters/jdbc/cubrid.rb +1 -1
  26. data/lib/sequel/adapters/jdbc/db2.rb +1 -1
  27. data/lib/sequel/adapters/jdbc/derby.rb +1 -1
  28. data/lib/sequel/adapters/jdbc/h2.rb +2 -2
  29. data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -1
  30. data/lib/sequel/adapters/jdbc/informix.rb +1 -1
  31. data/lib/sequel/adapters/jdbc/mssql.rb +2 -2
  32. data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
  33. data/lib/sequel/adapters/jdbc/oracle.rb +5 -1
  34. data/lib/sequel/adapters/jdbc/postgresql.rb +3 -3
  35. data/lib/sequel/adapters/jdbc/sqlite.rb +3 -3
  36. data/lib/sequel/adapters/jdbc/transactions.rb +3 -3
  37. data/lib/sequel/adapters/mock.rb +7 -7
  38. data/lib/sequel/adapters/mysql.rb +3 -3
  39. data/lib/sequel/adapters/mysql2.rb +4 -4
  40. data/lib/sequel/adapters/odbc.rb +2 -6
  41. data/lib/sequel/adapters/odbc/mssql.rb +1 -1
  42. data/lib/sequel/adapters/openbase.rb +1 -5
  43. data/lib/sequel/adapters/oracle.rb +13 -17
  44. data/lib/sequel/adapters/postgres.rb +20 -25
  45. data/lib/sequel/adapters/shared/cubrid.rb +3 -3
  46. data/lib/sequel/adapters/shared/db2.rb +2 -2
  47. data/lib/sequel/adapters/shared/firebird.rb +7 -7
  48. data/lib/sequel/adapters/shared/mssql.rb +9 -9
  49. data/lib/sequel/adapters/shared/mysql.rb +29 -13
  50. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +7 -7
  51. data/lib/sequel/adapters/shared/oracle.rb +22 -13
  52. data/lib/sequel/adapters/shared/postgres.rb +61 -46
  53. data/lib/sequel/adapters/shared/sqlite.rb +9 -9
  54. data/lib/sequel/adapters/sqlite.rb +17 -11
  55. data/lib/sequel/adapters/swift.rb +3 -3
  56. data/lib/sequel/adapters/swift/mysql.rb +1 -1
  57. data/lib/sequel/adapters/swift/sqlite.rb +1 -1
  58. data/lib/sequel/adapters/tinytds.rb +8 -8
  59. data/lib/sequel/ast_transformer.rb +3 -1
  60. data/lib/sequel/connection_pool.rb +4 -2
  61. data/lib/sequel/connection_pool/sharded_single.rb +2 -2
  62. data/lib/sequel/connection_pool/sharded_threaded.rb +5 -5
  63. data/lib/sequel/connection_pool/threaded.rb +7 -7
  64. data/lib/sequel/core.rb +4 -67
  65. data/lib/sequel/database.rb +1 -0
  66. data/lib/sequel/database/connecting.rb +2 -8
  67. data/lib/sequel/database/dataset.rb +2 -7
  68. data/lib/sequel/database/dataset_defaults.rb +0 -18
  69. data/lib/sequel/database/features.rb +4 -4
  70. data/lib/sequel/database/misc.rb +6 -8
  71. data/lib/sequel/database/query.rb +5 -61
  72. data/lib/sequel/database/schema_generator.rb +22 -20
  73. data/lib/sequel/database/schema_methods.rb +48 -20
  74. data/lib/sequel/database/transactions.rb +7 -17
  75. data/lib/sequel/dataset.rb +2 -0
  76. data/lib/sequel/dataset/actions.rb +23 -91
  77. data/lib/sequel/dataset/features.rb +1 -4
  78. data/lib/sequel/dataset/graph.rb +3 -47
  79. data/lib/sequel/dataset/misc.rb +4 -33
  80. data/lib/sequel/dataset/prepared_statements.rb +3 -1
  81. data/lib/sequel/dataset/query.rb +116 -240
  82. data/lib/sequel/dataset/sql.rb +19 -97
  83. data/lib/sequel/deprecated.rb +0 -16
  84. data/lib/sequel/exceptions.rb +0 -3
  85. data/lib/sequel/extensions/_pretty_table.rb +1 -1
  86. data/lib/sequel/extensions/columns_introspection.rb +1 -12
  87. data/lib/sequel/extensions/constraint_validations.rb +3 -3
  88. data/lib/sequel/extensions/core_extensions.rb +0 -9
  89. data/lib/sequel/extensions/date_arithmetic.rb +1 -2
  90. data/lib/sequel/extensions/graph_each.rb +11 -0
  91. data/lib/sequel/extensions/migration.rb +5 -5
  92. data/lib/sequel/extensions/null_dataset.rb +11 -13
  93. data/lib/sequel/extensions/pagination.rb +3 -6
  94. data/lib/sequel/extensions/pg_array.rb +6 -4
  95. data/lib/sequel/extensions/pg_array_ops.rb +35 -1
  96. data/lib/sequel/extensions/pg_json.rb +12 -2
  97. data/lib/sequel/extensions/pg_json_ops.rb +266 -0
  98. data/lib/sequel/extensions/pg_range.rb +2 -2
  99. data/lib/sequel/extensions/pg_range_ops.rb +0 -8
  100. data/lib/sequel/extensions/pg_row.rb +2 -2
  101. data/lib/sequel/extensions/pretty_table.rb +0 -4
  102. data/lib/sequel/extensions/query.rb +3 -8
  103. data/lib/sequel/extensions/schema_caching.rb +0 -7
  104. data/lib/sequel/extensions/schema_dumper.rb +10 -17
  105. data/lib/sequel/extensions/select_remove.rb +0 -4
  106. data/lib/sequel/extensions/set_overrides.rb +28 -0
  107. data/lib/sequel/extensions/to_dot.rb +6 -10
  108. data/lib/sequel/model.rb +6 -7
  109. data/lib/sequel/model/associations.rb +127 -182
  110. data/lib/sequel/model/base.rb +88 -211
  111. data/lib/sequel/model/errors.rb +0 -13
  112. data/lib/sequel/model/plugins.rb +2 -2
  113. data/lib/sequel/no_core_ext.rb +0 -1
  114. data/lib/sequel/plugins/after_initialize.rb +11 -17
  115. data/lib/sequel/plugins/association_autoreloading.rb +1 -47
  116. data/lib/sequel/plugins/association_dependencies.rb +2 -2
  117. data/lib/sequel/plugins/auto_validations.rb +2 -8
  118. data/lib/sequel/plugins/blacklist_security.rb +32 -2
  119. data/lib/sequel/plugins/caching.rb +1 -1
  120. data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
  121. data/lib/sequel/plugins/composition.rb +10 -8
  122. data/lib/sequel/plugins/constraint_validations.rb +2 -2
  123. data/lib/sequel/plugins/dataset_associations.rb +4 -0
  124. data/lib/sequel/plugins/defaults_setter.rb +8 -6
  125. data/lib/sequel/plugins/dirty.rb +6 -6
  126. data/lib/sequel/plugins/force_encoding.rb +13 -8
  127. data/lib/sequel/plugins/hook_class_methods.rb +1 -7
  128. data/lib/sequel/plugins/json_serializer.rb +13 -74
  129. data/lib/sequel/plugins/lazy_attributes.rb +2 -4
  130. data/lib/sequel/plugins/list.rb +1 -1
  131. data/lib/sequel/plugins/many_through_many.rb +4 -11
  132. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +1 -49
  133. data/lib/sequel/plugins/nested_attributes.rb +1 -1
  134. data/lib/sequel/plugins/optimistic_locking.rb +3 -5
  135. data/lib/sequel/plugins/pg_array_associations.rb +453 -0
  136. data/lib/sequel/plugins/pg_typecast_on_load.rb +23 -7
  137. data/lib/sequel/plugins/prepared_statements.rb +1 -1
  138. data/lib/sequel/plugins/prepared_statements_associations.rb +20 -14
  139. data/lib/sequel/plugins/prepared_statements_safe.rb +2 -2
  140. data/lib/sequel/plugins/rcte_tree.rb +1 -1
  141. data/lib/sequel/plugins/serialization.rb +5 -4
  142. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  143. data/lib/sequel/plugins/sharding.rb +7 -1
  144. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  145. data/lib/sequel/plugins/timestamps.rb +1 -1
  146. data/lib/sequel/plugins/touch.rb +2 -2
  147. data/lib/sequel/plugins/tree.rb +1 -1
  148. data/lib/sequel/plugins/typecast_on_load.rb +19 -4
  149. data/lib/sequel/plugins/validation_class_methods.rb +0 -30
  150. data/lib/sequel/plugins/validation_helpers.rb +13 -31
  151. data/lib/sequel/plugins/xml_serializer.rb +18 -57
  152. data/lib/sequel/sql.rb +20 -22
  153. data/lib/sequel/version.rb +2 -2
  154. data/spec/adapters/db2_spec.rb +14 -23
  155. data/spec/adapters/firebird_spec.rb +25 -29
  156. data/spec/adapters/informix_spec.rb +11 -14
  157. data/spec/adapters/mssql_spec.rb +71 -77
  158. data/spec/adapters/mysql_spec.rb +165 -172
  159. data/spec/adapters/oracle_spec.rb +36 -39
  160. data/spec/adapters/postgres_spec.rb +175 -100
  161. data/spec/adapters/spec_helper.rb +13 -11
  162. data/spec/adapters/sqlite_spec.rb +36 -44
  163. data/spec/core/connection_pool_spec.rb +2 -1
  164. data/spec/core/database_spec.rb +55 -55
  165. data/spec/core/dataset_spec.rb +45 -249
  166. data/spec/core/deprecated_spec.rb +0 -8
  167. data/spec/core/expression_filters_spec.rb +23 -5
  168. data/spec/core/object_graph_spec.rb +4 -66
  169. data/spec/core/schema_spec.rb +35 -12
  170. data/spec/core/spec_helper.rb +3 -2
  171. data/spec/core_extensions_spec.rb +17 -19
  172. data/spec/extensions/arbitrary_servers_spec.rb +2 -3
  173. data/spec/extensions/association_dependencies_spec.rb +14 -14
  174. data/spec/extensions/auto_validations_spec.rb +7 -0
  175. data/spec/extensions/blacklist_security_spec.rb +5 -5
  176. data/spec/extensions/blank_spec.rb +2 -0
  177. data/spec/extensions/class_table_inheritance_spec.rb +2 -2
  178. data/spec/extensions/columns_introspection_spec.rb +2 -29
  179. data/spec/extensions/composition_spec.rb +10 -17
  180. data/spec/extensions/core_refinements_spec.rb +5 -1
  181. data/spec/extensions/dataset_associations_spec.rb +18 -0
  182. data/spec/extensions/date_arithmetic_spec.rb +2 -2
  183. data/spec/extensions/defaults_setter_spec.rb +9 -9
  184. data/spec/extensions/dirty_spec.rb +0 -5
  185. data/spec/extensions/eval_inspect_spec.rb +2 -0
  186. data/spec/extensions/force_encoding_spec.rb +2 -18
  187. data/spec/extensions/hash_aliases_spec.rb +8 -0
  188. data/spec/extensions/hook_class_methods_spec.rb +39 -58
  189. data/spec/extensions/inflector_spec.rb +2 -0
  190. data/spec/extensions/instance_filters_spec.rb +8 -8
  191. data/spec/extensions/json_serializer_spec.rb +1 -41
  192. data/spec/extensions/list_spec.rb +1 -1
  193. data/spec/extensions/many_through_many_spec.rb +106 -109
  194. data/spec/extensions/migration_spec.rb +2 -0
  195. data/spec/extensions/named_timezones_spec.rb +1 -0
  196. data/spec/extensions/pg_array_associations_spec.rb +603 -0
  197. data/spec/extensions/pg_array_ops_spec.rb +25 -0
  198. data/spec/extensions/pg_array_spec.rb +9 -1
  199. data/spec/extensions/pg_hstore_ops_spec.rb +13 -0
  200. data/spec/extensions/pg_hstore_spec.rb +1 -0
  201. data/spec/extensions/pg_json_ops_spec.rb +131 -0
  202. data/spec/extensions/pg_json_spec.rb +10 -4
  203. data/spec/extensions/pg_range_ops_spec.rb +2 -5
  204. data/spec/extensions/pg_range_spec.rb +6 -2
  205. data/spec/extensions/pg_row_ops_spec.rb +2 -0
  206. data/spec/extensions/prepared_statements_associations_spec.rb +26 -5
  207. data/spec/extensions/rcte_tree_spec.rb +15 -15
  208. data/spec/extensions/schema_dumper_spec.rb +0 -1
  209. data/spec/extensions/schema_spec.rb +9 -9
  210. data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
  211. data/spec/extensions/serialization_spec.rb +18 -29
  212. data/spec/extensions/set_overrides_spec.rb +4 -0
  213. data/spec/extensions/{many_to_one_pk_lookup_spec.rb → shared_caching_spec.rb} +1 -4
  214. data/spec/extensions/single_table_inheritance_spec.rb +4 -4
  215. data/spec/extensions/spec_helper.rb +8 -9
  216. data/spec/extensions/sql_expr_spec.rb +2 -0
  217. data/spec/extensions/string_date_time_spec.rb +2 -0
  218. data/spec/extensions/string_stripper_spec.rb +2 -0
  219. data/spec/extensions/tactical_eager_loading_spec.rb +12 -12
  220. data/spec/extensions/thread_local_timezones_spec.rb +2 -0
  221. data/spec/extensions/timestamps_spec.rb +1 -1
  222. data/spec/extensions/to_dot_spec.rb +1 -1
  223. data/spec/extensions/touch_spec.rb +24 -24
  224. data/spec/extensions/tree_spec.rb +7 -7
  225. data/spec/extensions/typecast_on_load_spec.rb +8 -1
  226. data/spec/extensions/update_primary_key_spec.rb +10 -10
  227. data/spec/extensions/validation_class_methods_spec.rb +10 -39
  228. data/spec/extensions/validation_helpers_spec.rb +29 -47
  229. data/spec/extensions/xml_serializer_spec.rb +1 -23
  230. data/spec/integration/associations_test.rb +231 -40
  231. data/spec/integration/database_test.rb +1 -1
  232. data/spec/integration/dataset_test.rb +64 -64
  233. data/spec/integration/eager_loader_test.rb +28 -28
  234. data/spec/integration/migrator_test.rb +1 -1
  235. data/spec/integration/model_test.rb +2 -2
  236. data/spec/integration/plugin_test.rb +21 -21
  237. data/spec/integration/prepared_statement_test.rb +7 -7
  238. data/spec/integration/schema_test.rb +115 -110
  239. data/spec/integration/spec_helper.rb +17 -27
  240. data/spec/integration/timezone_test.rb +1 -1
  241. data/spec/integration/transaction_test.rb +10 -10
  242. data/spec/integration/type_test.rb +2 -2
  243. data/spec/model/association_reflection_spec.rb +2 -28
  244. data/spec/model/associations_spec.rb +239 -188
  245. data/spec/model/base_spec.rb +27 -68
  246. data/spec/model/dataset_methods_spec.rb +4 -4
  247. data/spec/model/eager_loading_spec.rb +160 -172
  248. data/spec/model/hooks_spec.rb +62 -79
  249. data/spec/model/model_spec.rb +36 -51
  250. data/spec/model/plugins_spec.rb +5 -19
  251. data/spec/model/record_spec.rb +125 -151
  252. data/spec/model/spec_helper.rb +8 -6
  253. data/spec/model/validations_spec.rb +4 -17
  254. data/spec/spec_config.rb +2 -10
  255. metadata +50 -56
  256. data/lib/sequel/deprecated_core_extensions.rb +0 -135
  257. data/lib/sequel/extensions/pg_auto_parameterize.rb +0 -185
  258. data/lib/sequel/extensions/pg_statement_cache.rb +0 -318
  259. data/lib/sequel/plugins/identity_map.rb +0 -260
  260. data/lib/sequel_core.rb +0 -2
  261. data/lib/sequel_model.rb +0 -2
  262. data/spec/extensions/association_autoreloading_spec.rb +0 -102
  263. data/spec/extensions/identity_map_spec.rb +0 -337
  264. data/spec/extensions/pg_auto_parameterize_spec.rb +0 -70
  265. data/spec/extensions/pg_statement_cache_spec.rb +0 -208
  266. data/spec/rcov.opts +0 -8
  267. data/spec/spec_config.rb.example +0 -10
@@ -5,19 +5,6 @@ module Sequel
5
5
  class Errors < ::Hash
6
6
  ATTRIBUTE_JOINER = ' and '.freeze
7
7
 
8
- # Assign an array of messages for each attribute on access.
9
- # Using this message is discouraged in new code, use +add+
10
- # to add new error messages, and +on+ to check existing
11
- # error messages.
12
- def [](k)
13
- if has_key?(k)
14
- super
15
- else
16
- Sequel::Deprecation.deprecate('Model::Errors#[] autovivification', 'Please switch to Model::Errors#add to add errors, and Model::Errors#on to get errors')
17
- self[k] = []
18
- end
19
- end
20
-
21
8
  # Adds an error for the given attribute.
22
9
  #
23
10
  # errors.add(:name, 'is not valid') if name == 'invalid'
@@ -9,10 +9,10 @@ module Sequel
9
9
  # already loaded by an ancestor class), before including/extending
10
10
  # any modules, with the arguments
11
11
  # and block provided to the call to Model.plugin.
12
- # * A module inside the plugin module named InstanceMethods,
13
- # which will be included in the model class.
14
12
  # * A module inside the plugin module named ClassMethods,
15
13
  # which will extend the model class.
14
+ # * A module inside the plugin module named InstanceMethods,
15
+ # which will be included in the model class.
16
16
  # * A module inside the plugin module named DatasetMethods,
17
17
  # which will extend the model's dataset.
18
18
  # * A singleton method named configure, which takes a model,
@@ -1,2 +1 @@
1
- ::SEQUEL_NO_CORE_EXTENSIONS = true unless defined?(::SEQUEL_NO_CORE_EXTENSIONS)
2
1
  require 'sequel'
@@ -13,30 +13,24 @@ module Sequel
13
13
  module AfterInitialize
14
14
  module ClassMethods
15
15
  # Call after_initialize for model objects loaded from the database.
16
- #def call
17
- # v = super
18
- # v.after_initialize
19
- # v
20
- #end
21
-
22
- private
23
-
24
- # REMOVE40
25
- def check_deprecated_after_initialize(meths)
16
+ def call(h={})
17
+ v = super
18
+ v.after_initialize
19
+ v
26
20
  end
27
21
  end
28
22
 
29
23
  module InstanceMethods
30
24
  # Call after_initialize for new model objects.
31
- #def initialize(h={})
32
- # super
33
- # after_initialize
34
- #end
35
-
25
+ def initialize(h={})
26
+ super
27
+ after_initialize
28
+ end
29
+
36
30
  # An empty after_initialize hook, so that plugins that use this
37
31
  # can always call super to get the default behavior.
38
- #def after_initialize
39
- #end
32
+ def after_initialize
33
+ end
40
34
  end
41
35
  end
42
36
  end
@@ -1,53 +1,7 @@
1
1
  module Sequel
2
2
  module Plugins
3
- # The AssociationAutoreloading plugin makes many_to_one association
4
- # accessor methods automatically reload the cached object whenever
5
- # the association's foreign key is modified:
6
- #
7
- # Album.many_to_one :artists
8
- # album = Album.first
9
- # album.artist_id #=> 1
10
- # album.artist # caches associated artist
11
- # album.artist_id = 2
12
- # album.artist # reloads associated artist
13
- #
3
+ # Empty plugin module for backwards compatibility
14
4
  module AssociationAutoreloading
15
- def self.apply(model)
16
- model.instance_variable_set(:@autoreloading_associations, {})
17
- end
18
-
19
- module ClassMethods
20
- # Hash with column symbol keys and arrays of many_to_one
21
- # association symbols that should be cleared when the column
22
- # value changes.
23
- attr_reader :autoreloading_associations
24
-
25
- Plugins.inherited_instance_variables(self, :@autoreloading_associations=>:hash_dup)
26
-
27
- private
28
-
29
- # Add the association to the array of associations to clear for
30
- # each of the foreign key columns.
31
- def def_many_to_one(opts)
32
- super
33
- opts[:keys].each do |key|
34
- (@autoreloading_associations[key] ||= []) << opts[:name]
35
- end
36
- end
37
- end
38
-
39
- module InstanceMethods
40
- private
41
-
42
- # If a foreign key column value changes, clear the related
43
- # cached associations.
44
- def change_column_value(column, value)
45
- if assocs = model.autoreloading_associations[column]
46
- assocs.each{|a| associations.delete(a)}
47
- end
48
- super
49
- end
50
- end
51
5
  end
52
6
  end
53
7
  end
@@ -29,12 +29,12 @@ module Sequel
29
29
  DEPENDENCE_ACTIONS = [:delete, :destroy, :nullify]
30
30
 
31
31
  # Initialize the association_dependencies hash for this model.
32
- def self.apply(model, hash={})
32
+ def self.apply(model, hash=OPTS)
33
33
  model.instance_eval{@association_dependencies = {:before_delete=>[], :before_destroy=>[], :before_nullify=>[], :after_delete=>[], :after_destroy=>[]}}
34
34
  end
35
35
 
36
36
  # Call add_association_dependencies with any dependencies given in the plugin call.
37
- def self.configure(model, hash={})
37
+ def self.configure(model, hash=OPTS)
38
38
  model.add_association_dependencies(hash) unless hash.empty?
39
39
  end
40
40
 
@@ -43,7 +43,7 @@ module Sequel
43
43
  # # Make the Album class use auto validations
44
44
  # Album.plugin :auto_validations
45
45
  module AutoValidations
46
- def self.apply(model, opts={})
46
+ def self.apply(model, opts=OPTS)
47
47
  model.instance_eval do
48
48
  plugin :validation_helpers
49
49
  @auto_validate_presence = false
@@ -55,7 +55,7 @@ module Sequel
55
55
  end
56
56
 
57
57
  # Setup auto validations for the model if it has a dataset.
58
- def self.configure(model, opts={})
58
+ def self.configure(model, opts=OPTS)
59
59
  model.instance_eval do
60
60
  setup_auto_validations if @dataset
61
61
  if opts[:not_null] == :presence
@@ -77,12 +77,6 @@ module Sequel
77
77
  Plugins.inherited_instance_variables(self, :@auto_validate_presence=>nil, :@auto_validate_types=>nil, :@auto_validate_not_null_columns=>:dup, :@auto_validate_explicit_not_null_columns=>:dup, :@auto_validate_unique_columns=>:dup)
78
78
  Plugins.after_set_dataset(self, :setup_auto_validations)
79
79
 
80
- # REMOVE40
81
- def auto_validate_presence_columns
82
- Sequel::Deprecation.deprecate('Model.auto_validate_presence_columns', 'Please switch to auto_validate_not_null_columns')
83
- auto_validate_not_null_columns
84
- end
85
-
86
80
  # Whether to use a presence validation for not null columns
87
81
  def auto_validate_presence?
88
82
  @auto_validate_presence
@@ -36,9 +36,25 @@ module Sequel
36
36
  clear_setter_methods_cache
37
37
  @restricted_columns = cols
38
38
  end
39
+
40
+ private
41
+
42
+ # If allowed_columns is not set but restricted_columns is, remove the
43
+ # restricted_columns.
44
+ def get_setter_methods
45
+ meths = super
46
+ if !allowed_columns && restricted_columns
47
+ meths -= restricted_columns.map{|x| "#{x}="}
48
+ end
49
+ meths
50
+ end
39
51
  end
40
52
 
41
53
  module InstanceMethods
54
+ # Special array subclass used for marking methods to be removed.
55
+ class ExceptionList < Array
56
+ end
57
+
42
58
  # Set all values using the entries in the hash, except for the keys
43
59
  # given in except. You should probably use +set_fields+ or +set_only+
44
60
  # instead of this method, as blacklist approaches to security are a bad idea.
@@ -46,7 +62,7 @@ module Sequel
46
62
  # artist.set_except({:name=>'Jim'}, :hometown)
47
63
  # artist.name # => 'Jim'
48
64
  def set_except(hash, *except)
49
- set_restricted(hash, false, except.flatten)
65
+ set_restricted(hash, ExceptionList.new(except.flatten))
50
66
  end
51
67
 
52
68
  # Update all values using the entries in the hash, except for the keys
@@ -55,7 +71,21 @@ module Sequel
55
71
  #
56
72
  # artist.update_except({:name=>'Jim'}, :hometown) # UPDATE artists SET name = 'Jim' WHERE (id = 1)
57
73
  def update_except(hash, *except)
58
- update_restricted(hash, false, except.flatten)
74
+ update_restricted(hash, ExceptionList.new(except.flatten))
75
+ end
76
+
77
+ private
78
+
79
+ # If set_except or update_except was used, remove the related methods from the list.
80
+ def setter_methods(type)
81
+ if type.is_a?(ExceptionList)
82
+ meths = super(:all)
83
+ meths -= Array(primary_key).map{|x| "#{x}="} if primary_key && model.restrict_primary_key?
84
+ meths -= type.map{|x| "#{x}="}
85
+ meths
86
+ else
87
+ super
88
+ end
59
89
  end
60
90
  end
61
91
  end
@@ -34,7 +34,7 @@ module Sequel
34
34
  module Caching
35
35
  # Set the cache_store and cache_ttl attributes for the given model.
36
36
  # If the :ttl option is not given, 3600 seconds is the default.
37
- def self.configure(model, store, opts={})
37
+ def self.configure(model, store, opts=OPTS)
38
38
  model.instance_eval do
39
39
  @cache_store = store
40
40
  @cache_ttl = opts[:ttl] || 3600
@@ -68,7 +68,7 @@ module Sequel
68
68
  # The class_table_inheritance plugin requires the lazy_attributes plugin
69
69
  # to handle lazily-loaded attributes for subclass instances returned
70
70
  # by superclass methods.
71
- def self.apply(model, opts={})
71
+ def self.apply(model, opts=OPTS)
72
72
  model.plugin :lazy_attributes
73
73
  end
74
74
 
@@ -81,7 +81,7 @@ module Sequel
81
81
  # * :table_map - Hash with class name symbol keys and table name symbol
82
82
  # values. Necessary if the implicit table name for the model class
83
83
  # does not match the database table name
84
- def self.configure(model, opts={})
84
+ def self.configure(model, opts=OPTS)
85
85
  model.instance_eval do
86
86
  m = method(:constantize)
87
87
  @cti_base_model = self
@@ -90,7 +90,7 @@ module Sequel
90
90
  # # for example y in the composition object represents year
91
91
  # # in the model object.
92
92
  # :mapping=>[[:year, :y], [:month, :m], [:day, :d]]
93
- def composition(name, opts={})
93
+ def composition(name, opts=OPTS)
94
94
  opts = opts.dup
95
95
  compositions[name] = opts
96
96
  if mapping = opts[:mapping]
@@ -127,7 +127,7 @@ module Sequel
127
127
  Plugins.inherited_instance_variables(self, :@compositions=>:dup)
128
128
 
129
129
  # Define getter and setter methods for the composition object.
130
- def define_composition_accessor(name, opts={})
130
+ def define_composition_accessor(name, opts=OPTS)
131
131
  include(@composition_module ||= Module.new) unless composition_module
132
132
  composer = opts[:composer]
133
133
  composition_module.class_eval do
@@ -149,12 +149,6 @@ module Sequel
149
149
  end
150
150
 
151
151
  module InstanceMethods
152
- # Clear the cached compositions when setting values.
153
- def set_values(hash)
154
- @compositions.clear if @compositions
155
- super
156
- end
157
-
158
152
  # For each composition, set the columns in the model class based
159
153
  # on the composition object.
160
154
  def before_save
@@ -172,6 +166,14 @@ module Sequel
172
166
  compositions.freeze
173
167
  super
174
168
  end
169
+
170
+ private
171
+
172
+ # Clear the cached compositions when manually refreshing.
173
+ def _refresh_set_values(hash)
174
+ @compositions.clear if @compositions
175
+ super
176
+ end
175
177
  end
176
178
  end
177
179
  end
@@ -32,7 +32,7 @@ module Sequel
32
32
  DEFAULT_CONSTRAINT_VALIDATIONS_TABLE = :sequel_constraint_validations
33
33
 
34
34
  # Automatically load the validation_helpers plugin to run the actual validations.
35
- def self.apply(model, opts={})
35
+ def self.apply(model, opts=OPTS)
36
36
  model.instance_eval do
37
37
  plugin :validation_helpers
38
38
  @constraint_validations_table = DEFAULT_CONSTRAINT_VALIDATIONS_TABLE
@@ -49,7 +49,7 @@ module Sequel
49
49
  # given options. Keys should be validation type symbols (e.g.
50
50
  # :presence) and values should be hashes of options specific
51
51
  # to that validation type.
52
- def self.configure(model, opts={})
52
+ def self.configure(model, opts=OPTS)
53
53
  model.instance_eval do
54
54
  if table = opts[:constraint_validations_table]
55
55
  @constraint_validations_table = table
@@ -89,6 +89,10 @@ module Sequel
89
89
  join(fe[:table], Array(fe[:right]).zip(Array(fe[:left])), :implicit_qualifier=>model.table_name)
90
90
  edges.each{|e| sds = sds.join(e[:table], Array(e[:right]).zip(Array(e[:left])))}
91
91
  ds.filter(r.qualified_right_primary_key=>sds)
92
+ when :pg_array_to_many
93
+ ds.filter(Sequel.expr(r.primary_key=>sds.select{Sequel.pg_array_op(r.qualify(r[:model].table_name, r[:key])).unnest}))
94
+ when :many_to_pg_array
95
+ ds.filter(Sequel.function(:coalesce, Sequel.pg_array_op(r[:key]).overlaps(sds.select{array_agg(r.qualify(r[:model].table_name, r.primary_key))}), false))
92
96
  else
93
97
  raise Error, "unrecognized association type for association #{name.inspect}: #{r[:type].inspect}"
94
98
  end
@@ -54,12 +54,14 @@ module Sequel
54
54
  end
55
55
 
56
56
  module InstanceMethods
57
- private
58
-
59
- # Set default values if they are not already set by the hash provided to initialize.
60
- def initialize_set(h)
61
- super
62
- model.default_values.each{|k,v| self[k] = (v.respond_to?(:call) ? v.call : v) unless values.has_key?(k)}
57
+ # Use default value for a new record if values doesn't already contain an entry for it.
58
+ def [](k)
59
+ if new? && !values.has_key?(k)
60
+ v = model.default_values[k]
61
+ v.respond_to?(:call) ? v.call : v
62
+ else
63
+ super
64
+ end
63
65
  end
64
66
  end
65
67
  end
@@ -123,12 +123,6 @@ module Sequel
123
123
  end
124
124
  end
125
125
 
126
- # Reset the initial values when setting values.
127
- def set_values(hash)
128
- reset_initial_values
129
- super
130
- end
131
-
132
126
  # Manually specify that a column will change. This should only be used
133
127
  # if you plan to modify a column value in place, which is not recommended.
134
128
  #
@@ -158,6 +152,12 @@ module Sequel
158
152
 
159
153
  private
160
154
 
155
+ # Reset the initial values when setting values.
156
+ def _refresh_set_values(hash)
157
+ reset_initial_values
158
+ super
159
+ end
160
+
161
161
  # Reset the initial values after saving.
162
162
  def after_save
163
163
  super
@@ -33,21 +33,26 @@ module Sequel
33
33
  attr_accessor :forced_encoding
34
34
 
35
35
  Plugins.inherited_instance_variables(self, :@forced_encoding=>nil)
36
+
37
+ def call(values)
38
+ o = super
39
+ o.send(:force_hash_encoding, o.values)
40
+ o
41
+ end
36
42
  end
37
43
 
38
44
  module InstanceMethods
39
- # Allow the force encoding plugin to work with the identity_map
40
- # plugin by typecasting new values.
41
- def merge_db_update(row)
42
- super(force_hash_encoding(row))
43
- end
45
+ private
44
46
 
45
47
  # Force the encoding of all string values when setting the instance's values.
46
- def set_values(row)
47
- super(force_hash_encoding(row))
48
+ def _refresh_set_values(values)
49
+ super(force_hash_encoding(values))
48
50
  end
49
51
 
50
- private
52
+ # Force the encoding of all string values when setting the instance's values.
53
+ def _save_set_values(values)
54
+ super(force_hash_encoding(values))
55
+ end
51
56
 
52
57
  # Force the encoding for all string values in the given row hash.
53
58
  def force_hash_encoding(row)
@@ -39,13 +39,7 @@ module Sequel
39
39
  end
40
40
 
41
41
  module ClassMethods
42
- (Model::HOOKS - [:after_initialize]).each{|h| class_eval("def #{h}(method = nil, &block); add_hook(:#{h}, method, &block) end", __FILE__, __LINE__)}
43
-
44
- # REMOVE40
45
- def after_initialize(method = nil, &block)
46
- Sequel::Deprecation.deprecate('The Model after_initialize hook', 'The hook_class_methods plugin will no longer support the hook. Please use the after_initialize plugin and define the after_initialize hook directly')
47
- add_hook(:after_initialize, method, &block)
48
- end
42
+ Model::HOOKS.each{|h| class_eval("def #{h}(method = nil, &block); add_hook(:#{h}, method, &block) end", __FILE__, __LINE__)}
49
43
 
50
44
  # This adds a new hook type. It will define both a class
51
45
  # method that you can use to add hooks, as well as an instance method
@@ -82,9 +82,6 @@ module Sequel
82
82
  #
83
83
  # album.from_json(json, :associations=>{:artist=>{:fields=>%w'id name', :associations=>:tags}})
84
84
  #
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.
87
- #
88
85
  # Note that active_support/json makes incompatible changes to the to_json API,
89
86
  # and breaks some aspects of the json_serializer plugin. You can undo the damage
90
87
  # done by active_support/json by doing:
@@ -142,10 +139,7 @@ module Sequel
142
139
 
143
140
  # Attempt to parse a single instance from the given JSON string,
144
141
  # with options passed to InstanceMethods#from_json_node.
145
- def from_json(json, opts={})
146
- if opts[:all_associations] || opts[:all_columns]
147
- Sequel::Deprecation.deprecate("The from_json :all_associations and :all_columns", 'You need to explicitly specify the associations and columns via the :associations and :fields options')
148
- end
142
+ def from_json(json, opts=OPTS)
149
143
  v = Sequel.parse_json(json)
150
144
  case v
151
145
  when self
@@ -159,10 +153,7 @@ module Sequel
159
153
 
160
154
  # Attempt to parse an array of instances from the given JSON string,
161
155
  # with options passed to InstanceMethods#from_json_node.
162
- def array_from_json(json, opts={})
163
- if opts[:all_associations] || opts[:all_columns]
164
- Sequel::Deprecation.deprecate("The from_json :all_associations and :all_columns", 'You need to explicitly specify the associations and columns via the :associations and :fields options')
165
- end
156
+ def array_from_json(json, opts=OPTS)
166
157
  v = Sequel.parse_json(json)
167
158
  if v.is_a?(Array)
168
159
  raise(Error, 'parsed json returned an array containing non-hashes') unless v.all?{|ve| ve.is_a?(Hash) || ve.is_a?(self)}
@@ -172,16 +163,6 @@ module Sequel
172
163
  end
173
164
  end
174
165
 
175
- # Exists for compatibility with old json library which allows creation
176
- # of arbitrary ruby objects by JSON.parse. Creates a new instance
177
- # and populates it using InstanceMethods#from_json_node with the
178
- # :all_columns and :all_associations options. Not recommended for usage
179
- # in new code, consider calling the from_json method directly with the JSON string.
180
- def json_create(hash, opts={})
181
- Sequel::Deprecation.deprecate("Model.json_create", 'Switch to Model.from_json')
182
- new.from_json_node(hash, {:all_columns=>true, :all_associations=>true}.merge(opts))
183
- end
184
-
185
166
  Plugins.inherited_instance_variables(self, :@json_serializer_opts=>lambda do |json_serializer_opts|
186
167
  opts = {}
187
168
  json_serializer_opts.each{|k, v| opts[k] = (v.is_a?(Array) || v.is_a?(Hash)) ? v.dup : v}
@@ -194,10 +175,7 @@ module Sequel
194
175
  module InstanceMethods
195
176
  # Parse the provided JSON, which should return a hash,
196
177
  # and process the hash with from_json_node.
197
- def from_json(json, opts={})
198
- if opts[:all_associations] || opts[:all_columns]
199
- Sequel::Deprecation.deprecate("The from_json :all_associations and :all_columns", 'You need to explicitly specify the associations and columns via the :associations and :fields options')
200
- end
178
+ def from_json(json, opts=OPTS)
201
179
  from_json_node(Sequel.parse_json(json), opts)
202
180
  end
203
181
 
@@ -205,38 +183,19 @@ module Sequel
205
183
  # calls set with the hash values.
206
184
  #
207
185
  # Options:
208
- # :all_associations :: Indicates that all associations supported by the model should be tried.
209
- # This option also cascades to associations if used. It is better to use the
210
- # :associations option instead of this option. This option only exists for
211
- # backwards compatibility.
212
- # :all_columns :: Overrides the setting logic allowing all setter methods be used,
213
- # even if access to the setter method is restricted.
214
- # This option cascades to associations if used, and can be reset in those associations
215
- # using the :all_columns=>false or :fields options. This option is considered a
216
- # security risk, and only exists for backwards compatibility. It is better to use
217
- # the :fields option appropriately instead of this option, or no option at all.
218
186
  # :associations :: Indicates that the associations cache should be updated by creating
219
187
  # a new associated object using data from the hash. Should be a Symbol
220
188
  # for a single association, an array of symbols for multiple associations,
221
189
  # or a hash with symbol keys and dependent association option hash values.
222
190
  # :fields :: Changes the behavior to call set_fields using the provided fields, instead of calling set.
223
- def from_json_node(hash, opts={})
191
+ def from_json_node(hash, opts=OPTS)
224
192
  unless hash.is_a?(Hash)
225
193
  raise Error, "parsed json doesn't return a hash"
226
194
  end
227
- if hash.has_key?(JSON.create_id)
228
- Sequel::Deprecation.deprecate('Attempting to use Model#from_json with a hash value that includes JSON.create_id is deprecated. Starting in Sequel 4.0, the create_id will not be removed automatically.')
229
- hash.delete(JSON.create_id)
230
- end
231
195
 
232
- unless assocs = opts[:associations]
233
- if opts[:all_associations]
234
- assocs = {}
235
- model.associations.each{|v| assocs[v] = {:all_associations=>true}}
236
- end
237
- end
196
+ populate_associations = {}
238
197
 
239
- if assocs
198
+ if assocs = opts[:associations]
240
199
  assocs = case assocs
241
200
  when Symbol
242
201
  {assocs=>{}}
@@ -250,19 +209,13 @@ module Sequel
250
209
  raise Error, ":associations should be Symbol, Array, or Hash if present"
251
210
  end
252
211
 
253
- if opts[:all_columns]
254
- assocs.each_value do |assoc_opts|
255
- assoc_opts[:all_columns] = true unless assoc_opts.has_key?(:fields) || assoc_opts.has_key?(:all_columns)
256
- end
257
- end
258
-
259
212
  assocs.each do |assoc, assoc_opts|
260
213
  if assoc_values = hash.delete(assoc.to_s)
261
214
  unless r = model.association_reflection(assoc)
262
215
  raise Error, "Association #{assoc} is not defined for #{model}"
263
216
  end
264
217
 
265
- associations[assoc] = if r.returns_array?
218
+ populate_associations[assoc] = if r.returns_array?
266
219
  raise Error, "Attempt to populate array association with a non-array" unless assoc_values.is_a?(Array)
267
220
  assoc_values.map{|v| v.is_a?(r.associated_class) ? v : r.associated_class.new.from_json_node(v, assoc_opts)}
268
221
  else
@@ -275,19 +228,14 @@ module Sequel
275
228
 
276
229
  if fields = opts[:fields]
277
230
  set_fields(hash, fields, opts)
278
- elsif opts[:all_columns]
279
- meths = methods.collect{|x| x.to_s}.grep(Model::SETTER_METHOD_REGEXP) - Model::RESTRICTED_SETTER_METHODS
280
- hash.each do |k, v|
281
- if meths.include?(setter_meth = "#{k}=")
282
- send(setter_meth, v)
283
- else
284
- raise Error, "Entry in JSON does not have a matching setter method: #{k}"
285
- end
286
- end
287
231
  else
288
232
  set(hash)
289
233
  end
290
234
 
235
+ populate_associations.each do |assoc, values|
236
+ associations[assoc] = values
237
+ end
238
+
291
239
  self
292
240
  end
293
241
 
@@ -306,7 +254,6 @@ module Sequel
306
254
  # include in the JSON output, ignoring all other
307
255
  # columns.
308
256
  # :root :: Qualify the JSON with the name of the object.
309
- # Implies :naked since the object name is explicit.
310
257
  def to_json(*a)
311
258
  if opts = a.first.is_a?(Hash)
312
259
  opts = model.json_serializer_opts.merge(a.first)
@@ -322,10 +269,6 @@ module Sequel
322
269
  end
323
270
 
324
271
  h = {}
325
- if JSON.create_id && !opts[:naked] && !opts[:root]
326
- Sequel::Deprecation.deprecate('The :naked and :root options have not been used, so adding JSON.create_id to the to_json output. This is deprecated, starting in Sequel 4, the JSON.create_id will never be added.')
327
- h[JSON.create_id] = model.name
328
- end
329
272
 
330
273
  cols.each{|c| h[c.to_s] = send(c)}
331
274
  if inc = opts[:include]
@@ -377,15 +320,11 @@ module Sequel
377
320
  collection_root = case opts[:root]
378
321
  when nil, false, :instance
379
322
  false
380
- when :collection
381
- opts = opts.dup
382
- opts.delete(:root)
383
- opts[:naked] = true unless opts.has_key?(:naked)
384
- true
385
323
  when :both
386
324
  true
387
325
  else
388
- Sequel::Deprecation.deprecate('The to_json :root=>true option will mean :root=>:collection starting in Sequel 4. Use :root=>:both if you want to wrap both the collection and each item in a wrapper.')
326
+ opts = opts.dup
327
+ opts.delete(:root)
389
328
  true
390
329
  end
391
330