sequel 4.46.0 → 4.49.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (228) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +210 -0
  3. data/Rakefile +1 -1
  4. data/doc/advanced_associations.rdoc +1 -1
  5. data/doc/opening_databases.rdoc +3 -2
  6. data/doc/release_notes/4.47.0.txt +56 -0
  7. data/doc/release_notes/4.48.0.txt +293 -0
  8. data/doc/release_notes/4.49.0.txt +222 -0
  9. data/lib/sequel/adapters/ado/access.rb +2 -1
  10. data/lib/sequel/adapters/do/postgres.rb +5 -2
  11. data/lib/sequel/adapters/ibmdb.rb +30 -8
  12. data/lib/sequel/adapters/jdbc/as400.rb +1 -1
  13. data/lib/sequel/adapters/jdbc/db2.rb +12 -3
  14. data/lib/sequel/adapters/jdbc/derby.rb +4 -5
  15. data/lib/sequel/adapters/jdbc/h2.rb +10 -1
  16. data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
  17. data/lib/sequel/adapters/jdbc/postgresql.rb +46 -20
  18. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
  19. data/lib/sequel/adapters/jdbc/sqlserver.rb +20 -6
  20. data/lib/sequel/adapters/jdbc.rb +39 -23
  21. data/lib/sequel/adapters/mock.rb +27 -19
  22. data/lib/sequel/adapters/mysql.rb +17 -16
  23. data/lib/sequel/adapters/mysql2.rb +5 -6
  24. data/lib/sequel/adapters/oracle.rb +5 -9
  25. data/lib/sequel/adapters/postgres.rb +91 -103
  26. data/lib/sequel/adapters/shared/db2.rb +22 -6
  27. data/lib/sequel/adapters/shared/mssql.rb +5 -4
  28. data/lib/sequel/adapters/shared/mysql.rb +79 -25
  29. data/lib/sequel/adapters/shared/oracle.rb +26 -3
  30. data/lib/sequel/adapters/shared/postgres.rb +199 -95
  31. data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
  32. data/lib/sequel/adapters/shared/sqlite.rb +72 -82
  33. data/lib/sequel/adapters/sqlanywhere.rb +4 -1
  34. data/lib/sequel/adapters/sqlite.rb +5 -3
  35. data/lib/sequel/adapters/swift/postgres.rb +5 -2
  36. data/lib/sequel/adapters/tinytds.rb +0 -5
  37. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
  38. data/lib/sequel/adapters/utils/pg_types.rb +2 -76
  39. data/lib/sequel/ast_transformer.rb +1 -1
  40. data/lib/sequel/connection_pool/sharded_single.rb +1 -1
  41. data/lib/sequel/connection_pool/sharded_threaded.rb +1 -1
  42. data/lib/sequel/connection_pool/single.rb +2 -2
  43. data/lib/sequel/connection_pool/threaded.rb +2 -2
  44. data/lib/sequel/connection_pool.rb +9 -2
  45. data/lib/sequel/core.rb +2 -2
  46. data/lib/sequel/database/connecting.rb +8 -8
  47. data/lib/sequel/database/dataset.rb +6 -3
  48. data/lib/sequel/database/dataset_defaults.rb +14 -1
  49. data/lib/sequel/database/misc.rb +1 -1
  50. data/lib/sequel/database/query.rb +3 -0
  51. data/lib/sequel/database/schema_methods.rb +1 -1
  52. data/lib/sequel/dataset/actions.rb +72 -10
  53. data/lib/sequel/dataset/dataset_module.rb +58 -0
  54. data/lib/sequel/dataset/graph.rb +1 -1
  55. data/lib/sequel/dataset/misc.rb +1 -0
  56. data/lib/sequel/dataset/prepared_statements.rb +3 -3
  57. data/lib/sequel/dataset/query.rb +22 -11
  58. data/lib/sequel/dataset.rb +1 -1
  59. data/lib/sequel/exceptions.rb +8 -0
  60. data/lib/sequel/extensions/_model_pg_row.rb +5 -2
  61. data/lib/sequel/extensions/core_extensions.rb +4 -1
  62. data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -1
  63. data/lib/sequel/extensions/date_arithmetic.rb +1 -0
  64. data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -3
  65. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
  66. data/lib/sequel/extensions/filter_having.rb +2 -0
  67. data/lib/sequel/extensions/freeze_datasets.rb +2 -0
  68. data/lib/sequel/extensions/from_block.rb +1 -1
  69. data/lib/sequel/extensions/graph_each.rb +2 -2
  70. data/lib/sequel/extensions/hash_aliases.rb +2 -0
  71. data/lib/sequel/extensions/identifier_mangling.rb +0 -7
  72. data/lib/sequel/extensions/meta_def.rb +2 -0
  73. data/lib/sequel/extensions/migration.rb +11 -8
  74. data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
  75. data/lib/sequel/extensions/null_dataset.rb +1 -0
  76. data/lib/sequel/extensions/pagination.rb +1 -1
  77. data/lib/sequel/extensions/pg_array.rb +207 -130
  78. data/lib/sequel/extensions/pg_hstore.rb +38 -20
  79. data/lib/sequel/extensions/pg_inet.rb +18 -6
  80. data/lib/sequel/extensions/pg_interval.rb +19 -12
  81. data/lib/sequel/extensions/pg_json.rb +25 -14
  82. data/lib/sequel/extensions/pg_json_ops.rb +2 -2
  83. data/lib/sequel/extensions/pg_range.rb +133 -100
  84. data/lib/sequel/extensions/pg_range_ops.rb +4 -3
  85. data/lib/sequel/extensions/pg_row.rb +68 -39
  86. data/lib/sequel/extensions/pg_row_ops.rb +11 -5
  87. data/lib/sequel/extensions/query_literals.rb +2 -0
  88. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
  89. data/lib/sequel/extensions/s.rb +1 -1
  90. data/lib/sequel/extensions/schema_dumper.rb +29 -25
  91. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
  92. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
  93. data/lib/sequel/extensions/server_block.rb +32 -15
  94. data/lib/sequel/extensions/set_overrides.rb +2 -2
  95. data/lib/sequel/extensions/string_agg.rb +0 -1
  96. data/lib/sequel/extensions/symbol_aref.rb +0 -4
  97. data/lib/sequel/model/associations.rb +35 -7
  98. data/lib/sequel/model/base.rb +113 -87
  99. data/lib/sequel/model/dataset_module.rb +5 -43
  100. data/lib/sequel/model/errors.rb +2 -1
  101. data/lib/sequel/model/inflections.rb +17 -5
  102. data/lib/sequel/model.rb +26 -58
  103. data/lib/sequel/plugins/active_model.rb +2 -2
  104. data/lib/sequel/plugins/association_autoreloading.rb +2 -0
  105. data/lib/sequel/plugins/association_dependencies.rb +3 -3
  106. data/lib/sequel/plugins/association_pks.rb +73 -46
  107. data/lib/sequel/plugins/association_proxies.rb +1 -1
  108. data/lib/sequel/plugins/auto_validations.rb +6 -2
  109. data/lib/sequel/plugins/boolean_readers.rb +2 -2
  110. data/lib/sequel/plugins/boolean_subsets.rb +1 -1
  111. data/lib/sequel/plugins/caching.rb +19 -13
  112. data/lib/sequel/plugins/class_table_inheritance.rb +24 -13
  113. data/lib/sequel/plugins/column_conflicts.rb +7 -2
  114. data/lib/sequel/plugins/column_select.rb +3 -3
  115. data/lib/sequel/plugins/composition.rb +2 -2
  116. data/lib/sequel/plugins/csv_serializer.rb +8 -8
  117. data/lib/sequel/plugins/dataset_associations.rb +25 -13
  118. data/lib/sequel/plugins/defaults_setter.rb +13 -1
  119. data/lib/sequel/plugins/eager_each.rb +1 -1
  120. data/lib/sequel/plugins/force_encoding.rb +2 -2
  121. data/lib/sequel/plugins/hook_class_methods.rb +9 -12
  122. data/lib/sequel/plugins/identifier_columns.rb +2 -0
  123. data/lib/sequel/plugins/instance_filters.rb +3 -1
  124. data/lib/sequel/plugins/instance_hooks.rb +17 -9
  125. data/lib/sequel/plugins/json_serializer.rb +19 -12
  126. data/lib/sequel/plugins/lazy_attributes.rb +8 -7
  127. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +2 -0
  128. data/lib/sequel/plugins/modification_detection.rb +3 -0
  129. data/lib/sequel/plugins/nested_attributes.rb +6 -2
  130. data/lib/sequel/plugins/pg_array_associations.rb +5 -0
  131. data/lib/sequel/plugins/pg_row.rb +4 -2
  132. data/lib/sequel/plugins/pg_typecast_on_load.rb +2 -0
  133. data/lib/sequel/plugins/prepared_statements.rb +1 -0
  134. data/lib/sequel/plugins/rcte_tree.rb +4 -24
  135. data/lib/sequel/plugins/serialization.rb +9 -15
  136. data/lib/sequel/plugins/single_table_inheritance.rb +8 -3
  137. data/lib/sequel/plugins/split_values.rb +6 -5
  138. data/lib/sequel/plugins/static_cache.rb +31 -25
  139. data/lib/sequel/plugins/subset_conditions.rb +3 -1
  140. data/lib/sequel/plugins/table_select.rb +1 -1
  141. data/lib/sequel/plugins/touch.rb +4 -2
  142. data/lib/sequel/plugins/validation_class_methods.rb +5 -6
  143. data/lib/sequel/plugins/validation_helpers.rb +14 -8
  144. data/lib/sequel/plugins/xml_serializer.rb +4 -4
  145. data/lib/sequel/sql.rb +18 -9
  146. data/lib/sequel/version.rb +1 -1
  147. data/spec/adapters/db2_spec.rb +115 -14
  148. data/spec/adapters/mssql_spec.rb +4 -4
  149. data/spec/adapters/mysql_spec.rb +83 -29
  150. data/spec/adapters/oracle_spec.rb +28 -24
  151. data/spec/adapters/postgres_spec.rb +40 -24
  152. data/spec/adapters/sqlanywhere_spec.rb +88 -86
  153. data/spec/adapters/sqlite_spec.rb +29 -24
  154. data/spec/bin_spec.rb +7 -1
  155. data/spec/core/connection_pool_spec.rb +45 -14
  156. data/spec/core/database_spec.rb +155 -0
  157. data/spec/core/dataset_spec.rb +219 -36
  158. data/spec/core/schema_spec.rb +16 -0
  159. data/spec/core/spec_helper.rb +1 -0
  160. data/spec/core_extensions_spec.rb +6 -2
  161. data/spec/extensions/active_model_spec.rb +1 -1
  162. data/spec/extensions/arbitrary_servers_spec.rb +1 -1
  163. data/spec/extensions/association_pks_spec.rb +34 -2
  164. data/spec/extensions/auto_literal_strings_spec.rb +5 -1
  165. data/spec/extensions/auto_validations_spec.rb +2 -0
  166. data/spec/extensions/boolean_readers_spec.rb +1 -1
  167. data/spec/extensions/boolean_subsets_spec.rb +1 -1
  168. data/spec/extensions/class_table_inheritance_spec.rb +106 -19
  169. data/spec/extensions/column_conflicts_spec.rb +11 -0
  170. data/spec/extensions/column_select_spec.rb +1 -0
  171. data/spec/extensions/composition_spec.rb +13 -0
  172. data/spec/extensions/connection_validator_spec.rb +1 -1
  173. data/spec/extensions/dataset_associations_spec.rb +20 -8
  174. data/spec/extensions/defaults_setter_spec.rb +15 -1
  175. data/spec/extensions/filter_having_spec.rb +5 -3
  176. data/spec/extensions/hash_aliases_spec.rb +3 -1
  177. data/spec/extensions/identifier_columns_spec.rb +3 -1
  178. data/spec/extensions/implicit_subquery_spec.rb +4 -2
  179. data/spec/extensions/json_serializer_spec.rb +18 -0
  180. data/spec/extensions/lazy_attributes_spec.rb +3 -3
  181. data/spec/extensions/many_through_many_spec.rb +4 -4
  182. data/spec/extensions/meta_def_spec.rb +9 -0
  183. data/spec/extensions/migration_spec.rb +3 -3
  184. data/spec/extensions/nested_attributes_spec.rb +14 -3
  185. data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
  186. data/spec/extensions/null_dataset_spec.rb +1 -1
  187. data/spec/extensions/pg_array_associations_spec.rb +29 -18
  188. data/spec/extensions/pg_array_spec.rb +44 -25
  189. data/spec/extensions/pg_hstore_spec.rb +10 -0
  190. data/spec/extensions/pg_inet_spec.rb +26 -0
  191. data/spec/extensions/pg_interval_spec.rb +20 -0
  192. data/spec/extensions/pg_json_spec.rb +24 -0
  193. data/spec/extensions/pg_range_spec.rb +98 -14
  194. data/spec/extensions/pg_row_spec.rb +14 -4
  195. data/spec/extensions/pg_typecast_on_load_spec.rb +11 -9
  196. data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
  197. data/spec/extensions/query_literals_spec.rb +3 -1
  198. data/spec/extensions/schema_dumper_spec.rb +108 -94
  199. data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
  200. data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
  201. data/spec/extensions/serialization_spec.rb +1 -1
  202. data/spec/extensions/server_block_spec.rb +7 -0
  203. data/spec/extensions/single_table_inheritance_spec.rb +17 -1
  204. data/spec/extensions/spec_helper.rb +7 -1
  205. data/spec/extensions/static_cache_spec.rb +75 -24
  206. data/spec/extensions/string_agg_spec.rb +1 -1
  207. data/spec/extensions/touch_spec.rb +9 -0
  208. data/spec/extensions/validation_helpers_spec.rb +10 -5
  209. data/spec/extensions/whitelist_security_spec.rb +26 -0
  210. data/spec/integration/associations_test.rb +8 -0
  211. data/spec/integration/dataset_test.rb +45 -44
  212. data/spec/integration/model_test.rb +53 -4
  213. data/spec/integration/plugin_test.rb +28 -4
  214. data/spec/integration/prepared_statement_test.rb +3 -0
  215. data/spec/integration/schema_test.rb +21 -1
  216. data/spec/integration/transaction_test.rb +40 -40
  217. data/spec/model/association_reflection_spec.rb +43 -1
  218. data/spec/model/associations_spec.rb +29 -9
  219. data/spec/model/class_dataset_methods_spec.rb +20 -4
  220. data/spec/model/dataset_methods_spec.rb +12 -3
  221. data/spec/model/eager_loading_spec.rb +8 -8
  222. data/spec/model/model_spec.rb +45 -1
  223. data/spec/model/plugins_spec.rb +34 -0
  224. data/spec/model/record_spec.rb +1 -1
  225. data/spec/spec_config.rb +2 -0
  226. metadata +11 -4
  227. data/spec/adapters/firebird_spec.rb +0 -405
  228. data/spec/adapters/informix_spec.rb +0 -100
