sequel 5.59.0 → 5.60.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +10 -0
  3. data/README.rdoc +1 -1
  4. data/bin/sequel +11 -3
  5. data/doc/release_notes/5.60.0.txt +22 -0
  6. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
  7. data/lib/sequel/adapters/jdbc.rb +5 -5
  8. data/lib/sequel/adapters/mock.rb +1 -1
  9. data/lib/sequel/adapters/mysql.rb +3 -3
  10. data/lib/sequel/adapters/oracle.rb +1 -1
  11. data/lib/sequel/adapters/postgres.rb +46 -11
  12. data/lib/sequel/adapters/shared/mssql.rb +1 -1
  13. data/lib/sequel/adapters/shared/oracle.rb +1 -1
  14. data/lib/sequel/adapters/shared/postgres.rb +26 -14
  15. data/lib/sequel/adapters/shared/sqlite.rb +1 -1
  16. data/lib/sequel/adapters/sqlite.rb +1 -1
  17. data/lib/sequel/ast_transformer.rb +1 -1
  18. data/lib/sequel/database/misc.rb +2 -2
  19. data/lib/sequel/dataset/sql.rb +2 -2
  20. data/lib/sequel/extensions/date_arithmetic.rb +35 -7
  21. data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
  22. data/lib/sequel/extensions/is_distinct_from.rb +3 -1
  23. data/lib/sequel/extensions/pg_array.rb +2 -2
  24. data/lib/sequel/extensions/pg_array_ops.rb +1 -1
  25. data/lib/sequel/extensions/pg_enum.rb +1 -1
  26. data/lib/sequel/extensions/pg_hstore_ops.rb +3 -3
  27. data/lib/sequel/extensions/pg_inet.rb +2 -2
  28. data/lib/sequel/extensions/pg_interval.rb +1 -1
  29. data/lib/sequel/extensions/pg_json.rb +1 -1
  30. data/lib/sequel/extensions/pg_json_ops.rb +3 -3
  31. data/lib/sequel/extensions/pg_multirange.rb +2 -2
  32. data/lib/sequel/extensions/pg_range.rb +2 -2
  33. data/lib/sequel/extensions/pg_row.rb +2 -2
  34. data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
  35. data/lib/sequel/extensions/symbol_aref.rb +2 -0
  36. data/lib/sequel/model/associations.rb +6 -6
  37. data/lib/sequel/model/base.rb +3 -3
  38. data/lib/sequel/model/exceptions.rb +1 -1
  39. data/lib/sequel/model/inflections.rb +6 -6
  40. data/lib/sequel/plugins/auto_validations.rb +1 -1
  41. data/lib/sequel/plugins/defaults_setter.rb +1 -1
  42. data/lib/sequel/plugins/dirty.rb +1 -1
  43. data/lib/sequel/plugins/insert_conflict.rb +1 -1
  44. data/lib/sequel/plugins/json_serializer.rb +1 -1
  45. data/lib/sequel/plugins/nested_attributes.rb +1 -1
  46. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +1 -1
  47. data/lib/sequel/plugins/serialization.rb +1 -1
  48. data/lib/sequel/plugins/sharding.rb +1 -1
  49. data/lib/sequel/plugins/sql_comments.rb +4 -4
  50. data/lib/sequel/plugins/subclasses.rb +1 -1
  51. data/lib/sequel/plugins/validation_class_methods.rb +3 -3
  52. data/lib/sequel/plugins/validation_helpers.rb +1 -1
  53. data/lib/sequel/sql.rb +1 -1
  54. data/lib/sequel/version.rb +1 -1
  55. metadata +4 -2
@@ -32,6 +32,10 @@
32
32
  #
33
33
  # DB[:table].select(add.as(:d)).where(sub > Sequel::CURRENT_TIMESTAMP)
34
34
  #
35
+ # On most databases, the values you provide for years/months/days/etc. must
36
+ # be numeric values and not arbitrary SQL expressions. However, on PostgreSQL
37
+ # 9.4+, use of arbitrary SQL expressions is supported.
38
+ #
35
39
  # Related module: Sequel::SQL::DateAdd
36
40
 
37
41
  #
@@ -54,7 +58,16 @@ module Sequel
54
58
  interval = interval.parts
55
59
  end
56
60
  parts = {}
