sequel 4.46.0 → 4.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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