@@ -53,7 +53,6 @@
53
53
  # * DB2 9.7+ (except distinct)
54
54
  # * MySQL
55
55
  # * HSQLDB
56
- # * CUBRID
57
56
  # * H2
58
57
  #
59
58
  # Related module: Sequel::SQL::StringAgg
@@ -18,10 +18,6 @@
18
18
  # If you are using Ruby 2+, and you would like to use refinements, there
19
19
  # is a refinement version of this in the symbol_aref_refinement extension.
20
20
  #
21
- # If you are using the ruby18_symbol_extensions, and would like symbol_aref
22
- # to take affect, load the symbol_aref extension after the
23
- # ruby18_symbol_extensions.
24
- #
25
21
  # Related module: Sequel::SymbolAref
26
22
 
27
23
  if RUBY_VERSION >= '2.0'
@@ -15,6 +15,7 @@ module Sequel
15
15
  @autoreloading_associations = {}
16
16
  @cache_associations = true
17
17
  @default_association_options = {}
18
+ @default_association_type_options = {}
18
19
  @dataset_module_class = DatasetModule
19
20
  end
20
21
  end
@@ -326,6 +327,7 @@ module Sequel
326
327
 
327
328
  # Alias of predicate_key, only for backwards compatibility.
328
329
  def eager_loading_predicate_key