57
- interval.each{|k,v| parts[k] = -v unless v.nil?}
61
+ interval.each do |k,v|
62
+ case v
63
+ when nil
64
+ # ignore
65
+ when Numeric
66
+ parts[k] = -v
67
+ else
68
+ parts[k] = Sequel::SQL::NumericExpression.new(:*, v, -1)
69
+ end
70
+ end
58
71
  DateAdd.new(expr, parts, opts)
59
72
  end
60
73
  end
@@ -68,6 +81,7 @@ module Sequel
68
81
  module DatasetMethods
69
82
  DURATION_UNITS = [:years, :months, :days, :hours, :minutes, :seconds].freeze
70
83
  DEF_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| s.to_s.freeze}).freeze
84
+ POSTGRES_DURATION_UNITS = DURATION_UNITS.zip([:years, :months, :days, :hours, :mins, :secs].map{|s| s.to_s.freeze}).freeze
71
85
  MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1]).freeze}).freeze
72
86
  MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1]).freeze}).freeze
73
87
  H2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| s.to_s[0...-1].freeze}).freeze
@@ -87,14 +101,28 @@ module Sequel
87
101
 
88
102
  cast = case db_type = db.database_type
89
103
  when :postgres
90
- interval = String.new
91
- each_valid_interval_unit(h, DEF_DURATION_UNITS) do |value, sql_unit|
92
- interval << "#{value} #{sql_unit} "
104
+ casted = Sequel.cast(expr, cast_type)
105
+
106
+ if db.server_version >= 90400
107
+ placeholder = []
108
+ vals = []
109
+ each_valid_interval_unit(h, POSTGRES_DURATION_UNITS) do |value, sql_unit|
110
+ placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := "
111
+ vals << value
112
+ end
113
+ interval = Sequel.function(:make_interval, Sequel.lit(placeholder, *vals)) unless vals.empty?
114
+ else
115
+ parts = String.new
116
+ each_valid_interval_unit(h, DEF_DURATION_UNITS) do |value, sql_unit|
117
+ parts << "#{value} #{sql_unit} "
118
+ end
119
+ interval = Sequel.cast(parts, :interval) unless parts.empty?
93
120
  end
94
- if interval.empty?
95
- return literal_append(sql, Sequel.cast(expr, cast_type))
121
+
122
+ if interval
123
+ return complex_expression_sql_append(sql, :+, [casted, interval])
96
124
  else
97
- return complex_expression_sql_append(sql, :+, [Sequel.cast(expr, cast_type), Sequel.cast(interval, :interval)])
125
+ return literal_append(sql, casted)
98
126
  end
99
127
  when :sqlite
100
128
  args = [expr]
@@ -77,7 +77,7 @@ module Sequel
77
77
  def duplicate_columns_handler_type(cols)
78
78
  handler = opts.fetch(:on_duplicate_columns){db.opts.fetch(:on_duplicate_columns, :warn)}
79
79
 
80
- if handler.respond_to?(:call)
80
+ if defined?(handler.call)
81
81
  handler.call(cols)
82
82
  else
83
83
  handler
@@ -3,7 +3,7 @@
3
3
  # The is_distinct_from extension adds the ability to use the
4
4
  # SQL standard IS DISTINCT FROM operator, which is similar to the
5
5
  # not equals operator, except that NULL values are considered
6
- # equal. Only PostgreSQL and H2 currently support this operator. On
6
+ # equal. PostgreSQL, SQLite 3.39+, and H2 currently support this operator. On
7
7
  # other databases, support is emulated.
8
8
  #
9
9
  # First, you need to load the extension into the database:
@@ -90,6 +90,8 @@ module Sequel
90
90
  case db.database_type
91
91
  when :postgres, :h2
92
92
  true
93
+ when :sqlite
94
+ db.sqlite_version >= 33900
93
95
  else
94
96
  false
95
97
  end
@@ -301,7 +301,7 @@ module Sequel
301
301
  end
302
302
  end
303
303
 
304
- unless Sequel::Postgres.respond_to?(:parse_pg_array)
304
+ unless defined?(Sequel::Postgres.parse_pg_array)
305
305
  require 'strscan'
306
306
 
307
307
  # PostgreSQL array parser that handles PostgreSQL array output format.
@@ -412,7 +412,7 @@ module Sequel
412
412
  @converter = converter
413
413
  end
414
414
 
415
- if Sequel::Postgres.respond_to?(:parse_pg_array)
415
+ if defined?(Sequel::Postgres.parse_pg_array)
416
416
  # :nocov:
