sequel 5.36.0 → 5.41.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +56 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/doc/cheat_sheet.rdoc +5 -5
- data/doc/code_order.rdoc +0 -12
- data/doc/fork_safety.rdoc +84 -0
- data/doc/opening_databases.rdoc +5 -1
- data/doc/postgresql.rdoc +1 -1
- data/doc/querying.rdoc +3 -3
- data/doc/release_notes/5.37.0.txt +30 -0
- data/doc/release_notes/5.38.0.txt +28 -0
- data/doc/release_notes/5.39.0.txt +19 -0
- data/doc/release_notes/5.40.0.txt +40 -0
- data/doc/release_notes/5.41.0.txt +25 -0
- data/doc/sql.rdoc +1 -1
- data/doc/transactions.rdoc +0 -8
- data/lib/sequel/adapters/jdbc.rb +15 -3
- data/lib/sequel/adapters/jdbc/mysql.rb +4 -4
- data/lib/sequel/adapters/shared/mssql.rb +21 -1
- data/lib/sequel/adapters/shared/oracle.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +6 -4
- data/lib/sequel/adapters/shared/sqlite.rb +35 -1
- data/lib/sequel/core.rb +5 -6
- data/lib/sequel/database/connecting.rb +0 -1
- data/lib/sequel/database/misc.rb +14 -0
- data/lib/sequel/database/schema_generator.rb +6 -0
- data/lib/sequel/database/schema_methods.rb +16 -6
- data/lib/sequel/database/transactions.rb +1 -1
- data/lib/sequel/dataset/actions.rb +10 -6
- data/lib/sequel/dataset/features.rb +10 -0
- data/lib/sequel/dataset/prepared_statements.rb +2 -0
- data/lib/sequel/dataset/sql.rb +32 -10
- data/lib/sequel/extensions/blank.rb +8 -0
- data/lib/sequel/extensions/date_arithmetic.rb +8 -9
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/inflector.rb +8 -0
- data/lib/sequel/extensions/migration.rb +9 -1
- data/lib/sequel/extensions/named_timezones.rb +5 -1
- data/lib/sequel/extensions/pg_array.rb +1 -0
- data/lib/sequel/extensions/pg_interval.rb +34 -8
- data/lib/sequel/extensions/pg_row.rb +1 -0
- data/lib/sequel/extensions/pg_row_ops.rb +24 -0
- data/lib/sequel/extensions/query.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +3 -3
- data/lib/sequel/model/associations.rb +28 -4
- data/lib/sequel/model/base.rb +21 -4
- data/lib/sequel/model/plugins.rb +5 -0
- data/lib/sequel/plugins/association_proxies.rb +2 -0
- data/lib/sequel/plugins/auto_validations.rb +15 -1
- data/lib/sequel/plugins/class_table_inheritance.rb +0 -5
- data/lib/sequel/plugins/composition.rb +5 -1
- data/lib/sequel/plugins/constraint_validations.rb +2 -1
- data/lib/sequel/plugins/dataset_associations.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +44 -0
- data/lib/sequel/plugins/nested_attributes.rb +3 -1
- data/lib/sequel/plugins/pg_array_associations.rb +4 -0
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +2 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +7 -0
- data/lib/sequel/plugins/tree.rb +9 -4
- data/lib/sequel/plugins/validation_helpers.rb +6 -2
- data/lib/sequel/timezones.rb +8 -3
- data/lib/sequel/version.rb +1 -1
- metadata +33 -21
data/lib/sequel/dataset/sql.rb
CHANGED
@@ -22,7 +22,7 @@ module Sequel
|
|
22
22
|
def insert_sql(*values)
|
23
23
|
return static_sql(@opts[:sql]) if @opts[:sql]
|
24
24
|
|
25
|
-
|
25
|
+
check_insert_allowed!
|
26
26
|
|
27
27
|
columns = []
|
28
28
|
|
@@ -172,7 +172,7 @@ module Sequel
|
|
172
172
|
# than one table.
|
173
173
|
def update_sql(values = OPTS)
|
174
174
|
return static_sql(opts[:sql]) if opts[:sql]
|
175
|
-
|
175
|
+
check_update_allowed!
|
176
176
|
check_not_limited!(:update)
|
177
177
|
|
178
178
|
case values
|
@@ -215,7 +215,7 @@ module Sequel
|
|
215
215
|
lines << "def #{'_' if priv}#{type}_sql"
|
216
216
|
lines << 'if sql = opts[:sql]; return static_sql(sql) end' unless priv
|
217
217
|
lines << "if sql = cache_get(:_#{type}_sql); return sql end" if cacheable
|
218
|
-
lines << '
|
218
|
+
lines << 'check_delete_allowed!' << 'check_not_limited!(:delete)' if type == :delete
|
219
219
|
lines << 'sql = @opts[:append_sql] || sql_string_origin'
|
220
220
|
|
221
221
|
if clauses.all?{|c| c.is_a?(Array)}
|
@@ -918,10 +918,35 @@ module Sequel
|
|
918
918
|
!@opts[:no_cache_sql] && !cache_get(:_no_cache_sql)
|
919
919
|
end
|
920
920
|
|
921
|
-
# Raise an InvalidOperation exception if
|
921
|
+
# Raise an InvalidOperation exception if modification is not allowed for this dataset.
|
922
|
+
# Check whether it is allowed to insert into this dataset.
|
923
|
+
# Only for backwards compatibility with older external adapters.
|
922
924
|
def check_modification_allowed!
|
925
|
+
# SEQUEL6: Remove
|
926
|
+
Sequel::Deprecation.deprecate("Dataset#check_modification_allowed!", "Use check_{insert,delete,update,truncation}_allowed! instead")
|
927
|
+
_check_modification_allowed!(supports_modifying_joins?)
|
928
|
+
end
|
929
|
+
|
930
|
+
# Check whether it is allowed to insert into this dataset.
|
931
|
+
def check_insert_allowed!
|
932
|
+
_check_modification_allowed!(false)
|
933
|
+
end
|
934
|
+
alias check_truncation_allowed! check_insert_allowed!
|
935
|
+
|
936
|
+
# Check whether it is allowed to delete from this dataset.
|
937
|
+
def check_delete_allowed!
|
938
|
+
_check_modification_allowed!(supports_deleting_joins?)
|
939
|
+
end
|
940
|
+
|
941
|
+
# Check whether it is allowed to update this dataset.
|
942
|
+
def check_update_allowed!
|
943
|
+
_check_modification_allowed!(supports_updating_joins?)
|
944
|
+
end
|
945
|
+
|
946
|
+
# Internals of the check_*_allowed! methods
|
947
|
+
def _check_modification_allowed!(modifying_joins_supported)
|
923
948
|
raise(InvalidOperation, "Grouped datasets cannot be modified") if opts[:group]
|
924
|
-
raise(InvalidOperation, "Joined datasets cannot be modified") if !
|
949
|
+
raise(InvalidOperation, "Joined datasets cannot be modified") if !modifying_joins_supported && joined_dataset?
|
925
950
|
end
|
926
951
|
|
927
952
|
# Raise error if the dataset uses limits or offsets.
|
@@ -930,11 +955,6 @@ module Sequel
|
|
930
955
|
raise InvalidOperation, "Dataset##{type} not supported on datasets with limits or offsets" if opts[:limit] || opts[:offset]
|
931
956
|
end
|
932
957
|
|
933
|
-
# Alias of check_modification_allowed!
|
934
|
-
def check_truncation_allowed!
|
935
|
-
check_modification_allowed!
|
936
|
-
end
|
937
|
-
|
938
958
|
# Append column list to SQL string.
|
939
959
|
# If the column list is empty, a wildcard (*) is appended.
|
940
960
|
def column_list_append(sql, columns)
|
@@ -971,7 +991,9 @@ module Sequel
|
|
971
991
|
# operators unsupported by some databases. Used by adapters for databases
|
972
992
|
# that don't support the operators natively.
|
973
993
|
def complex_expression_emulate_append(sql, op, args)
|
994
|
+
# :nocov:
|
974
995
|
case op
|
996
|
+
# :nocov:
|
975
997
|
when :%
|
976
998
|
complex_expression_arg_pairs_append(sql, args){|a, b| Sequel.function(:MOD, a, b)}
|
977
999
|
when :>>
|
@@ -6,6 +6,14 @@
|
|
6
6
|
#
|
7
7
|
# Sequel.extension :blank
|
8
8
|
|
9
|
+
[FalseClass, Object, NilClass, Numeric, String, TrueClass].each do |klass|
|
10
|
+
# :nocov:
|
11
|
+
if klass.method_defined?(:blank?)
|
12
|
+
klass.send(:alias_method, :blank?, :blank?)
|
13
|
+
end
|
14
|
+
# :nocov:
|
15
|
+
end
|
16
|
+
|
9
17
|
class FalseClass
|
10
18
|
# false is always blank
|
11
19
|
def blank?
|
@@ -49,14 +49,13 @@ module Sequel
|
|
49
49
|
# Options:
|
50
50
|
# :cast :: Cast to the specified type instead of the default if casting
|
51
51
|
def date_sub(expr, interval, opts=OPTS)
|
52
|
-
|
53
|
-
|
54
|
-
interval.each{|k,v| h[k] = -v unless v.nil?}
|
55
|
-
h
|
56
|
-
else
|
57
|
-
-interval
|
52
|
+
if defined?(ActiveSupport::Duration) && interval.is_a?(ActiveSupport::Duration)
|
53
|
+
interval = interval.parts
|
58
54
|
end
|
59
|
-
|
55
|
+
parts = {}
|
56
|
+
interval.each{|k,v| parts[k] = -v unless v.nil?}
|
57
|
+
parts
|
58
|
+
DateAdd.new(expr, parts, opts)
|
60
59
|
end
|
61
60
|
end
|
62
61
|
|
@@ -113,12 +112,12 @@ module Sequel
|
|
113
112
|
end
|
114
113
|
when :mssql, :h2, :access, :sqlanywhere
|
115
114
|
units = case db_type
|
116
|
-
when :mssql, :sqlanywhere
|
117
|
-
MSSQL_DURATION_UNITS
|
118
115
|
when :h2
|
119
116
|
H2_DURATION_UNITS
|
120
117
|
when :access
|
121
118
|
ACCESS_DURATION_UNITS
|
119
|
+
else
|
120
|
+
MSSQL_DURATION_UNITS
|
122
121
|
end
|
123
122
|
each_valid_interval_unit(h, units) do |value, sql_unit|
|
124
123
|
expr = Sequel.function(:DATEADD, sql_unit, value, expr)
|
@@ -105,6 +105,14 @@ class String
|
|
105
105
|
yield Inflections if block_given?
|
106
106
|
Inflections
|
107
107
|
end
|
108
|
+
|
109
|
+
%w'classify constantize dasherize demodulize foreign_key humanize pluralize singularize tableize underscore'.each do |m|
|
110
|
+
# :nocov:
|
111
|
+
if method_defined?(m)
|
112
|
+
alias_method(m, m)
|
113
|
+
end
|
114
|
+
# :nocov:
|
115
|
+
end
|
108
116
|
|
109
117
|
# By default, camelize converts the string to UpperCamelCase. If the argument to camelize
|
110
118
|
# is set to :lower then camelize produces lowerCamelCase.
|
@@ -68,7 +68,9 @@ module Sequel
|
|
68
68
|
# Allow calling private methods for backwards compatibility
|
69
69
|
@db.send(method_sym, *args, &block)
|
70
70
|
end
|
71
|
+
# :nocov:
|
71
72
|
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
73
|
+
# :nocov:
|
72
74
|
|
73
75
|
# This object responds to all methods the database responds to.
|
74
76
|
def respond_to_missing?(meth, include_private)
|
@@ -330,7 +332,8 @@ module Sequel
|
|
330
332
|
# schema_migrations for timestamped migrations). in the database to keep track
|
331
333
|
# of the current migration version. If no migration version is stored in the
|
332
334
|
# database, the version is considered to be 0. If no target version is
|
333
|
-
# specified, the
|
335
|
+
# specified, or the target version specified is greater than the latest
|
336
|
+
# version available, the database is migrated to the latest version available in the
|
334
337
|
# migration directory.
|
335
338
|
#
|
336
339
|
# For example, to migrate the database to the latest version:
|
@@ -538,6 +541,11 @@ module Sequel
|
|
538
541
|
end
|
539
542
|
|
540
543
|
@direction = current < target ? :up : :down
|
544
|
+
|
545
|
+
if @direction == :down && @current >= @files.length
|
546
|
+
raise Migrator::Error, "Missing migration version(s) needed to migrate down to target version (current: #{current}, target: #{target})"
|
547
|
+
end
|
548
|
+
|
541
549
|
@migrations = get_migrations
|
542
550
|
end
|
543
551
|
|
@@ -84,9 +84,9 @@ module Sequel
|
|
84
84
|
def convert_output_time_other(v, output_timezone)
|
85
85
|
Time.at(v.to_i, :in => output_timezone)
|
86
86
|
end
|
87
|
-
else
|
88
87
|
# :nodoc:
|
89
88
|
# :nocov:
|
89
|
+
else
|
90
90
|
def convert_input_time_other(v, input_timezone)
|
91
91
|
local_offset = input_timezone.period_for_local(v, &tzinfo_disambiguator_for(v)).utc_total_offset
|
92
92
|
Time.new(1970, 1, 1, 0, 0, 0, local_offset) + v.to_i
|
@@ -105,6 +105,8 @@ module Sequel
|
|
105
105
|
Time.new(1970, 1, 1, 0, 0, 0, local_offset) + v.to_i
|
106
106
|
end
|
107
107
|
end
|
108
|
+
# :nodoc:
|
109
|
+
# :nocov:
|
108
110
|
end
|
109
111
|
|
110
112
|
# Handle both TZInfo 1 and TZInfo 2
|
@@ -142,6 +144,8 @@ module Sequel
|
|
142
144
|
# Convert timezone offset from UTC to the offset for the output_timezone
|
143
145
|
(v - local_offset).new_offset(local_offset)
|
144
146
|
end
|
147
|
+
# :nodoc:
|
148
|
+
# :nocov:
|
145
149
|
end
|
146
150
|
|
147
151
|
# Returns TZInfo::Timezone instance if given a String.
|
@@ -213,6 +213,7 @@ module Sequel
|
|
213
213
|
scalar_typecast_method = :"typecast_value_#{opts.fetch(:scalar_typecast, type)}"
|
214
214
|
define_method(meth){|v| typecast_value_pg_array(v, creator, scalar_typecast_method)}
|
215
215
|
private meth
|
216
|
+
alias_method(meth, meth)
|
216
217
|
end
|
217
218
|
|
218
219
|
@schema_type_classes[:"#{type}_array"] = PGArray
|
@@ -34,6 +34,13 @@
|
|
34
34
|
|
35
35
|
require 'active_support/duration'
|
36
36
|
|
37
|
+
# :nocov:
|
38
|
+
begin
|
39
|
+
require 'active_support/version'
|
40
|
+
rescue LoadError
|
41
|
+
end
|
42
|
+
# :nocov:
|
43
|
+
|
37
44
|
module Sequel
|
38
45
|
module Postgres
|
39
46
|
module IntervalDatabaseMethods
|
@@ -61,34 +68,47 @@ module Sequel
|
|
61
68
|
|
62
69
|
# Creates callable objects that convert strings into ActiveSupport::Duration instances.
|
63
70
|
class Parser
|
71
|
+
# Whether ActiveSupport::Duration.new takes parts as array instead of hash
|
72
|
+
USE_PARTS_ARRAY = !defined?(ActiveSupport::VERSION::STRING) || ActiveSupport::VERSION::STRING < '5.1'
|
73
|
+
|
74
|
+
if defined?(ActiveSupport::Duration::SECONDS_PER_MONTH)
|
75
|
+
SECONDS_PER_MONTH = ActiveSupport::Duration::SECONDS_PER_MONTH
|
76
|
+
SECONDS_PER_YEAR = ActiveSupport::Duration::SECONDS_PER_YEAR
|
77
|
+
# :nocov:
|
78
|
+
else
|
79
|
+
SECONDS_PER_MONTH = 2592000
|
80
|
+
SECONDS_PER_YEAR = 31557600
|
81
|
+
# :nocov:
|
82
|
+
end
|
83
|
+
|
64
84
|
# Parse the interval input string into an ActiveSupport::Duration instance.
|
65
85
|
def call(string)
|
66
86
|
raise(InvalidValue, "invalid or unhandled interval format: #{string.inspect}") unless matches = /\A([+-]?\d+ years?\s?)?([+-]?\d+ mons?\s?)?([+-]?\d+ days?\s?)?(?:(?:([+-])?(\d{2,10}):(\d\d):(\d\d(\.\d+)?))|([+-]?\d+ hours?\s?)?([+-]?\d+ mins?\s?)?([+-]?\d+(\.\d+)? secs?\s?)?)?\z/.match(string)
|
67
87
|
|
68
88
|
value = 0
|
69
|
-
parts =
|
89
|
+
parts = {}
|
70
90
|
|
71
91
|
if v = matches[1]
|
72
92
|
v = v.to_i
|
73
|
-
value +=
|
74
|
-
parts
|
93
|
+
value += SECONDS_PER_YEAR * v
|
94
|
+
parts[:years] = v
|
75
95
|
end
|
76
96
|
if v = matches[2]
|
77
97
|
v = v.to_i
|
78
|
-
value +=
|
79
|
-
parts
|
98
|
+
value += SECONDS_PER_MONTH * v
|
99
|
+
parts[:months] = v
|
80
100
|
end
|
81
101
|
if v = matches[3]
|
82
102
|
v = v.to_i
|
83
103
|
value += 86400 * v
|
84
|
-
parts
|
104
|
+
parts[:days] = v
|
85
105
|
end
|
86
106
|
if matches[5]
|
87
107
|
seconds = matches[5].to_i * 3600 + matches[6].to_i * 60
|
88
108
|
seconds += matches[8] ? matches[7].to_f : matches[7].to_i
|
89
109
|
seconds *= -1 if matches[4] == '-'
|
90
110
|
value += seconds
|
91
|
-
parts
|
111
|
+
parts[:seconds] = seconds
|
92
112
|
elsif matches[9] || matches[10] || matches[11]
|
93
113
|
seconds = 0
|
94
114
|
if v = matches[9]
|
@@ -101,8 +121,14 @@ module Sequel
|
|
101
121
|
seconds += matches[12] ? v.to_f : v.to_i
|
102
122
|
end
|
103
123
|
value += seconds
|
104
|
-
parts
|
124
|
+
parts[:seconds] = seconds
|
125
|
+
end
|
126
|
+
|
127
|
+
# :nocov:
|
128
|
+
if USE_PARTS_ARRAY
|
129
|
+
parts = parts.to_a
|
105
130
|
end
|
131
|
+
# :nocov:
|
106
132
|
|
107
133
|
ActiveSupport::Duration.new(value, parts)
|
108
134
|
end
|
@@ -158,6 +158,30 @@ module Sequel
|
|
158
158
|
end
|
159
159
|
end
|
160
160
|
end
|
161
|
+
|
162
|
+
# :nocov:
|
163
|
+
if defined?(PGRow::ArrayRow)
|
164
|
+
# :nocov:
|
165
|
+
class PGRow::ArrayRow
|
166
|
+
# Wrap the PGRow::ArrayRow instance in an PGRowOp, allowing you to easily use
|
167
|
+
# the PostgreSQL row functions and operators with literal rows.
|
168
|
+
def op
|
169
|
+
Sequel.pg_row_op(self)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# :nocov:
|
175
|
+
if defined?(PGRow::HashRow)
|
176
|
+
# :nocov:
|
177
|
+
class PGRow::HashRow
|
178
|
+
# Wrap the PGRow::ArrayRow instance in an PGRowOp, allowing you to easily use
|
179
|
+
# the PostgreSQL row functions and operators with literal rows.
|
180
|
+
def op
|
181
|
+
Sequel.pg_row_op(self)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
161
185
|
end
|
162
186
|
|
163
187
|
module SQL::Builders
|
@@ -37,7 +37,7 @@ module Sequel
|
|
37
37
|
{:type =>schema[:type] == :boolean ? TrueClass : Integer}
|
38
38
|
when /\Abigint(?:\((?:\d+)\))?(?: unsigned)?\z/
|
39
39
|
{:type=>:Bignum}
|
40
|
-
when /\A(?:real|float
|
40
|
+
when /\A(?:real|float|double(?: precision)?|double\(\d+,\d+\))(?: unsigned)?\z/
|
41
41
|
{:type=>Float}
|
42
42
|
when 'boolean', 'bit', 'bool'
|
43
43
|
{:type=>TrueClass}
|
@@ -57,7 +57,7 @@ module Sequel
|
|
57
57
|
{:type=>String, :size=>($1.to_i if $1)}
|
58
58
|
when /\A(?:small)?money\z/
|
59
59
|
{:type=>BigDecimal, :size=>[19,2]}
|
60
|
-
when /\A(?:decimal|numeric|number)(?:\((\d+)(?:,\s*(\d+))?\))?\z/
|
60
|
+
when /\A(?:decimal|numeric|number)(?:\((\d+)(?:,\s*(\d+))?\))?(?: unsigned)?\z/
|
61
61
|
s = [($1.to_i if $1), ($2.to_i if $2)].compact
|
62
62
|
{:type=>BigDecimal, :size=>(s.empty? ? nil : s)}
|
63
63
|
when /\A(?:bytea|(?:tiny|medium|long)?blob|(?:var)?binary)(?:\((\d+)\))?\z/
|
@@ -218,7 +218,7 @@ END_MIG
|
|
218
218
|
gen.foreign_key(name, table, col_opts)
|
219
219
|
else
|
220
220
|
gen.column(name, type, col_opts)
|
221
|
-
if [Integer, :Bignum, Float].include?(type) && schema[:db_type] =~ / unsigned\z/io
|
221
|
+
if [Integer, :Bignum, Float, BigDecimal].include?(type) && schema[:db_type] =~ / unsigned\z/io
|
222
222
|
gen.check(Sequel::SQL::Identifier.new(name) >= 0)
|
223
223
|
end
|
224
224
|
end
|
@@ -1929,7 +1929,22 @@ module Sequel
|
|
1929
1929
|
# can be easily overridden in the class itself while allowing for
|
1930
1930
|
# super to be called.
|
1931
1931
|
def association_module_def(name, opts=OPTS, &block)
|
1932
|
-
association_module(opts)
|
1932
|
+
mod = association_module(opts)
|
1933
|
+
mod.send(:define_method, name, &block)
|
1934
|
+
mod.send(:alias_method, name, name)
|
1935
|
+
end
|
1936
|
+
|
1937
|
+
# Add a method to the module included in the class, so the method
|
1938
|
+
# can be easily overridden in the class itself while allowing for
|
1939
|
+
# super to be called. This method allows passing keywords through
|
1940
|
+
# the defined methods.
|
1941
|
+
def association_module_delegate_def(name, opts, &block)
|
1942
|
+
mod = association_module(opts)
|
1943
|
+
mod.send(:define_method, name, &block)
|
1944
|
+
# :nocov:
|
1945
|
+
mod.send(:ruby2_keywords, name) if mod.respond_to?(:ruby2_keywords, true)
|
1946
|
+
# :nocov:
|
1947
|
+
mod.send(:alias_method, name, name)
|
1933
1948
|
end
|
1934
1949
|
|
1935
1950
|
# Add a private method to the module included in the class.
|
@@ -1981,17 +1996,17 @@ module Sequel
|
|
1981
1996
|
|
1982
1997
|
if adder = opts[:adder]
|
1983
1998
|
association_module_private_def(opts[:_add_method], opts, &adder)
|
1984
|
-
|
1999
|
+
association_module_delegate_def(opts[:add_method], opts){|o,*args| add_associated_object(opts, o, *args)}
|
1985
2000
|
end
|
1986
2001
|
|
1987
2002
|
if remover = opts[:remover]
|
1988
2003
|
association_module_private_def(opts[:_remove_method], opts, &remover)
|
1989
|
-
|
2004
|
+
association_module_delegate_def(opts[:remove_method], opts){|o,*args| remove_associated_object(opts, o, *args)}
|
1990
2005
|
end
|
1991
2006
|
|
1992
2007
|
if clearer = opts[:clearer]
|
1993
2008
|
association_module_private_def(opts[:_remove_all_method], opts, &clearer)
|
1994
|
-
|
2009
|
+
association_module_delegate_def(opts[:remove_all_method], opts){|*args| remove_all_associated_objects(opts, *args)}
|
1995
2010
|
end
|
1996
2011
|
end
|
1997
2012
|
|
@@ -2423,6 +2438,9 @@ module Sequel
|
|
2423
2438
|
run_association_callbacks(opts, :after_add, o)
|
2424
2439
|
o
|
2425
2440
|
end
|
2441
|
+
# :nocov:
|
2442
|
+
ruby2_keywords(:add_associated_object) if respond_to?(:ruby2_keywords, true)
|
2443
|
+
# :nocov:
|
2426
2444
|
|
2427
2445
|
# Add/Set the current object to/as the given object's reciprocal association.
|
2428
2446
|
def add_reciprocal_object(opts, o)
|
@@ -2565,6 +2583,9 @@ module Sequel
|
|
2565
2583
|
associations[opts[:name]] = []
|
2566
2584
|
ret
|
2567
2585
|
end
|
2586
|
+
# :nocov:
|
2587
|
+
ruby2_keywords(:remove_all_associated_objects) if respond_to?(:ruby2_keywords, true)
|
2588
|
+
# :nocov:
|
2568
2589
|
|
2569
2590
|
# Remove the given associated object from the given association
|
2570
2591
|
def remove_associated_object(opts, o, *args)
|
@@ -2586,6 +2607,9 @@ module Sequel
|
|
2586
2607
|
run_association_callbacks(opts, :after_remove, o)
|
2587
2608
|
o
|
2588
2609
|
end
|
2610
|
+
# :nocov:
|
2611
|
+
ruby2_keywords(:remove_associated_object) if respond_to?(:ruby2_keywords, true)
|
2612
|
+
# :nocov:
|
2589
2613
|
|
2590
2614
|
# Check that the object from the associated table specified by the primary key
|
2591
2615
|
# is currently associated to the receiver. If it is associated, return the object, otherwise
|