330
+ Sequel::Deprecation.deprecate("AssociationReflection#eager_loading_predicate_key", "Use #predicate_key instead")
329
331
  predicate_key
330
332
  end
331
333
 
@@ -1449,7 +1451,7 @@ module Sequel
1449
1451
 
1450
1452
  # This module contains methods added to all association datasets
1451
1453
  module AssociationDatasetMethods
1452
- Dataset.def_deprecated_opts_setter(self, :model, :association_reflection)
1454
+ Dataset.def_deprecated_opts_setter(self, :model_object, :association_reflection)
1453
1455
 
1454
1456
  # The model object that created the association dataset
1455
1457
  def model_object
@@ -1460,6 +1462,12 @@ module Sequel
1460
1462
  def association_reflection
1461
1463
  @opts[:association_reflection]
1462
1464
  end
1465
+
1466
+ private
1467
+
1468
+ def non_sql_option?(key)
1469
+ super || key == :model_object || key == :association_reflection
1470
+ end
1463
1471
  end
1464
1472
 
1465
1473
  # Each kind of association adds a number of instance methods to the model class which
@@ -1526,9 +1534,15 @@ module Sequel
1526
1534
  # the previous class.
1527
1535
  attr_accessor :cache_associations
1528
1536
 
1529
- # The default options to use for all associations.
1537
+ # The default options to use for all associations. This hash is merged into the association reflection hash for
1538
+ # all association reflections.
1530
1539
  attr_accessor :default_association_options
1531
1540
 
1541
+ # The default options to use for all associations of a given type. This is a hash keyed by association type
1542
+ # symbol. If there is a value for the association type symbol key, the resulting hash will be merged into the
1543
+ # association reflection hash for all association reflections of that type.
1544
+ attr_accessor :default_association_type_options
1545
+
1532
1546
  # The default :eager_limit_strategy option to use for limited or offset associations (default: true, causing Sequel
1533
1547
  # to use what it considers the most appropriate strategy).
1534
1548
  attr_accessor :default_eager_limit_strategy
@@ -1768,7 +1782,13 @@ module Sequel
1768
1782
  orig_opts = cloned_assoc[:orig_opts].merge(orig_opts)
1769
1783
  end
1770
1784
 
1771
- opts = default_association_options.merge(orig_opts).merge(:type => type, :name => name, :cache=>({} if cache_associations), :model => self)
1785
+ opts = Hash[default_association_options]
1786
+ if type_options = default_association_type_options[type]
1787
+ opts.merge!(type_options)
1788
+ end
1789
+ opts.merge!(orig_opts)
1790
+ opts.merge!(:type => type, :name => name, :cache=>({} if cache_associations), :model => self)
1791
+
1772
1792
  opts[:block] = block if block
1773
1793
  if !opts.has_key?(:instance_specific) && (block || orig_opts[:block] || orig_opts[:dataset])
1774
1794
  # It's possible the association is instance specific, in that it depends on