417
417
  # Use sequel_pg's C-based parser if it has already been defined.
418
418
  def call(string)
@@ -158,7 +158,7 @@ module Sequel
158
158
  Sequel.function(:hstore, self, wrap_array(arg))
159
159
  end
160
160
  # :nocov:
161
- if Sequel.respond_to?(:hstore_op)
161
+ if defined?(Sequel.hstore_op)
162
162
  # :nocov:
163
163
  v = Sequel.hstore_op(v)
164
164
  end
@@ -144,7 +144,7 @@ module Sequel
144
144
  select_hash_groups(Sequel.cast(:enumtypid, Integer).as(:v), :enumlabel).freeze
145
145
  enum_labels.each_value(&:freeze)
146
146
 
147
- if respond_to?(:register_array_type)
147
+ if defined?(register_array_type)
148
148
  array_types = metadata_dataset.
149
149
  from(:pg_type).
150
150
  where(:oid=>enum_labels.keys).
@@ -296,7 +296,7 @@ module Sequel
296
296
 
297
297
  # Wrap argument in a PGArray if it is an array
298
298
  def wrap_input_array(obj)
299
- if obj.is_a?(Array) && Sequel.respond_to?(:pg_array)
299
+ if obj.is_a?(Array) && defined?(Sequel.pg_array)
300
300
  Sequel.pg_array(obj)
301
301
  else
302
302
  obj
@@ -305,7 +305,7 @@ module Sequel
305
305
 
306
306
  # Wrap argument in an Hstore if it is a hash
307
307
  def wrap_input_hash(obj)
308
- if obj.is_a?(Hash) && Sequel.respond_to?(:hstore)
308
+ if obj.is_a?(Hash) && defined?(Sequel.hstore)
309
309
  Sequel.hstore(obj)
310
310
  else
311
311
  obj
@@ -314,7 +314,7 @@ module Sequel
314
314
 
315
315
  # Wrap argument in a PGArrayOp if supported
316
316
  def wrap_output_array(obj)
317
- if Sequel.respond_to?(:pg_array_op)
317
+ if defined?(Sequel.pg_array_op)
318
318
  Sequel.pg_array_op(obj)
319
319
  else
320
320
  obj
@@ -49,13 +49,13 @@ module Sequel
49
49
  meth = IPAddr.method(:new)
50
50
  add_conversion_proc(869, meth)
51
51
  add_conversion_proc(650, meth)
52
- if respond_to?(:register_array_type)
52
+ if defined?(register_array_type)
53
53
  register_array_type('inet', :oid=>1041, :scalar_oid=>869)
54
54
  register_array_type('cidr', :oid=>651, :scalar_oid=>650)
55
55
  end
56
56
  end
57
57
 
58
- if respond_to?(:register_array_type)
58
+ if defined?(register_array_type)
59
59
  register_array_type('macaddr', :oid=>1040, :scalar_oid=>829)
60
60
  end
61
61
  @schema_type_classes[:ipaddr] = IPAddr
@@ -144,7 +144,7 @@ module Sequel
144
144
  db.instance_exec do
145
145
  extend_datasets(IntervalDatasetMethods)
146
146
  add_conversion_proc(1186, Postgres::IntervalDatabaseMethods::PARSER)
147
- if respond_to?(:register_array_type)
147
+ if defined?(register_array_type)
148
148
  register_array_type('interval', :oid=>1187, :scalar_oid=>1186)
149
149
  end
150
150
  @schema_type_classes[:interval] = ActiveSupport::Duration
@@ -227,7 +227,7 @@ module Sequel
227
227
  db.instance_exec do
228
228
  add_conversion_proc(114, method(:_db_parse_json))
229
229
  add_conversion_proc(3802, method(:_db_parse_jsonb))
230
- if respond_to?(:register_array_type)
230
+ if defined?(register_array_type)
231
231
  register_array_type('json', :oid=>199, :scalar_oid=>114)
232
232
  register_array_type('jsonb', :oid=>3807, :scalar_oid=>3802)
233
233
  end
@@ -358,7 +358,7 @@ module Sequel
358
358
  # Automatically wrap argument in a PGArray if it is a plain Array.
359
359
  # Requires that the pg_array extension has been loaded to work.
360
360
  def wrap_array(arg)
361
- if arg.instance_of?(Array) && Sequel.respond_to?(:pg_array)
361
+ if arg.instance_of?(Array) && defined?(Sequel.pg_array)
362
362
  Sequel.pg_array(arg)
