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
@@ -7,7 +7,7 @@ module Sequel
7
7
  # the additional support that the pg_* extensions add for advanced PostgreSQL
8
8
  # types such as arrays.
9
9
  #
10
- # This plugin modifies Model#set_values to do the same conversion that the
10
+ # This plugin makes model loading to do the same conversion that the
11
11
  # native postgres adapter would do for all columns given. You can either
12
12
  # specify the columns to typecast on load in the plugin call itself, or
13
13
  # afterwards using add_pg_typecast_on_load_columns:
@@ -41,19 +41,35 @@ module Sequel
41
41
  @pg_typecast_on_load_columns.concat(columns)
42
42
  end
43
43
 
44
- Plugins.inherited_instance_variables(self, :@pg_typecast_on_load_columns=>:dup)
45
- end
44
+ def call(values)
45
+ super(load_typecast_pg(values))
46
+ end
46
47
 
47
- module InstanceMethods
48
48
  # Lookup the conversion proc for the column's oid in the Database
49
49
  # object, and use it to convert the value.
50
- def set_values(values)
51
- model.pg_typecast_on_load_columns.each do |c|
50
+ def load_typecast_pg(values)
51
+ pg_typecast_on_load_columns.each do |c|
52
52
  if (v = values[c]).is_a?(String) && (oid = db_schema[c][:oid]) && (pr = db.conversion_procs[oid])
53
53
  values[c] = pr.call(v)
54
54
  end
55
55
  end
56
- super
56
+ values
57
+ end
58
+
59
+ Plugins.inherited_instance_variables(self, :@pg_typecast_on_load_columns=>:dup)
60
+ end
61
+
62
+ module InstanceMethods
63
+ private
64
+
65
+ # Typecast specific columns using the conversion procs when manually refreshing.
66
+ def _refresh_set_values(values)
67
+ super(model.load_typecast_pg(values))
68
+ end
69
+
70
+ # Typecast specific columns using the conversion procs when refreshing after save.
71
+ def _save_set_values(values)
72
+ super(model.load_typecast_pg(values))
57
73
  end
58
74
  end
59
75
  end
@@ -42,7 +42,7 @@ module Sequel
42
42
 
43
43
  # Create a prepared statement based on the given dataset with a unique name for the given
44
44
  # type of query and values.
45
- def prepare_statement(ds, type, vals={})
45
+ def prepare_statement(ds, type, vals=OPTS)
46
46
  ps = ds.prepare(type, :"smpsp_#{NEXT.call}", vals)
47
47
  ps.log_sql = true
48
48
  ps
@@ -25,8 +25,8 @@ module Sequel
25
25
  module ClassMethods
26
26
  # Disable prepared statement use if a block is given, or the :dataset or :conditions
27
27
  # options are used, or you are cloning an association.
28
- def associate(type, name, opts = {}, &block)
29
- if block || opts[:dataset] || opts[:conditions] || (opts[:clone] && association_reflection(opts[:clone])[:prepared_statement] == false)
28
+ def associate(type, name, opts = OPTS, &block)
29
+ if block || opts[:dataset] || (opts[:clone] && association_reflection(opts[:clone])[:prepared_statement] == false)
30
30
  opts = opts.merge(:prepared_statement=>false)
31
31
  end
32
32
  super(type, name, opts, &block)
@@ -48,7 +48,7 @@ module Sequel
48
48
  case opts[:type]
49
49
  when :many_to_one
50
50
  association_bound_variable_hash(opts.associated_class.table_name, opts.primary_keys, opts[:keys])
51
- when :one_to_many
51
+ when :one_to_many, :one_to_one
52
52
  association_bound_variable_hash(opts.associated_class.table_name, opts[:keys], opts[:primary_keys])
53
53
  when :many_to_many
54
54
  association_bound_variable_hash(opts.join_table_alias, opts[:left_keys], opts[:left_primary_keys])
@@ -59,10 +59,18 @@ module Sequel
59
59
 
60
60
  # Given an association reflection, return and cache a prepared statement for this association such
61
61
  # that, given appropriate bound variables, the prepared statement will work correctly for any
62
- # instance.
63
- def association_prepared_statement(opts)
62
+ # instance. Return false if such a prepared statement cannot be created.
63
+ def association_prepared_statement(opts, assoc_bv)
64
64
  opts.send(:cached_fetch, :prepared_statement) do