@@ -1784,6 +1804,7 @@ module Sequel
1784
1804
 
1785
1805
  opts[:eager_block] = opts[:block] unless opts.include?(:eager_block)
1786
1806
  if !opts.has_key?(:predicate_key) && opts.has_key?(:eager_loading_predicate_key)
1807
+ Sequel::Deprecation.deprecate("The :eager_loading_predicate_key association option", "Use the :predicate_key option instead")
1787
1808
  opts[:predicate_key] = opts[:eager_loading_predicate_key]
1788
1809
  end
1789
1810
  opts[:graph_join_type] ||= :left_outer
@@ -1832,6 +1853,8 @@ module Sequel
1832
1853
  @association_reflections.freeze.each_value(&:freeze)
1833
1854
  @autoreloading_associations.freeze.each_value(&:freeze)
1834
1855
  @default_association_options.freeze
1856
+ @default_association_type_options.freeze
1857
+ @default_association_type_options.each_value(&:freeze)
1835
1858
 
1836
1859
  super
1837
1860
  end
@@ -1869,7 +1892,7 @@ module Sequel
1869
1892
  associate(:one_to_one, name, opts, &block)
1870
1893
  end
1871
1894
 
1872
- Plugins.inherited_instance_variables(self, :@association_reflections=>:dup, :@autoreloading_associations=>:hash_dup, :@default_association_options=>:dup, :@cache_associations=>nil, :@default_eager_limit_strategy=>nil)
1895
+ Plugins.inherited_instance_variables(self, :@association_reflections=>:dup, :@autoreloading_associations=>:hash_dup, :@default_association_options=>:dup, :@default_association_type_options=>:hash_dup, :@cache_associations=>nil, :@default_eager_limit_strategy=>nil)
1873
1896
  Plugins.def_dataset_methods(self, [:eager, :eager_graph, :eager_graph_with_options, :association_join, :association_full_join, :association_inner_join, :association_left_join, :association_right_join])
1874
1897
 
1875
1898
  private
@@ -1896,7 +1919,7 @@ module Sequel
1896
1919
  # Adds the association method to the association methods module.
1897
1920
  def def_association_method(opts)
1898
1921
  association_module_def(opts.association_method, opts) do |*dynamic_opts, &block|
1899
- Sequel::Deprecation.deprecate("Passing multiple arguments to ##{opts.association_method}", "Additional arguments are currently ignored.") if dynamic_opts.length > 1
1922
+ Sequel::Deprecation.deprecate("Passing multiple arguments to ##{opts.association_method}", "Additional arguments are currently ignored") if dynamic_opts.length > 1
1900
1923
  load_associated_objects(opts, dynamic_opts.length == 0 ? OPTS : dynamic_opts[0], &block)
1901
1924
  end
1902
1925
  end
@@ -2534,6 +2557,7 @@ module Sequel
2534
2557
  end
2535
2558
 
2536
2559
  if res == false and stop_on_false
2560
+ Sequel::Deprecation.deprecate("Having #{callback_type} association callback return false to cancel modification", "Instead, call Model#cancel_action inside the association callback")
2537
2561
  raise(HookFailed, "Unable to modify association for #{inspect}: one of the #{callback_type} hooks returned false")
2538
2562
  end
2539
2563
  end
@@ -2799,7 +2823,7 @@ END
2799
2823
 
2800
2824
  # If the dataset is being eagerly loaded, default to calling all
2801
2825
  # instead of each.
2802
- def to_hash(key_column=nil, value_column=nil, opts=OPTS)
2826
+ def as_hash(key_column=nil, value_column=nil, opts=OPTS)
2803
2827
  if (@opts[:eager_graph] || @opts[:eager]) && !opts.has_key?(:all)
2804
2828
  opts = Hash[opts]
2805
2829
  opts[:all] = true
@@ -3024,7 +3048,7 @@ END
3024
3048
  # specific foreign/primary key
3025
3049
  key_hash = {}
3026
3050
  # Reflections for all associations to eager load
3027
- reflections = eager_assoc.keys.collect{|assoc| model.association_reflection(assoc) || (raise Sequel::UndefinedAssociation, "Model: #{self}, Association: #{assoc}")}
3051
+ reflections = eager_assoc.keys.map{|assoc| model.association_reflection(assoc) || (raise Sequel::UndefinedAssociation, "Model: #{self}, Association: #{assoc}")}
3028
3052
 
3029
3053
  # Populate the key_hash entry for each association being eagerly loaded
3030
3054
  reflections.each do |r|
@@ -3120,6 +3144,10 @@ END
3120
3144
  end
3121
3145
  alias one_to_one_association_filter_expression one_to_many_association_filter_expression
3122
3146
 
3147
+ def non_sql_option?(key)
3148
+ super || key == :eager || key == :eager_graph
3149
+ end
3150
+
3123
3151
  # Build associations from the graph if #eager_graph was used,
3124
3152
  # and/or load other associations if #eager was used.
3125
3153
  def post_load(all_records)
@@ -7,16 +7,27 @@ module Sequel
7
7
 
8
8
  # Class methods for Sequel::Model that implement basic model functionality.
9
9
  #
10
- # * All of the method names in Model::DATASET_METHODS have class methods created that call
11
- # the Model's dataset with the method of the same name with the given arguments.
10
+ # * All of the following methods have class methods created that send the method
11
+ # to the model's dataset: all, as_hash, avg, count, cross_join, distinct, each,
12
+ # each_server, empty?, except, exclude, exclude_having, fetch_rows,
13
+ # filter, first, first!, for_update, from, from_self, full_join, full_outer_join,
14
+ # get, graph, grep, group, group_and_count, group_append, group_by, having, import,
15
+ # inner_join, insert, intersect, invert, join, join_table, last, left_join,
16
+ # left_outer_join, limit, lock_style, map, max, min, multi_insert, naked, natural_full_join,
17
+ # natural_join, natural_left_join, natural_right_join, offset, order, order_append, order_by,
18
+ # order_more, order_prepend, paged_each, qualify, reverse, reverse_order, right_join,
19
+ # right_outer_join, select, select_all, select_append, select_group, select_hash,
20
+ # select_hash_groups, select_map, select_more, select_order_map, server,
21
+ # single_record, single_record!, single_value, single_value!, sum, to_hash, to_hash_groups,
22
+ # truncate, unfiltered, ungraphed, ungrouped, union, unlimited, unordered, where, where_all,
23
+ # where_each, where_single_value, with, with_recursive, with_sql
12
24
  module ClassMethods