363
363
  else
364
364
  arg
@@ -652,7 +652,7 @@ module Sequel
652
652
 
653
653
  # Wrap argument in a PGArray if it is an array
654
654
  def wrap_input_array(obj)
655
- if obj.is_a?(Array) && Sequel.respond_to?(:pg_array)
655
+ if obj.is_a?(Array) && defined?(Sequel.pg_array)
656
656
  Sequel.pg_array(obj)
657
657
  else
658
658
  obj
@@ -661,7 +661,7 @@ module Sequel
661
661
 
662
662
  # Wrap argument in a JSONBArray or JSONBHash if it is an array or hash.
663
663
  def wrap_input_jsonb(obj)
664
- if Sequel.respond_to?(:pg_jsonb) && (obj.is_a?(Array) || obj.is_a?(Hash))
664
+ if defined?(Sequel.pg_jsonb) && (obj.is_a?(Array) || obj.is_a?(Hash))
665
665
  Sequel.pg_jsonb(obj)
666
666
  else
667
667
  obj
@@ -124,7 +124,7 @@ module Sequel
124
124
  register_multirange_type('datemultirange', :range_oid=>3912, :oid=>4535)
125
125
  register_multirange_type('int8multirange', :range_oid=>3926, :oid=>4536)
126
126
 
127
- if respond_to?(:register_array_type)
127
+ if defined?(register_array_type)
128
128
  register_array_type('int4multirange', :oid=>6150, :scalar_oid=>4451, :scalar_typecast=>:int4multirange)
129
129
  register_array_type('nummultirange', :oid=>6151, :scalar_oid=>4532, :scalar_typecast=>:nummultirange)
130
130
  register_array_type('tsmultirange', :oid=>6152, :scalar_oid=>4533, :scalar_typecast=>:tsmultirange)
@@ -141,7 +141,7 @@ module Sequel
141
141
  add_conversion_proc(4533, PGMultiRange::Creator.new("tsmultirange", procs[3908]))
142
142
  add_conversion_proc(4534, PGMultiRange::Creator.new("tstzmultirange", procs[3910]))
143
143
 
144
- if respond_to?(:register_array_type) && defined?(PGArray::Creator)
144
+ if defined?(register_array_type) && defined?(PGArray::Creator)
145
145
  add_conversion_proc(6152, PGArray::Creator.new("tsmultirange", procs[4533]))
146
146
  add_conversion_proc(6153, PGArray::Creator.new("tstzmultirange", procs[4534]))
147
147
  end
@@ -139,7 +139,7 @@ module Sequel
139
139
  register_range_type('tstzrange', :oid=>3910, :subtype_oid=>1184)
140
140
  register_range_type('daterange', :oid=>3912, :subtype_oid=>1082)
141
141
  register_range_type('int8range', :oid=>3926, :subtype_oid=>20)
142
- if respond_to?(:register_array_type)
142
+ if defined?(register_array_type)
143
143
  register_array_type('int4range', :oid=>3905, :scalar_oid=>3904, :scalar_typecast=>:int4range)
144
144
  register_array_type('numrange', :oid=>3907, :scalar_oid=>3906, :scalar_typecast=>:numrange)
145
145
  register_array_type('tsrange', :oid=>3909, :scalar_oid=>3908, :scalar_typecast=>:tsrange)
@@ -154,7 +154,7 @@ module Sequel
154
154
  procs = conversion_procs
155
155
  add_conversion_proc(3908, Parser.new("tsrange", procs[1114]))
156
156
  add_conversion_proc(3910, Parser.new("tstzrange", procs[1184]))
157
- if respond_to?(:register_array_type) && defined?(PGArray::Creator)
157
+ if defined?(register_array_type) && defined?(PGArray::Creator)
158
158
  add_conversion_proc(3909, PGArray::Creator.new("tsrange", procs[3908]))
159
159
  add_conversion_proc(3911, PGArray::Creator.new("tstzrange", procs[3910]))
160
160
  end
@@ -375,7 +375,7 @@ module Sequel
375
375
  @row_schema_types = {}
376
376
  extend(@row_type_method_module = Module.new)
377
377
  add_conversion_proc(2249, PGRow::Parser.new(:converter=>PGRow::ArrayRow))
378
- if respond_to?(:register_array_type)
378
+ if defined?(register_array_type)
379
379
  register_array_type('record', :oid=>2287, :scalar_oid=>2249)
