sequel 3.48.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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