13
25
  # Which columns should be the only columns allowed in a call to a mass assignment method (e.g. set)
14
26
  # (default: not set, so all columns not otherwise restricted are allowed).
15
27
  attr_reader :allowed_columns # SEQUEL5: Deprecate after release
16
28
 
17
- # Whether to cache the anonymous models created by Sequel::Model(). This is
18
- # required for reloading them correctly (avoiding the superclass mismatch). True
19
- # by default for backwards compatibility.
29
+ # Whether to cache the anonymous models created by Sequel::Model(), true by default. This is
30
+ # required for reloading them correctly (avoiding the superclass mismatch).
20
31
  attr_accessor :cache_anonymous_models
21
32
 
22
33
  # Array of modules that extend this model's dataset. Stored
@@ -215,16 +226,20 @@ module Sequel
215
226
  end
216
227
 
217
228
  def initialize_copy(_)
218
- Sequel::Deprecation.deprecate("Model.clone", "Create a subclass of the model instead of cloning it.")
229
+ Sequel::Deprecation.deprecate("Model.clone", "Create a subclass of the model instead of cloning it")
219
230
  # raise(Error, "cannot dup/clone a Sequel::Model class") # SEQUEL5
220
231
  super
221
232
  end
222
233
  def dup
223
- Sequel::Deprecation.deprecate("Model.dup", "Create a subclass of the model instead of duping it.")
234
+ Sequel::Deprecation.deprecate("Model.dup", "Create a subclass of the model instead of duping it")
224
235
  # raise(Error, "cannot dup/clone a Sequel::Model class") # SEQUEL5
225
236
  super
226
237
  end
227
238
 
239
+ def <<(arg)
240
+ Sequel::Deprecation.deprecate("Sequel::Model.<<", "Switch to using #insert")
241
+ dataset << (arg)
242
+ end
228
243
 
229
244
  # Returns the first record from the database matching the conditions.
230
245
  # If a hash is given, it is used as the conditions. If another
@@ -661,7 +676,7 @@ module Sequel
661
676
  # end
662
677
  def inherited(subclass)
663
678
  super
664
- ivs = subclass.instance_variables.collect(&:to_s)
679
+ ivs = subclass.instance_variables.map(&:to_s)
665
680
  inherited_instance_variables.each do |iv, dup|
666
681
  next if ivs.include?(iv.to_s)
667
682
  if (sup_class_value = instance_variable_get(iv)) && dup
@@ -700,14 +715,14 @@ module Sequel
700
715
  pluralize(underscore(demodulize(name))).to_sym
701
716
  end
702
717
 
703
- # Calls #call with the values hash. Only for backwards compatibility.
718
+ # Calls #call with the values hash.
704
719
  def load(values)
705
720
  call(values)
706
721
  end
707
722
 
708
723
  # Clear the setter_methods cache when a setter method is added
709
724
  def method_added(meth)
710
- clear_setter_methods_cache if meth.to_s =~ SETTER_METHOD_REGEXP
725
+ clear_setter_methods_cache if meth.to_s.end_with?('=')
711
726
  super
712
727
  end
713
728
 
@@ -976,18 +991,26 @@ module Sequel
976
991
  end
977
992
 
978
993
  # Add model methods that call dataset methods
979
- Plugins.def_dataset_methods(self, DATASET_METHODS)
994
+ Plugins.def_dataset_methods(self, (Dataset::ACTION_METHODS + Dataset::QUERY_METHODS + [:each_server]) - [:<<, :and, :or, :[], :columns, :columns!, :delete, :update, :add_graph_aliases])
995
+ # SEQUEL5: add :set_graph_aliases to remove list and remove :and
980
996
 
981
997
  private
982
998
 
983
999
  # Yield to the passed block and swallow all errors other than DatabaseConnectionErrors.
984
- def check_non_connection_error
1000
+ def check_non_connection_error(do_raise=require_valid_table)
985
1001
  begin
986
1002
  db.transaction(:savepoint=>:only){yield}
987
1003
  rescue Sequel::DatabaseConnectionError
988
1004
  raise
989
1005
  rescue Sequel::Error
990
- raise if require_valid_table
1006
+ case do_raise
1007
+ when nil
1008
+ Sequel::Deprecation.deprecate("Setting a model class dataset to an invalid dataset", "Either use a valid dataset or set require_valid_table = false for the model class")
1009
+ when false
1010
+ # nothing
1011
+ else
1012
+ raise
1013
+ end
991
1014
  end
992
1015
  end
993
1016
 
@@ -1000,6 +1023,7 @@ module Sequel
1000
1023
  ds = db.from(ds)
1001
1024
  when Dataset
1002
1025
  if ds.joined_dataset?
1026
+ # raise Error, "Using a joined dataset as a model dataset is not support, use from_self on the dataset to wrap it in a subquery" # SEQUEL5
1003
1027
  Sequel::Deprecation.deprecate("Using a joined dataset as a Sequel::Model dataset", respond_to?(:cti_base_model) ? "Use the class_table_inheritance plugin :alias option in #{cti_base_model.inspect}" : "Call from_self on the dataset to wrap it in a subquery")
1004
1028
  end
1005
1029
 
@@ -1038,9 +1062,9 @@ module Sequel
1038
1062
  # use a string to define the method for speed. For other columns names, use a block.
1039
1063
  def def_column_accessor(*columns)
1040
1064
  clear_setter_methods_cache
1041
- columns, bad_columns = columns.partition{|x| NORMAL_METHOD_NAME_REGEXP.match(x.to_s)}
1065
+ columns, bad_columns = columns.partition{|x| /\A[A-Za-z_][A-Za-z0-9_]*\z/.match(x.to_s)}
1042
1066
  bad_columns.each{|x| def_bad_column_accessor(x)}
1043
- im = instance_methods.collect(&:to_s)
1067
+ im = instance_methods.map(&:to_s)
1044
1068
  columns.each do |column|
1045
1069
  meth = "#{column}="
1046
1070
  overridable_methods_module.module_eval("def #{column}; self[:#{column}] end", __FILE__, __LINE__) unless im.include?(column.to_s)
@@ -1054,7 +1078,7 @@ module Sequel
1054
1078
  def def_model_dataset_method(meth)
1055
1079
  return if respond_to?(meth, true)
1056
1080
 