380
380
  end
381
381
  end
@@ -464,7 +464,7 @@ module Sequel
464
464
  parser = Parser.new(parser_opts)
465
465
  add_conversion_proc(parser.oid, parser)
466
466
 
467
- if respond_to?(:register_array_type) && array_oid && array_oid > 0
467
+ if defined?(register_array_type) && array_oid && array_oid > 0
468
468
  array_type_name = if type_schema
469
469
  "#{type_schema}.#{type_name}"
470
470
  else
@@ -115,13 +115,13 @@ SQL
115
115
  # :before_thread_exit :: An object that responds to +call+ that is called before the
116
116
  # the created thread exits.
117
117
  def listen_for_static_cache_updates(models, opts=OPTS)
118
- raise Error, "this database object does not respond to listen, use the postgres adapter with the pg driver" unless respond_to?(:listen)
118
+ raise Error, "this database object does not respond to listen, use the postgres adapter with the pg driver" unless defined?(listen)
119
119
  models = [models] unless models.is_a?(Array)
120
120
  raise Error, "array of models to listen for changes cannot be empty" if models.empty?
121
121
 
122
122
  oid_map = {}
123
123
  models.each do |model|
124
- raise Error, "#{model.inspect} does not use the static_cache plugin" unless model.respond_to?(:load_cache)
124
+ raise Error, "#{model.inspect} does not use the static_cache plugin" unless defined?(model.load_cache)
125
125
  oid_map[get(regclass_oid(model.dataset.first_source_table))] = model
126
126
  end
127
127
 
@@ -35,6 +35,7 @@ if RUBY_VERSION >= '2.0'
35
35
  class Symbol
36
36
  prepend Sequel::SymbolAref
37
37
  end
38
+ # :nocov:
38
39
  else
39
40
  class Symbol
40
41
  if method_defined?(:[])
@@ -51,3 +52,4 @@ else
51
52
  end
52
53
  end
53
54
  end
55
+ # :nocov:
@@ -3016,7 +3016,7 @@ module Sequel
3016
3016
  def complex_expression_sql_append(sql, op, args)
3017
3017
  r = args[1]
3018
3018
  if (((op == :'=' || op == :'!=') && r.is_a?(Sequel::Model)) ||
3019
- (multiple = ((op == :IN || op == :'NOT IN') && ((is_ds = r.is_a?(Sequel::Dataset)) || (r.respond_to?(:all?) && r.all?{|x| x.is_a?(Sequel::Model)})))))
3019
+ (multiple = ((op == :IN || op == :'NOT IN') && ((is_ds = r.is_a?(Sequel::Dataset)) || (defined?(r.all?) && r.all?{|x| x.is_a?(Sequel::Model)})))))
3020
3020
  l = args[0]
3021
3021
  if ar = model.association_reflections[l]
3022
3022
  raise Error, "filtering by associations is not allowed for #{ar.inspect}" if ar[:allow_filtering_by] == false
@@ -3024,7 +3024,7 @@ module Sequel
3024
3024
  if multiple
3025
3025
  klass = ar.associated_class
3026
3026
  if is_ds
3027
- if r.respond_to?(:model)
3027
+ if defined?(r.model)
3028
3028
  unless r.model <= klass
3029
3029
  # A dataset for a different model class, could be a valid regular query
3030
3030
  return super
@@ -3356,10 +3356,10 @@ module Sequel
3356
3356
  assoc_table_alias = ds.unused_table_alias(alias_base)
3357
3357
  loader = r[:eager_grapher]
3358
3358
  if !associations.empty?
3359
- if associations.first.respond_to?(:call)
3359
+ if defined?(associations.first.call)
3360
3360
  callback = associations.first
3361
3361
  associations = {}
3362
- elsif associations.length == 1 && (assocs = associations.first).is_a?(Hash) && assocs.length == 1 && (pr_assoc = assocs.to_a.first) && pr_assoc.first.respond_to?(:call)
3362
+ elsif associations.length == 1 && (assocs = associations.first).is_a?(Hash) && assocs.length == 1 && (pr_assoc = assocs.to_a.first) && defined?(pr_assoc.first.call)
3363
3363
  callback, assoc = pr_assoc
3364
3364
  associations = assoc.is_a?(Array) ? assoc : [assoc]
3365
3365
  end
@@ -3601,10 +3601,10 @@ module Sequel
3601
3601
  end