65
- ps = _associated_dataset(opts, {}).unbind.first.prepare(opts.returns_array? ? :select : :first, :"smpsap_#{NEXT.call}")
65
+ ds, bv = _associated_dataset(opts, {}).unbind
66
+ if bv.length != assoc_bv.length
67
+ h = {}
68
+ bv.each do |k,v|
69
+ h[k] = v unless assoc_bv.has_key?(k)
70
+ end
71
+ ds = ds.bind(h)
72
+ end
73
+ ps = ds.prepare(opts.returns_array? ? :select : :first, :"smpsap_#{NEXT.call}")
66
74
  ps.log_sql = true
67
75
  ps
68
76
  end
@@ -70,15 +78,13 @@ module Sequel
70
78
 
71
79
  # If a prepared statement can be used to load the associated objects, execute it to retrieve them. Otherwise,
72
80
  # fall back to the default implementation.
73
- def _load_associated_objects(opts, dynamic_opts={})
74
- if !opts.can_have_associated_objects?(self) || dynamic_opts[:callback] || (ps = opts[:prepared_statement]) == false
81
+ def _load_associated_objects(opts, dynamic_opts=OPTS)
82
+ if !opts.can_have_associated_objects?(self) || dynamic_opts[:callback] || (load_with_primary_key_lookup?(opts, dynamic_opts) && opts.associated_class.respond_to?(:cache_get_pk))
83
+ super
84
+ elsif (bv = association_bound_variables(opts)) && (ps ||= association_prepared_statement(opts, bv))
85
+ ps.call(bv)
86
+ else
75
87
  super
76
- else
77
- if bv = association_bound_variables(opts)
78
- (ps || association_prepared_statement(opts)).call(bv)
79
- else
80
- super
81
- end
82
88
  end
83
89
  end
84
90
  end
@@ -57,14 +57,14 @@ module Sequel
57
57
  # of free columns.
58
58
  def before_create
59
59
  if v = model.prepared_statements_column_defaults
60
- set_values(v.merge(values))
60
+ @values = v.merge(values)
61
61
  end
62
62
  super
63
63
  end
64
64
 
65
65
  # Always do a full save of all columns to reduce the number of prepared
66
66
  # statements that can be used.
67
- def save_changes(opts={})
67
+ def save_changes(opts=OPTS)
68
68
  save(opts) || false if modified?
69
69
  end
70
70
  end
@@ -92,7 +92,7 @@ module Sequel
92
92
  module RcteTree
93
93
  # Create the appropriate parent, children, ancestors, and descendants
94
94
  # associations for the model.
95
- def self.apply(model, opts={})
95
+ def self.apply(model, opts=OPTS)
96
96
  model.plugin :tree, opts
97
97
 
98
98
  opts = opts.dup
@@ -172,19 +172,20 @@ module Sequel
172
172
  @deserialized_values ||= {}
173
173
  end
174
174
 
175
+ # Freeze the deserialized values
175
176
  def freeze
176
177
  deserialized_values.freeze
177
178
  super
178
179
  end
179
180
 
180
- # Initialization the deserialized values for objects retrieved from the database.
181
- def set_values(hash)
181
+ private
182
+
183
+ # Clear any cached deserialized values when doing a manual refresh.
184
+ def _refresh_set_values(hash)
182
185
  @deserialized_values.clear if @deserialized_values
183
186
  super
184
187
  end
185
188
 
186
- private
187
-
188
189
  # Deserialize the column value. Called when the model column accessor is called to
189
190
  # return a deserialized value.
190
191
  def deserialize_value(column, v)
@@ -34,7 +34,7 @@ module Sequel
34
34
  # show the column is modified after saving.
35
35
  def after_save
36
36
  super
37
- @original_deserialized_values = {}
37
+ @original_deserialized_values = @deserialized_values
38
38
  end
39
39
 
40
40
  # Detect which serialized columns have changed.
@@ -27,7 +27,7 @@ module Sequel
27
27
  # When eagerly loading, if the current dataset has a defined shard and the
28
28
  # dataset that you will be using to get the associated records does not,
29
29
  # use the current dataset's shard for the associated dataset.
30
- def eager_loading_dataset(opts, ds, select, associations, eager_options={})
30
+ def eager_loading_dataset(opts, ds, select, associations, eager_options=OPTS)
31
31
  ds = super(opts, ds, select, associations, eager_options)
32
32
  if !ds.opts[:server] and s = eager_options[:self] and server = s.opts[:server]
33
33
  ds = ds.server(server)
@@ -82,6 +82,12 @@ module Sequel
82
82
  o.set_server?(@server) if o.respond_to?(:set_server?)
83
83
  super