1057
- if meth.to_s =~ NORMAL_METHOD_NAME_REGEXP
1081
+ if meth.to_s =~ /\A[A-Za-z_][A-Za-z0-9_]*\z/
1058
1082
  instance_eval("def #{meth}(*args, &block); dataset.#{meth}(*args, &block) end", __FILE__, __LINE__)
1059
1083
  else
1060
1084
  (class << self; self; end).send(:define_method, meth){|*args, &block| dataset.send(meth, *args, &block)}
@@ -1097,14 +1121,14 @@ module Sequel
1097
1121
  schema_hash = {}
1098
1122
  ds_opts = dataset.opts
1099
1123
  get_columns = proc{check_non_connection_error{columns} || []}
1100
- schema_array = check_non_connection_error{db.schema(dataset, :reload=>reload)} if db.supports_schema_parsing?
1124
+ schema_array = check_non_connection_error(false){db.schema(dataset, :reload=>reload)} if db.supports_schema_parsing?
1101
1125
  if schema_array
1102
1126
  schema_array.each{|k,v| schema_hash[k] = v}
1103
1127
 
1104
1128
  # Set the primary key(s) based on the schema information,
1105
1129
  # if the schema information includes primary key information
1106
1130
  if schema_array.all?{|k,v| v.has_key?(:primary_key)}
1107
- pks = schema_array.collect{|k,v| k if v[:primary_key]}.compact
1131
+ pks = schema_array.map{|k,v| k if v[:primary_key]}.compact
1108
1132
  pks.length > 0 ? set_primary_key(pks) : no_primary_key
1109
1133
  end
1110
1134
 
@@ -1119,7 +1143,7 @@ module Sequel
1119
1143
  # Dataset is for a single table with all columns,
1120
1144
  # so set the columns based on the order they were
1121
1145
  # returned by the schema.
1122
- cols = schema_array.collect{|k,v| k}
1146
+ cols = schema_array.map{|k,v| k}
1123
1147
  set_columns(cols)
1124
1148
  # Also set the columns for the dataset, so the dataset
1125
1149
  # doesn't have to do a query to get them.
@@ -1141,18 +1165,46 @@ module Sequel
1141
1165
  # SEQUEL5: Remove allowed_columns handling
1142
1166
  allowed_columns.map{|x| "#{x}="}
1143
1167
  else
1144
- meths = instance_methods.collect(&:to_s).grep(SETTER_METHOD_REGEXP) - RESTRICTED_SETTER_METHODS
1168
+ meths = instance_methods.map(&:to_s).select{|l| l.end_with?('=')} - RESTRICTED_SETTER_METHODS
1145
1169
  meths -= Array(primary_key).map{|x| "#{x}="} if primary_key && restrict_primary_key?
1146
1170
  meths
1147
1171
  end
1148
1172
  end
1149
1173
 
1150
1174
  # A hash of instance variables to automatically set up in subclasses.
1151
- # See Sequel::Model::INHERITED_INSTANCE_VARIABLES. It is safe to modify
1152
- # the hash returned by this method, though it may not be safe to modify
1153
- # values of the hash.
1175
+ # Keys are instance variable symbols, values should be:
1176
+ # nil :: Assign directly from superclass to subclass (frozen objects)
1177
+ # :dup :: Dup object when assigning from superclass to subclass (mutable objects)
1178
+ # :hash_dup :: Assign hash with same keys, but dup all the values
1179
+ # Proc :: Call with subclass to do the assignment
1154
1180
  def inherited_instance_variables
1155
- INHERITED_INSTANCE_VARIABLES.dup
1181
+ {
1182
+ :@allowed_columns=>:dup, # SEQUEL5: Remove
1183
+ :@cache_anonymous_models=>nil,
1184
+ :@dataset_method_modules=>:dup,
1185
+ :@dataset_module_class=>nil,
1186
+ :@db=>nil,
1187
+ :@default_set_fields_options=>:dup,
1188
+ :@fast_instance_delete_sql=>nil,
1189
+ :@fast_pk_lookup_sql=>nil,
1190
+ :@finder_loaders=>:dup, # SEQUEL5: Remove
1191
+ :@finders=>:dup, # SEQUEL5: Remove
1192
+ :@plugins=>:dup,
1193
+ :@primary_key=>nil,
1194
+ :@raise_on_save_failure=>nil,
1195
+ :@raise_on_typecast_failure=>nil,
1196
+ :@require_modification=>nil,
1197
+ :@require_valid_table=>nil,
1198
+ :@restrict_primary_key=>nil,
1199
+ :@setter_methods=>nil,
1200
+ :@simple_pk=>nil,
1201
+ :@simple_table=>nil,
1202
+ :@strict_param_setting=>nil,
1203
+ :@typecast_empty_string_to_nil=>nil,
1204
+ :@typecast_on_assignment=>nil,
1205
+ :@use_after_commit_rollback=>nil,
1206
+ :@use_transactions=>nil
1207
+ }
1156
1208
  end
1157
1209
 
1158
1210
  # For the given opts hash and default name or :class option, add a
@@ -1196,6 +1248,7 @@ module Sequel
1196
1248
  rescue LoadError => e
1197
1249
  begin
1198
1250
  require "sequel_#{plugin}"
1251
+ Sequel::Deprecation.deprecate("requiring 'sequel_#{plugin}' to load a plugin", "Update the #{plugin} plugin to be required via 'sequel/plugins/#{plugin}'")
1199
1252
  rescue LoadError => e2
1200
1253
  e.message << "; #{e2.message}"
1201
1254
  raise e
@@ -1249,6 +1302,7 @@ module Sequel
1249
1302
  ds.fetch_rows(sql){|r| return ds.row_proc.call(r)}
1250
1303
  nil
1251
1304
  elsif dataset.joined_dataset?
1305
+ # SEQUEL5: Remove as joined model datasets are not allowed
1252
1306
  dataset.first(qualified_primary_key_hash(pk))
1253
1307
  else
1254
1308
  dataset.first(primary_key_hash(pk))
@@ -1311,19 +1365,21 @@ module Sequel
1311
1365
 
1312
1366
  # Sequel::Model instance methods that implement basic model functionality.
1313
1367
  #
1314
- # * All of the methods in +HOOKS+ and +AROUND_HOOKS+ create instance methods that are called
1368
+ # * All of the model before/after/around hooks are implemented as instance methods that are called
1315
1369
  # by Sequel when the appropriate action occurs. For example, when destroying
1316
1370
  # a model object, Sequel will call +around_destroy+, which will call +before_destroy+, do
1317
1371
  # the destroy, and then call +after_destroy+.
1318
1372
  # * The following instance_methods all call the class method of the same