3602
3602
 
3603
3603
  associations = eager_assoc[r[:name]]
3604
- if associations.respond_to?(:call)
3604
+ if defined?(associations.call)
3605
3605
  eager_block = associations
3606
3606
  associations = OPTS
3607
- elsif associations.is_a?(Hash) && associations.length == 1 && (pr_assoc = associations.to_a.first) && pr_assoc.first.respond_to?(:call)
3607
+ elsif associations.is_a?(Hash) && associations.length == 1 && (pr_assoc = associations.to_a.first) && defined?(pr_assoc.first.call)
3608
3608
  eager_block, associations = pr_assoc
3609
3609
  end
3610
3610
 
@@ -492,13 +492,13 @@ module Sequel
492
492
  def plugin(plugin, *args, &block)
493
493
  m = plugin.is_a?(Module) ? plugin : plugin_module(plugin)
494
494
 
495
- if !m.respond_to?(:apply) && !m.respond_to?(:configure) && (!args.empty? || block)
495
+ if !defined?(m.apply) && !defined?(m.configure) && (!args.empty? || block)
496
496
  Deprecation.deprecate("Plugin #{plugin} accepts no arguments or block, and passing arguments/block to it", "Remove arguments and block when loading the plugin")
497
497
  end
498
498
 
499
499
  unless @plugins.include?(m)
500
500
  @plugins << m
501
- m.apply(self, *args, &block) if m.respond_to?(:apply)
501
+ m.apply(self, *args, &block) if defined?(m.apply)
502
502
  extend(m::ClassMethods) if m.const_defined?(:ClassMethods, false)
503
503
  include(m::InstanceMethods) if m.const_defined?(:InstanceMethods, false)
504
504
  if m.const_defined?(:DatasetMethods, false)
@@ -506,7 +506,7 @@ module Sequel
506
506
  end
507
507
  end
508
508
 
509
- m.configure(self, *args, &block) if m.respond_to?(:configure)
509
+ m.configure(self, *args, &block) if defined?(m.configure)
510
510
  end
511
511
  # :nocov:
512
512
  ruby2_keywords(:plugin) if respond_to?(:ruby2_keywords, true)
@@ -44,7 +44,7 @@ module Sequel
44
44
  errors = @model.errors
45
45
  end
46
46
 
47
- if errors.respond_to?(:full_messages)
47
+ if defined?(errors.full_messages)
48
48
  @errors = errors
49
49
  super(errors.full_messages.join(', '))
50
50
  else
@@ -99,7 +99,7 @@ module Sequel
99
99
  # Convert the given string to CamelCase. Will also convert '/' to '::' which is useful for converting paths to namespaces.
100
100
  def camelize(s)
101
101
  s = s.to_s
102
- return s.camelize if s.respond_to?(:camelize)
102
+ return s.camelize if defined?(s.camelize)
103
103
  s = s.gsub(/\/(.?)/){|x| "::#{x[-1..-1].upcase unless x == '/'}"}.gsub(/(^|_)(.)/){|x| x[-1..-1].upcase}
104
104
  s
105
105
  end
@@ -109,7 +109,7 @@ module Sequel
109
109
  # or is not initialized.
110
110
  def constantize(s)
111
111
  s = s.to_s
112
- return s.constantize if s.respond_to?(:constantize)
112
+ return s.constantize if defined?(s.constantize)
113
113
  raise(NameError, "#{s.inspect} is not a valid constant name!") unless m = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.match(s)
114
114
  Object.module_eval("::#{m[1]}", __FILE__, __LINE__)
115
115
  end
@@ -117,14 +117,14 @@ module Sequel
117
117
  # Removes the module part from the expression in the string
118
118
  def demodulize(s)
119
119
  s = s.to_s
120
- return s.demodulize if s.respond_to?(:demodulize)
120
+ return s.demodulize if defined?(s.demodulize)
121
121
  s.gsub(/^.*::/, '')
122
122
  end
123
123
 
124
124
  # Returns the plural form of the word in the string.
125
125
  def pluralize(s)
126
126
  s = s.to_s
127
- return s.pluralize if s.respond_to?(:pluralize)
127
+ return s.pluralize if defined?(s.pluralize)
128
128
  result = s.dup
129
129
  Inflections.plurals.each{|(rule, replacement)| break if result.gsub!(rule, replacement)} unless Inflections.uncountables.include?(s.downcase)
130
130
  result