84
84
  end
85
+
86
+ # Don't use primary key lookup to load associated objects, since that will not
87
+ # respect the current object's server.
88
+ def load_with_primary_key_lookup?(opts, dynamic_opts)
89
+ false
90
+ end
85
91
  end
86
92
 
87
93
  module DatasetMethods
@@ -69,7 +69,7 @@ module Sequel
69
69
  # as keys.
70
70
  module SingleTableInheritance
71
71
  # Setup the necessary STI variables, see the module RDoc for SingleTableInheritance
72
- def self.configure(model, key, opts={})
72
+ def self.configure(model, key, opts=OPTS)
73
73
  model.instance_eval do
74
74
  @sti_key_array = nil
75
75
  @sti_key = key
@@ -26,7 +26,7 @@ module Sequel
26
26
  # * :force - Whether to overwrite an existing create timestamp (default: false)
27
27
  # * :update - The field to hold the update timestamp (default: :updated_at)
28
28
  # * :update_on_create - Whether to set the update timestamp to the create timestamp when creating (default: false)
29
- def self.configure(model, opts={})
29
+ def self.configure(model, opts=OPTS)
30
30
  model.instance_eval do
31
31
  @create_timestamp_field = opts[:create]||:created_at
32
32
  @update_timestamp_field = opts[:update]||:updated_at
@@ -30,7 +30,7 @@ module Sequel
30
30
  # The default column to update when touching
31
31
  TOUCH_COLUMN_DEFAULT = :updated_at
32
32
 
33
- def self.apply(model, opts={})
33
+ def self.apply(model, opts=OPTS)
34
34
  model.instance_variable_set(:@touched_associations, {})
35
35
  end
36
36
 
@@ -43,7 +43,7 @@ module Sequel
43
43
  # when updating the associated objects is the model's touch_column.
44
44
  # If a hash is used, the value is used as the column to update.
45
45
  # * :column - The column to modify when touching a model instance.
46
- def self.configure(model, opts={})
46
+ def self.configure(model, opts=OPTS)
47
47
  model.touch_column = opts[:column] || TOUCH_COLUMN_DEFAULT if opts[:column] || !model.touch_column
48
48
  model.touch_associations(opts[:associations]) if opts[:associations]
49
49
  end
@@ -27,7 +27,7 @@ module Sequel
27
27
  # specify options to use for the parent association
28
28
  # using a :parent option, and options to use for the
29
29
  # children association using a :children option.
30
- def self.apply(model, opts={})
30
+ def self.apply(model, opts=OPTS)
31
31
  opts = opts.dup
32
32
  opts[:class] = model
33
33
 
@@ -5,7 +5,7 @@ module Sequel
5
5
  # typecast correctly (with correct being defined as how the model object
6
6
  # would typecast the same column values).
7
7
  #
8
- # This plugin modifies Model#set_values to call the setter methods (which typecast
8
+ # This plugin makes model loading call the setter methods (which typecast
9
9
  # by default) for all columns given. You can either specify the columns to
10
10
  # typecast on load in the plugin call itself, or afterwards using
11
11
  # add_typecast_on_load_columns:
@@ -36,6 +36,12 @@ module Sequel
36
36
  @typecast_on_load_columns.concat(columns)
37
37
  end
38
38
 
39
+ # Typecast values using #load_typecast when the values are retrieved
40
+ # from the database.
41
+ def call(values)
42
+ super.load_typecast
43
+ end
44
+
39
45
  Plugins.inherited_instance_variables(self, :@typecast_on_load_columns=>:dup)
40
46
  end
41
47
 
@@ -52,9 +58,18 @@ module Sequel
52
58
  self
53
59
  end
54
60
 
55
- # Typecast values using #load_typecast when the values are retrieved from
56
- # the database.
57
- def set_values(values)
61
+ private
62
+
63
+ # Typecast values using #load_typecast when the values are refreshed manually.
64
+ def _refresh_set_values(values)
65
+ ret = super
66
+ load_typecast
67
+ ret
68
+ end
69
+
70
+ # Typecast values using #load_typecast when the values are refreshed
71
+ # automatically after a save.
72
+ def _save_set_values(values)
58
73
  ret = super
59
74
  load_typecast
60
75
  ret
@@ -264,36 +264,6 @@ module Sequel
264
264
  end
265
265
  end
266
266
 