1319
1373
  # name: columns, db, primary_key, db_schema.
1320
- # * All of the methods in +BOOLEAN_SETTINGS+ create attr_writers allowing you
1321
- # to set values for the attribute. It also creates instance getters returning
1322
- # the value of the setting. If the value has not yet been set, it
1323
- # gets the default value from the class by calling the class method of the same name.
1374
+ # * The following accessor methods are defined via metaprogramming:
1375
+ # raise_on_save_failure, raise_on_typecast_failure, require_modification,
1376
+ # strict_param_setting, typecast_empty_string_to_nil, typecast_on_assignment,
1377
+ # and use_transactions. The setter methods will change the setting for the
1378
+ # instance, and the getter methods will check for an instance setting, then
1379
+ # try the class setting if no instance setting has been set.
1324
1380
  module InstanceMethods
1325
1381
  HOOKS.each{|h| class_eval("def #{h}; end", __FILE__, __LINE__)}
1326
- AROUND_HOOKS.each{|h| class_eval("def #{h}; yield end", __FILE__, __LINE__)}
1382
+ [:around_create, :around_update, :around_save, :around_destroy, :around_validation].each{|h| class_eval("def #{h}; yield end", __FILE__, __LINE__)}
1327
1383
 
1328
1384
  # Define instance method(s) that calls class method(s) of the
1329
1385
  # same name. Replaces the construct:
@@ -1334,8 +1390,13 @@ module Sequel
1334
1390
  # Define instance method(s) that calls class method(s) of the
1335
1391
  # same name, caching the result in an instance variable. Define
1336
1392
  # standard attr_writer method for modifying that instance variable.
1337
- BOOLEAN_SETTINGS.each{|meth| class_eval("def #{meth}; !defined?(@#{meth}) ? (frozen? ? self.class.#{meth} : (@#{meth} = self.class.#{meth})) : @#{meth} end", __FILE__, __LINE__)}
1338
- attr_writer(*BOOLEAN_SETTINGS)
1393
+ [:typecast_empty_string_to_nil, :typecast_on_assignment, :strict_param_setting, \
1394
+ :raise_on_save_failure, :raise_on_typecast_failure, :require_modification, :use_transactions,
1395
+ :use_after_commit_rollback # SEQUEL5: Remove
1396
+ ].each do |meth|
1397
+ class_eval("def #{meth}; !defined?(@#{meth}) ? (frozen? ? self.class.#{meth} : (@#{meth} = self.class.#{meth})) : @#{meth} end", __FILE__, __LINE__)
1398
+ attr_writer(meth)
1399
+ end
1339
1400
 
1340
1401
  # The hash of attribute values. Keys are symbols with the names of the
1341
1402
  # underlying database columns. The returned hash is a reference to the
@@ -1882,7 +1943,7 @@ module Sequel
1882
1943
 
1883
1944
  # Clear the setter_methods cache when a method is added
1884
1945
  def singleton_method_added(meth)
1885
- @singleton_setter_added = true if meth.to_s =~ SETTER_METHOD_REGEXP
1946
+ @singleton_setter_added = true if meth.to_s.end_with?('=')
1886
1947
  super
1887
1948
  end
1888
1949
 
@@ -1895,6 +1956,7 @@ module Sequel
1895
1956
  raise Error, "No dataset for model #{model}" unless ds = model.instance_dataset
1896
1957
 
1897
1958
  cond = if ds.joined_dataset?
1959
+ # SEQUEL5: Remove as joined model datasets are now allowed
1898
1960
  qualified_pk_hash
1899
1961
  else
1900
1962
  pk_hash
@@ -2136,7 +2198,7 @@ module Sequel
2136
2198
  sh = {:server=>this_server}
2137
2199
  uacr = use_after_commit_rollback
2138
2200
  if uacr.nil? ? (method(:after_rollback).owner != InstanceMethods) : uacr
2139
- Sequel::Deprecation.deprecate("Model#after_rollback", "Instead, call db.after_rollback in Model#before_save.")
2201
+ Sequel::Deprecation.deprecate("Model#after_rollback", "Instead, call db.after_rollback in Model#before_save")
2140
2202
  db.after_rollback(sh){after_rollback}
2141
2203
  end
2142
2204
  pk = nil
@@ -2203,7 +2265,7 @@ module Sequel
2203
2265
  raise_hook_failure(:around_save) unless called_save
2204
2266
  _after_save(pk) # SEQUEL5: Remove
2205
2267
  if uacr.nil? ? (method(:after_commit).owner != InstanceMethods) : uacr
2206
- Sequel::Deprecation.deprecate("Model#after_commit", "Instead, call db.after_commit in Model#after_save.")
2268
+ Sequel::Deprecation.deprecate("Model#after_commit", "Instead, call db.after_commit in Model#after_save")
2207
2269
  db.after_commit(sh){after_commit}
2208
2270
  end
2209
2271
  self
@@ -2436,7 +2498,7 @@ module Sequel
2436
2498
  if type.is_a?(Array)
2437
2499
  type.map{|x| "#{x}="}
2438
2500
  else
2439
- meths = methods.collect(&:to_s).grep(SETTER_METHOD_REGEXP) - RESTRICTED_SETTER_METHODS
2501
+ meths = methods.map(&:to_s).select{|l| l.end_with?('=')} - RESTRICTED_SETTER_METHODS
2440
2502
  meths -= Array(primary_key).map{|x| "#{x}="} if type != :all && primary_key && model.restrict_primary_key?
2441
2503
  meths
2442
2504
  end
@@ -2600,15 +2662,15 @@ module Sequel
2600
2662
  end
2601
2663
  end
2602
2664
 
2603
- # This allows you to call +to_hash+ without any arguments, which will
2665
+ # This allows you to call +as_hash+ without any arguments, which will
2604
2666
  # result in a hash with the primary key value being the key and the
2605
2667
  # model object being the value.
2606
2668
  #
2607
- # Artist.dataset.to_hash # SELECT * FROM artists
2669
+ # Artist.dataset.as_hash # SELECT * FROM artists
2608
2670
  # # => {1=>#<Artist {:id=>1, ...}>,
2609
2671
  # # 2=>#<Artist {:id=>2, ...}>,
2610
2672
  # # ...}
2611
- def to_hash(key_column=nil, value_column=nil, opts=OPTS)
2673
+ def as_hash(key_column=nil, value_column=nil, opts=OPTS)
2612
2674
  if key_column
2613
2675
  super
2614
2676
  else