@@ -133,7 +133,7 @@ module Sequel
133
133
  # The reverse of pluralize, returns the singular form of a word in a string.
134
134
  def singularize(s)
135
135
  s = s.to_s
136
- return s.singularize if s.respond_to?(:singularize)
136
+ return s.singularize if defined?(s.singularize)
137
137
  result = s.dup
138
138
  Inflections.singulars.each{|(rule, replacement)| break if result.gsub!(rule, replacement)} unless Inflections.uncountables.include?(s.downcase)
139
139
  result
@@ -143,7 +143,7 @@ module Sequel
143
143
  # Also changes '::' to '/' to convert namespaces to paths.
144
144
  def underscore(s)
145
145
  s = s.to_s
146
- return s.underscore if s.respond_to?(:underscore)
146
+ return s.underscore if defined?(s.underscore)
147
147
  s.gsub('::', '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
148
148
  gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
149
149
  end
@@ -252,7 +252,7 @@ module Sequel
252
252
 
253
253
  unless skip.include?(:unique)
254
254
  unique_opts = Hash[opts[:unique]]
255
- if model.respond_to?(:sti_dataset)
255
+ if defined?(model.sti_dataset)
256
256
  unique_opts[:dataset] = model.sti_dataset
257
257
  end
258
258
  model.auto_validate_unique_columns.each{|cols| validates_unique(cols, unique_opts)}
@@ -117,7 +117,7 @@ module Sequel
117
117
  def [](k)
118
118
  if new? && !values.has_key?(k)
119
119
  v = model.default_values.fetch(k){return}
120
- v = v.call if v.respond_to?(:call)
120
+ v = v.call if defined?(v.call)
121
121
  values[k] = v if model.cache_default_values?
122
122
  v
123
123
  else
@@ -203,7 +203,7 @@ module Sequel
203
203
  get_column_value(column)
204
204
  end
205
205
 
206
- initial_values[column] = if value && value != true && value.respond_to?(:clone)
206
+ initial_values[column] = if value && value != true && defined?(value.clone)
207
207
  begin
208
208
  value.clone
209
209
  rescue TypeError
@@ -36,7 +36,7 @@ module Sequel
36
36
  module InsertConflict
37
37
  def self.configure(model)
38
38
  model.instance_exec do
39
- if @dataset && !@dataset.respond_to?(:insert_conflict)
39
+ if @dataset && !defined?(@dataset.insert_conflict)
40
40
  raise Error, "#{self}'s dataset does not support insert_conflict"
41
41
  end
42
42
  end
@@ -152,7 +152,7 @@ module Sequel
152
152
  if obj.is_a?(Array)
153
153
  obj.map{|x| object_to_json_data(x, *args, &block)}
154
154
  else
155
- if obj.respond_to?(:to_json_data)
155
+ if defined?(obj.to_json_data)
156
156
  obj.to_json_data(*args, &block)
157
157
  else
158
158
  begin
@@ -259,7 +259,7 @@ module Sequel
259
259
  # specific :fields if configured.
260
260
  def nested_attributes_set_attributes(meta, obj, attributes)
261
261
  if fields = meta[:fields]
262
- fields = fields.call(obj) if fields.respond_to?(:call)
262
+ fields = fields.call(obj) if defined?(fields.call)
263
263
  obj.set_fields(attributes, fields, :missing=>:skip)
264
264
  else
265
265
  obj.set(attributes)
@@ -159,7 +159,7 @@ module Sequel
159
159
 
160
160
  case @dataset.first_source_table
161
161
  when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier
162
- convert_errors = db.respond_to?(:error_info)
162
+ convert_errors = defined?(db.error_info)
163
163
  end
164
164
 
165
165
  unless convert_errors
@@ -162,7 +162,7 @@ module Sequel
162
162
  if !cc.include?(column) && (new? || get_column_value(column) != v)
163
163
  cc << column
164
164
 
165
- will_change_column(column) if respond_to?(:will_change_column)
165
+ will_change_column(column) if defined?(will_change_column)
166
166
  end
167
167
 
168
168
  deserialized_values[column] = v
@@ -91,7 +91,7 @@ module Sequel
91
91
  # +many_to_many+ association, make sure the associated object is created on the
92
92
  # current object's shard, unless the passed object already has an assigned shard.
93
93
  def ensure_associated_primary_key(opts, o, *args)
94
- o.set_server?(@server) if o.respond_to?(:set_server?)
94
+ o.set_server?(@server) if defined?(o.set_server?)
95
95
  super
96
96
  end
97
97
 
@@ -63,7 +63,7 @@ module Sequel
63
63
  end
64
64
  end
65
65
  # :nocov:
66
- ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
66
+ mod.send(:ruby2_keywords, meth) if mod.respond_to?(:ruby2_keywords, true)
67
67
  # :nocov:
68
68
  end
69
69
 
@@ -97,7 +97,7 @@ module Sequel
97
97
  end
98
98
  end
99
99
  # :nocov:
100
- ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
100
+ ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
101
101
  # :nocov:
102
102
  end
103
103
 
@@ -129,7 +129,7 @@ module Sequel
129
129
  end
130
130
  end
131
131
  # :nocov:
132
- ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
132
+ ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
133
133
  # :nocov:
134
134
  end
135
135
 
@@ -159,7 +159,7 @@ module Sequel
159
159
  end
160
160
  end
161
161
  # :nocov:
162
- ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
162
+ ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
163
163
  # :nocov:
164
164
  end
165
165
 
@@ -35,7 +35,7 @@ module Sequel
35
35
  # class B < Sequel::Model; end
36
36
  # a # => [A, B]
37
37
  module Subclasses
38
- NEED_SUBCLASSES = !Object.respond_to?(:subclasses) || Object.method(:subclasses).source_location
38
+ NEED_SUBCLASSES = !defined?(Object.subclasses) || Object.method(:subclasses).source_location
39
39
  private_constant :NEED_SUBCLASSES
40
40
 
41
41
  # Initialize the subclasses instance variable for the model.
@@ -282,7 +282,7 @@ module Sequel
282
282
  o.errors.add(a, opts[:message] || opts[:wrong_length]) unless v && v.size == i
283
283
  end
284
284
  if w = opts[:within]
285
- o.errors.add(a, opts[:message] || opts[:wrong_length]) unless v && w.public_send(w.respond_to?(:cover?) ? :cover? : :include?, v.size)
285
+ o.errors.add(a, opts[:message] || opts[:wrong_length]) unless v && w.public_send(defined?(w.cover?) ? :cover? : :include?, v.size)
286
286
  end
287
287
  end
288
288
  end
@@ -337,14 +337,14 @@ module Sequel
337
337
  def validates_inclusion_of(*atts)
338
338
  opts = extract_options!(atts)
339
339
  n = opts[:in]
340
- unless n && (n.respond_to?(:cover?) || n.respond_to?(:include?))
340
+ unless n && (defined?(n.cover?) || defined?(n.include?))
341
341
  raise ArgumentError, "The :in parameter is required, and must respond to cover? or include?"
342
342
  end
343
343
  opts[:message] ||= "is not in range or set: #{n.inspect}"
344
344
  reflect_validation(:inclusion, opts, atts)
345
345
  atts << opts
346
346
  validates_each(*atts) do |o, a, v|
347
- o.errors.add(a, opts[:message]) unless n.public_send(n.respond_to?(:cover?) ? :cover? : :include?, v)
347
+ o.errors.add(a, opts[:message]) unless n.public_send(defined?(n.cover?) ? :cover? : :include?, v)
348
348
  end
349
349
  end
350
350
 
@@ -107,7 +107,7 @@ module Sequel
107
107
 
108
108
  # Check attribute value(s) is included in the given set.
109
109
  def validates_includes(set, atts, opts=OPTS)
110
- validatable_attributes_for_type(:includes, atts, opts){|a,v,m| validation_error_message(m, set) unless set.public_send(set.respond_to?(:cover?) ? :cover? : :include?, v)}
110
+ validatable_attributes_for_type(:includes, atts, opts){|a,v,m| validation_error_message(m, set) unless set.public_send(defined?(set.cover?) ? :cover? : :include?, v)}
111
111
  end
112
112
 
113
113
  # Check attribute value(s) string representation is a valid integer.
data/lib/sequel/sql.rb CHANGED
@@ -1347,7 +1347,7 @@ module Sequel
1347
1347
  # underlying callable only accepts a single argument, call it
1348
1348
  # with the given dataset.
1349
1349
  def call(ds)
1350
- if @callable.respond_to?(:arity) && @callable.arity == 1
1350
+ if defined?(@callable.arity) && @callable.arity == 1
1351
1351
  @callable.call(ds)
1352
1352
  else
1353
1353
  @callable.call