267
- # Validates whether an attribute is not a string. This is generally useful
268
- # in conjunction with raise_on_typecast_failure = false, where you are
269
- # passing in string values for non-string attributes (such as numbers and dates).
270
- # If typecasting fails (invalid number or date), the value of the attribute will
271
- # be a string in an invalid format, and if typecasting succeeds, the value will
272
- # not be a string.
273
- #
274
- # Possible Options:
275
- # * :message - The message to use (default: 'is a string' or 'is not a valid (integer|datetime|etc.)' if the type is known)
276
- def validates_not_string(*atts)
277
- Sequel::Deprecation.deprecate('validates_not_string', "Please switch to validates_schema_type")
278
- opts = {
279
- :tag => :not_string,
280
- }.merge!(extract_options!(atts))
281
- reflect_validation(:not_string, opts, atts)
282
- atts << opts
283
- validates_each(*atts) do |o, a, v|
284
- if v.is_a?(String)
285
- unless message = opts[:message]
286
- message = if sch = o.db_schema[a] and typ = sch[:type]
287
- "is not a valid #{typ}"
288
- else
289
- "is a string"
290
- end
291
- end
292
- o.errors.add(a, message)
293
- end
294
- end
295
- end
296
-
297
267
  # Validates whether an attribute is a number.
298
268
  #
299
269
  # Possible Options:
@@ -32,9 +32,7 @@ module Sequel
32
32
  # :allow_nil :: Whether to skip the validation if the value is nil.
33
33
  # :message :: The message to use. Can be a string which is used directly, or a
34
34
  # proc which is called. If the validation method takes a argument before the array of attributes,
35
- # that argument is passed as an argument to the proc. The exception is the
36
- # validates_not_string method, which doesn't take an argument, but passes
37
- # the schema type symbol as the argument to the proc.
35
+ # that argument is passed as an argument to the proc.
38
36
  #
39
37
  # The default validation options for all models can be modified by
40
38
  # changing the values of the Sequel::Plugins::ValidationHelpers::DEFAULT_OPTIONS hash. You
@@ -84,7 +82,6 @@ module Sequel
84
82
  :max_length=>{:message=>lambda{|max| "is longer than #{max} characters"}, :nil_message=>lambda{"is not present"}},
85
83
  :min_length=>{:message=>lambda{|min| "is shorter than #{min} characters"}},
86
84
  :not_null=>{:message=>lambda{"is not present"}},
87
- :not_string=>{:message=>lambda{|type| type ? "is not a valid #{type}" : "is a string"}},
88
85
  :numeric=>{:message=>lambda{"is not a number"}},
89
86
  :type=>{:message=>lambda{|klass| klass.is_a?(Array) ? "is not a valid #{klass.join(" or ").downcase}" : "is not a valid #{klass.to_s.downcase}"}},
90
87
  :presence=>{:message=>lambda{"is not present"}},
@@ -93,22 +90,22 @@ module Sequel
93
90
 
94
91
  module InstanceMethods
95
92
  # Check that the attribute values are the given exact length.
96
- def validates_exact_length(exact, atts, opts={})
93
+ def validates_exact_length(exact, atts, opts=OPTS)
97
94
  validatable_attributes_for_type(:exact_length, atts, opts){|a,v,m| validation_error_message(m, exact) if v.nil? || v.length != exact}
98
95
  end
99
96
 
100
97
  # Check the string representation of the attribute value(s) against the regular expression with.
101
- def validates_format(with, atts, opts={})
98
+ def validates_format(with, atts, opts=OPTS)
102
99
  validatable_attributes_for_type(:format, atts, opts){|a,v,m| validation_error_message(m, with) unless v.to_s =~ with}
103
100
  end
104
101
 
105
102
  # Check attribute value(s) is included in the given set.
106
- def validates_includes(set, atts, opts={})
103
+ def validates_includes(set, atts, opts=OPTS)
107
104
  validatable_attributes_for_type(:includes, atts, opts){|a,v,m| validation_error_message(m, set) unless set.send(set.respond_to?(:cover?) ? :cover? : :include?, v)}
108
105
  end
109
106
 
110
107
  # Check attribute value(s) string representation is a valid integer.
111
- def validates_integer(atts, opts={})
108
+ def validates_integer(atts, opts=OPTS)
112
109
  validatable_attributes_for_type(:integer, atts, opts) do |a,v,m|
113
110
  begin
114
111
  Kernel.Integer(v.to_s)
@@ -120,7 +117,7 @@ module Sequel
120
117
  end
121
118
 
122
119
  # Check that the attribute values length is in the specified range.