@@ -2617,50 +2679,9 @@ module Sequel
2617
2679
  end
2618
2680
  end
2619
2681
 
2620
- # Return an array of all rows matching the given filter condition, also
2621
- # yielding each row to the given block. Basically the same as where(cond).all(&block),
2622
- # except it can be optimized to not create an intermediate dataset.
2623
- #
2624
- # Artist.where_all(:id=>[1,2,3])
2625
- # # SELECT * FROM artists WHERE (id IN (1, 2, 3))
2626
- def where_all(cond, &block)
2627
- if loader = _model_where_loader
2628
- loader.all(filter_expr(cond), &block)
2629
- else
2630
- where(cond).all(&block)
2631
- end
2632
- end
2633
-
2634
- # Iterate over all rows matching the given filter condition,
2635
- # yielding each row to the given block. Basically the same as where(cond).each(&block),
2636
- # except it can be optimized to not create an intermediate dataset.
2637
- #
2638
- # Artist.where_each(:id=>[1,2,3]){|row| p row}
2639
- # # SELECT * FROM artists WHERE (id IN (1, 2, 3))
2640
- def where_each(cond, &block)
2641
- if loader = _model_where_loader
2642
- loader.each(filter_expr(cond), &block)
2643
- else
2644
- where(cond).each(&block)
2645
- end
2646
- end
2647
-
2648
- # Filter the datasets using the given filter condition, then return a single value.
2649
- # This assumes that the dataset has already been setup to limit the selection to
2650
- # a single column. Basically the same as where(cond).single_value,
2651
- # except it can be optimized to not create an intermediate dataset.
2652
- #
2653
- # Artist.select(:name).where_single_value(:id=>1)
2654
- # # SELECT name FROM artists WHERE (id = 1) LIMIT 1
2655
- def where_single_value(cond)
2656
- if loader = cached_placeholder_literalizer(:_model_where_single_value_loader) do |pl|
2657
- single_value_ds.where(pl.arg)
2658
- end
2659
-
2660
- loader.get(filter_expr(cond))
2661
- else
2662
- where(cond).single_value
2663
- end
2682
+ # Alias of as_hash for backwards compatibility.
2683
+ def to_hash(*a)
2684
+ as_hash(*a)
2664
2685
  end
2665
2686
 
2666
2687
  # Given a primary key value, return the first record in the dataset with that primary key
@@ -2689,11 +2710,12 @@ module Sequel
2689
2710
 
2690
2711
  private
2691
2712
 
2692
- # Loader used for where_all and where_each.
2713
+ # SEQUEL5: Remove
2693
2714
  def _model_where_loader
2694
- cached_placeholder_literalizer(:_model_where_loader) do |pl|
2695
- where(pl.arg)
2696
- end
2715
+ # :nocov:
2716
+ Sequel::Deprecation.deprecate("Dataset#_model_where_loader", "Use _where_loader instead")
2717
+ _where_loader
2718
+ # :nocov:
2697
2719
  end
2698
2720
 
2699
2721
  # If the dataset is not already ordered, and the model has a primary key,
@@ -2720,6 +2742,10 @@ module Sequel
2720
2742
  where(cond).limit(1)
2721
2743
  end
2722
2744
  end
2745
+
2746
+ def non_sql_option?(key)
2747
+ super || key == :model
2748
+ end
2723
2749
  end
2724
2750
 
2725
2751
  extend ClassMethods
@@ -3,12 +3,11 @@
3
3
  module Sequel
4
4
  class Model
5
5
  # This Module subclass is used by Model.dataset_module
6
- # to add dataset methods to classes. It adds a couple
7
- # of features standard Modules, allowing you to use
8
- # the same subset method you can call on Model, as well
9
- # as making sure that public methods added to the module
10
- # automatically have class methods created for them.
11
- class DatasetModule < ::Module
6
+ # to add dataset methods to classes. In addition to the
7
+ # methods offered by Dataset::DatasetModule, it also
8
+ # automatically creates class methods for public dataset
9
+ # methods.
10
+ class DatasetModule < Dataset::DatasetModule
12
11
  # Store the model related to this dataset module.
13
12
  def initialize(model)
14
13
  @model = model
@@ -19,43 +18,6 @@ module Sequel
19
18
  where(name, *args, &block)
20
19
  end
21
20
 
22
- %w'where exclude exclude_having having'.map(&:to_sym).each do |meth|
23
- define_method(meth) do |name, *args, &block|
24
- if block || args.flatten.any?{|arg| arg.is_a?(Proc)}
25
- define_method(name){send(meth, *args, &block)}
26
- else
27
- key = :"_#{meth}_#{name}_ds"
28
- define_method(name) do
29
- cached_dataset(key){send(meth, *args)}
30
- end
31
- end
32
- end
33
- end
34
-
35
- meths = (<<-METHS).split.map(&:to_sym)
36
- distinct grep group group_and_count group_append
37
- limit offset order order_append order_prepend
38
- select select_all select_append select_group server
39
- METHS
40
-
41
- # Define a method in the module
42
- def self.def_dataset_caching_method(mod, meth)
43
- mod.send(:define_method, meth) do |name, *args, &block|
44
- if block
45
- define_method(name){send(meth, *args, &block)}
46
- else
47
- key = :"_#{meth}_#{name}_ds"
48
- define_method(name) do
49
- cached_dataset(key){send(meth, *args)}
50
- end
51
- end
52
- end
53
- end
54
-
55
- meths.each do |meth|
56
- def_dataset_caching_method(self, meth)
57
- end
58
-
59
21
  private
60
22
 
61
23
  # Add a class method to the related model that
@@ -6,6 +6,7 @@ module Sequel
6
6
  # with a few convenience methods.
7
7
  class Errors < ::Hash
8
8
  ATTRIBUTE_JOINER = ' and '.freeze
9
+ Sequel::Deprecation.deprecate_constant(self, :ATTRIBUTE_JOINER)
9
10
 
10
11
  # Adds an error for the given attribute.
11
12
  #
@@ -40,7 +41,7 @@ module Sequel
40
41
  def full_messages
41
42
  inject([]) do |m, kv|
42
43
  att, errors = *kv
43
- errors.each {|e| m << (e.is_a?(LiteralString) ? e : "#{Array(att).join(ATTRIBUTE_JOINER)} #{e}")}
44
+ errors.each {|e| m << (e.is_a?(LiteralString) ? e : "#{Array(att).join(' and ')} #{e}")}
44
45
  m
45
46
  end
46
47
  end