123
- def validates_length_range(range, atts, opts={})
120
+ def validates_length_range(range, atts, opts=OPTS)
124
121
  validatable_attributes_for_type(:length_range, atts, opts){|a,v,m| validation_error_message(m, range) if v.nil? || !range.send(range.respond_to?(:cover?) ? :cover? : :include?, v.length)}
125
122
  end
126
123
 
@@ -128,33 +125,22 @@ module Sequel
128
125
  #
129
126
  # Accepts a :nil_message option that is the error message to use when the
130
127
  # value is nil instead of being too long.
131
- def validates_max_length(max, atts, opts={})
128
+ def validates_max_length(max, atts, opts=OPTS)
132
129
  validatable_attributes_for_type(:max_length, atts, opts){|a,v,m| v ? validation_error_message(m, max) : validation_error_message(opts[:nil_message] || DEFAULT_OPTIONS[:max_length][:nil_message]) if v.nil? || v.length > max}
133
130
  end
134
131
 
135
132
  # Check that the attribute values are not shorter than the given min length.
136
- def validates_min_length(min, atts, opts={})
133
+ def validates_min_length(min, atts, opts=OPTS)
137
134
  validatable_attributes_for_type(:min_length, atts, opts){|a,v,m| validation_error_message(m, min) if v.nil? || v.length < min}
138
135
  end
139
136
 
140
137
  # Check attribute value(s) are not NULL/nil.
141
- def validates_not_null(atts, opts={})
138
+ def validates_not_null(atts, opts=OPTS)
142
139
  validatable_attributes_for_type(:not_null, atts, opts){|a,v,m| validation_error_message(m) if v.nil?}
143
140
  end
144
141
 
145
- # Check that the attribute value(s) is not a string. This is generally useful
146
- # in conjunction with raise_on_typecast_failure = false, where you are
147
- # passing in string values for non-string attributes (such as numbers and dates).
148
- # If typecasting fails (invalid number or date), the value of the attribute will
149
- # be a string in an invalid format, and if typecasting succeeds, the value will
150
- # not be a string.
151
- def validates_not_string(atts, opts={})
152
- Sequel::Deprecation.deprecate('validates_not_string', "Please switch to validates_schema_types")
153
- validatable_attributes_for_type(:not_string, atts, opts){|a,v,m| validation_error_message(m, (db_schema[a]||{})[:type]) if v.is_a?(String)}
154
- end
155
-
156
142
  # Check attribute value(s) string representation is a valid float.
157
- def validates_numeric(atts, opts={})
143
+ def validates_numeric(atts, opts=OPTS)
158
144
  validatable_attributes_for_type(:numeric, atts, opts) do |a,v,m|
159
145
  begin
160
146
  Kernel.Float(v.to_s)
@@ -168,7 +154,7 @@ module Sequel
168
154
  # Validates for all of the model columns (or just the given columns)
169
155
  # that the column value is an instance of the expected class based on
170
156
  # the column's schema type.
171
- def validates_schema_types(atts=keys, opts={})
157
+ def validates_schema_types(atts=keys, opts=OPTS)
172
158
  Array(atts).each do |k|
173
159
  if type = schema_type_class(k)
174
160
  validates_type(type, k, {:allow_nil=>true}.merge(opts))
@@ -178,13 +164,9 @@ module Sequel
178
164
 
179
165
  # Check if value is an instance of a class. If +klass+ is an array,
180
166
  # the value must be an instance of one of the classes in the array.
181
- def validates_type(klass, atts, opts={})
167
+ def validates_type(klass, atts, opts=OPTS)
182
168
  klass = klass.to_s.constantize if klass.is_a?(String) || klass.is_a?(Symbol)
183
169
  validatable_attributes_for_type(:type, atts, opts) do |a,v,m|
184
- if v.nil?
185
- Sequel::Deprecation.deprecate('validates_type will no longer allow nil values by default in Sequel 4. Use the :allow_nil=>true option to allow nil values.')
186
- next
187
- end
188
170
  if klass.is_a?(Array) ? !klass.any?{|kls| v.is_a?(kls)} : !v.is_a?(klass)
189
171
  validation_error_message(m, klass)
190
172
  end
@@ -192,7 +174,7 @@ module Sequel
192
174
  end
193
175
 
194
176
  # Check attribute value(s) is not considered blank by the database, but allow false values.
195
- def validates_presence(atts, opts={})
177
+ def validates_presence(atts, opts=OPTS)
196
178
  validatable_attributes_for_type(:presence, atts, opts){|a,v,m| validation_error_message(m) if model.db.send(:blank_object?, v) && v != false}
197
179
  end
198
180