sequel 4.31.0 → 4.32.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.
- checksums.yaml +4 -4
- data/CHANGELOG +24 -0
- data/Rakefile +17 -15
- data/doc/association_basics.rdoc +7 -3
- data/doc/opening_databases.rdoc +7 -0
- data/doc/release_notes/4.32.0.txt +132 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/security.rdoc +70 -26
- data/doc/testing.rdoc +1 -0
- data/lib/sequel/adapters/jdbc.rb +2 -1
- data/lib/sequel/adapters/postgres.rb +3 -4
- data/lib/sequel/adapters/shared/mysql.rb +14 -1
- data/lib/sequel/adapters/shared/sqlite.rb +2 -2
- data/lib/sequel/extensions/_pretty_table.rb +2 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +2 -0
- data/lib/sequel/extensions/columns_introspection.rb +2 -0
- data/lib/sequel/extensions/connection_validator.rb +2 -0
- data/lib/sequel/extensions/constraint_validations.rb +2 -0
- data/lib/sequel/extensions/core_extensions.rb +1 -5
- data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -0
- data/lib/sequel/extensions/dataset_source_alias.rb +2 -0
- data/lib/sequel/extensions/date_arithmetic.rb +2 -0
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +3 -1
- data/lib/sequel/extensions/error_sql.rb +2 -0
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/filter_having.rb +2 -0
- data/lib/sequel/extensions/from_block.rb +2 -0
- data/lib/sequel/extensions/graph_each.rb +2 -0
- data/lib/sequel/extensions/hash_aliases.rb +2 -0
- data/lib/sequel/extensions/inflector.rb +2 -0
- data/lib/sequel/extensions/looser_typecasting.rb +3 -1
- data/lib/sequel/extensions/meta_def.rb +2 -0
- data/lib/sequel/extensions/migration.rb +4 -0
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +2 -0
- data/lib/sequel/extensions/named_timezones.rb +2 -0
- data/lib/sequel/extensions/no_auto_literal_strings.rb +84 -0
- data/lib/sequel/extensions/null_dataset.rb +2 -0
- data/lib/sequel/extensions/pagination.rb +2 -0
- data/lib/sequel/extensions/pg_array.rb +2 -4
- data/lib/sequel/extensions/pg_array_ops.rb +2 -0
- data/lib/sequel/extensions/pg_enum.rb +2 -0
- data/lib/sequel/extensions/pg_hstore.rb +2 -4
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -0
- data/lib/sequel/extensions/pg_inet.rb +2 -4
- data/lib/sequel/extensions/pg_inet_ops.rb +2 -0
- data/lib/sequel/extensions/pg_interval.rb +2 -4
- data/lib/sequel/extensions/pg_json.rb +4 -4
- data/lib/sequel/extensions/pg_json_ops.rb +3 -0
- data/lib/sequel/extensions/pg_loose_count.rb +2 -0
- data/lib/sequel/extensions/pg_range.rb +2 -4
- data/lib/sequel/extensions/pg_range_ops.rb +2 -0
- data/lib/sequel/extensions/pg_row.rb +2 -4
- data/lib/sequel/extensions/pg_row_ops.rb +2 -0
- data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -0
- data/lib/sequel/extensions/pretty_table.rb +2 -0
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/query_literals.rb +7 -5
- data/lib/sequel/extensions/round_timestamps.rb +4 -3
- data/lib/sequel/extensions/schema_caching.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +2 -0
- data/lib/sequel/extensions/select_remove.rb +2 -0
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +2 -0
- data/lib/sequel/extensions/server_block.rb +3 -0
- data/lib/sequel/extensions/set_overrides.rb +2 -0
- data/lib/sequel/extensions/split_array_nil.rb +2 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +2 -0
- data/lib/sequel/model/associations.rb +95 -55
- data/lib/sequel/plugins/association_pks.rb +58 -33
- data/lib/sequel/plugins/eager_each.rb +22 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +44 -3
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/mysql_spec.rb +34 -6
- data/spec/adapters/oracle_spec.rb +1 -1
- data/spec/bin_spec.rb +2 -2
- data/spec/core/dataset_spec.rb +7 -0
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/class_table_inheritance_spec.rb +24 -0
- data/spec/extensions/eager_each_spec.rb +25 -1
- data/spec/extensions/no_auto_literal_strings_spec.rb +65 -0
- data/spec/extensions/pg_range_spec.rb +1 -0
- data/spec/extensions/spec_helper.rb +5 -5
- data/spec/extensions/tactical_eager_loading_spec.rb +71 -17
- data/spec/integration/associations_test.rb +77 -62
- data/spec/integration/dataset_test.rb +3 -3
- data/spec/integration/plugin_test.rb +22 -0
- data/spec/integration/prepared_statement_test.rb +8 -8
- data/spec/integration/spec_helper.rb +4 -0
- data/spec/model/association_reflection_spec.rb +30 -0
- data/spec/model/associations_spec.rb +177 -16
- metadata +6 -2
@@ -80,11 +80,9 @@
|
|
80
80
|
# See the {schema modification guide}[rdoc-ref:doc/schema_modification.rdoc]
|
81
81
|
# for details on using hstore columns in CREATE/ALTER TABLE statements.
|
82
82
|
#
|
83
|
-
# If you are not using the native postgres or jdbc/postgresql adapters and are using hstore
|
84
|
-
# types as model column values you probably should use the
|
85
|
-
# pg_typecast_on_load plugin if the column values are returned as a string.
|
86
|
-
#
|
87
83
|
# This extension requires the delegate and strscan libraries.
|
84
|
+
#
|
85
|
+
# Related module: Sequel::Postgres::HStore
|
88
86
|
|
89
87
|
require 'delegate'
|
90
88
|
require 'strscan'
|
@@ -75,6 +75,8 @@
|
|
75
75
|
# pg_hstore extension is loaded. Methods representing expressions that return
|
76
76
|
# PostgreSQL arrays will have the returned expression automatically wrapped in a
|
77
77
|
# Postgres::ArrayOp if the pg_array_ops extension is loaded.
|
78
|
+
#
|
79
|
+
# Related module: Sequel::Postgres::HStoreOp
|
78
80
|
|
79
81
|
#
|
80
82
|
module Sequel
|
@@ -11,10 +11,6 @@
|
|
11
11
|
#
|
12
12
|
# DB.extension :pg_inet
|
13
13
|
#
|
14
|
-
# If you are not using the native postgres or jdbc/postgresql adapters and are using inet/cidr
|
15
|
-
# types as model column values you probably should use the
|
16
|
-
# pg_typecast_on_load plugin if the column values are returned as a string.
|
17
|
-
#
|
18
14
|
# This extension integrates with the pg_array extension. If you plan
|
19
15
|
# to use the inet[] or cidr[] types, load the pg_array extension before
|
20
16
|
# the pg_inet extension:
|
@@ -29,6 +25,8 @@
|
|
29
25
|
#
|
30
26
|
# See the {schema modification guide}[rdoc-ref:doc/schema_modification.rdoc]
|
31
27
|
# for details on using inet/cidr columns in CREATE/ALTER TABLE statements.
|
28
|
+
#
|
29
|
+
# Related module: Sequel::Postgres::InetDatabaseMethods
|
32
30
|
|
33
31
|
require 'ipaddr'
|
34
32
|
Sequel.require 'adapters/utils/pg_types'
|
@@ -17,10 +17,6 @@
|
|
17
17
|
#
|
18
18
|
# DB.extension :pg_interval
|
19
19
|
#
|
20
|
-
# If you are not using the native postgres or jdbc/postgresql adapters and are using interval
|
21
|
-
# types as model column values you probably should use the
|
22
|
-
# pg_typecast_on_load plugin if the column values are returned as a string.
|
23
|
-
#
|
24
20
|
# This extension integrates with the pg_array extension. If you plan
|
25
21
|
# to use arrays of interval types, load the pg_array extension before the
|
26
22
|
# pg_interval extension:
|
@@ -36,6 +32,8 @@
|
|
36
32
|
#
|
37
33
|
# See the {schema modification guide}[rdoc-ref:doc/schema_modification.rdoc]
|
38
34
|
# for details on using interval columns in CREATE/ALTER TABLE statements.
|
35
|
+
#
|
36
|
+
# Related module: Sequel::Postgres::IntervalDatabaseMethods
|
39
37
|
|
40
38
|
require 'active_support/duration'
|
41
39
|
Sequel.require 'adapters/utils/pg_types'
|
@@ -45,10 +45,6 @@
|
|
45
45
|
#
|
46
46
|
# DB.extension :pg_json
|
47
47
|
#
|
48
|
-
# If you are not using the native postgres adapter and are using json
|
49
|
-
# types as model column values you probably should use the
|
50
|
-
# pg_typecast_on_load plugin if the column values are returned as a string.
|
51
|
-
#
|
52
48
|
# See the {schema modification guide}[rdoc-ref:doc/schema_modification.rdoc]
|
53
49
|
# for details on using json columns in CREATE/ALTER TABLE statements.
|
54
50
|
#
|
@@ -62,6 +58,10 @@
|
|
62
58
|
# Attempting to use other values (such as symbols) will not work correctly.
|
63
59
|
#
|
64
60
|
# This extension requires both the json and delegate libraries.
|
61
|
+
#
|
62
|
+
# Related modules: Sequel::Postgres::JSONArrayBase, Sequel::Postgres::JSONArray,
|
63
|
+
# Sequel::Postgres::JSONArray, Sequel::Postgres::JSONBArray, Sequel::Postgres::JSONHashBase,
|
64
|
+
# Sequel::Postgres::JSONHash, Sequel::Postgres::JSONBHash, Sequel::Postgres::JSONDatabaseMethods
|
65
65
|
|
66
66
|
require 'delegate'
|
67
67
|
require 'json'
|
@@ -80,6 +80,9 @@
|
|
80
80
|
# In order to get the automatic conversion from a ruby array to a PostgreSQL array
|
81
81
|
# (as shown in the #[] and #get_text examples above), you need to load the pg_array
|
82
82
|
# extension.
|
83
|
+
#
|
84
|
+
# Related modules: Sequel::Postgres::JSONBaseOp, Sequel::Postgres::JSONOp,
|
85
|
+
# Sequel::Postgres::JSONBOp
|
83
86
|
|
84
87
|
#
|
85
88
|
module Sequel
|
@@ -47,10 +47,6 @@
|
|
47
47
|
#
|
48
48
|
# DB.extension :pg_range
|
49
49
|
#
|
50
|
-
# If you are not using the native postgres or jdbc/postgresql adapters and are using range
|
51
|
-
# types as model column values you probably should use the
|
52
|
-
# pg_typecast_on_load plugin if the column values are returned as a string.
|
53
|
-
#
|
54
50
|
# See the {schema modification guide}[rdoc-ref:doc/schema_modification.rdoc]
|
55
51
|
# for details on using range type columns in CREATE/ALTER TABLE statements.
|
56
52
|
#
|
@@ -59,6 +55,8 @@
|
|
59
55
|
# pg_range extension:
|
60
56
|
#
|
61
57
|
# DB.extension :pg_array, :pg_range
|
58
|
+
#
|
59
|
+
# Related module: Sequel::Postgres::PGRange
|
62
60
|
|
63
61
|
Sequel.require 'adapters/utils/pg_types'
|
64
62
|
|
@@ -53,6 +53,8 @@
|
|
53
53
|
# If you are also using the pg_range extension, you should load it before
|
54
54
|
# loading this extension. Doing so will allow you to use PGArray#op to get
|
55
55
|
# an RangeOp, allowing you to perform range operations on range literals.
|
56
|
+
#
|
57
|
+
# Related module: Sequel::Postgres::RangeOp
|
56
58
|
|
57
59
|
#
|
58
60
|
module Sequel
|
@@ -76,14 +76,12 @@
|
|
76
76
|
# DB.conversion_procs.select{|k,v| v.is_a?(Sequel::Postgres::PGRow::Parser) && \
|
77
77
|
# v.converter && (v.converter.name.nil? || v.converter.name == '') }.map{|k,v| v}
|
78
78
|
#
|
79
|
-
# If you are not using the native postgres or jdbc/postgresql adapters and are using composite types
|
80
|
-
# types as model column values you probably should use the
|
81
|
-
# pg_typecast_on_load plugin if the column values are returned as a string.
|
82
|
-
#
|
83
79
|
# See the {schema modification guide}[rdoc-ref:doc/schema_modification.rdoc]
|
84
80
|
# for details on using row type columns in CREATE/ALTER TABLE statements.
|
85
81
|
#
|
86
82
|
# This extension requires both the strscan and delegate libraries.
|
83
|
+
#
|
84
|
+
# Related module: Sequel::Postgres::PGRow
|
87
85
|
|
88
86
|
require 'delegate'
|
89
87
|
require 'strscan'
|
@@ -17,11 +17,11 @@
|
|
17
17
|
# SELECT a, b, 2, FROM table GROUP BY a, b ORDER BY c
|
18
18
|
#
|
19
19
|
# This extension makes select, group, and order methods operate
|
20
|
-
# like filter methods, which support the same interface.
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
20
|
+
# like filter methods, which support the same interface. Note
|
21
|
+
# that this extension can add SQL injection vulnerabilities to existing
|
22
|
+
# code if any of the strings passed to one of the supported
|
23
|
+
# methods is derived from user input. For that reason, it should
|
24
|
+
# be used with caution.
|
25
25
|
#
|
26
26
|
# You can load this extension into specific datasets:
|
27
27
|
#
|
@@ -32,6 +32,8 @@
|
|
32
32
|
# is probably the desired behavior if you are using this extension:
|
33
33
|
#
|
34
34
|
# DB.extension(:query_literals)
|
35
|
+
#
|
36
|
+
# Related module: Sequel::QueryLiterals
|
35
37
|
|
36
38
|
#
|
37
39
|
module Sequel
|
@@ -4,9 +4,8 @@
|
|
4
4
|
# values to the database's supported level of precision before literalizing
|
5
5
|
# them.
|
6
6
|
#
|
7
|
-
# For example, if the database supports
|
8
|
-
# it a Time value with
|
9
|
-
# appropriately:
|
7
|
+
# For example, if the database supports millisecond precision, and you give
|
8
|
+
# it a Time value with microsecond precision, it will round it appropriately:
|
10
9
|
#
|
11
10
|
# Time.at(1405341161.917999982833862)
|
12
11
|
# # default: 2014-07-14 14:32:41.917999
|
@@ -23,6 +22,8 @@
|
|
23
22
|
# To round timestamps for all datasets on a single database:
|
24
23
|
#
|
25
24
|
# DB.extension(:round_timestamps)
|
25
|
+
#
|
26
|
+
# Related module: Sequel::Dataset::RoundTimestamps
|
26
27
|
|
27
28
|
unless RUBY_VERSION >= '1.9'
|
28
29
|
# :nocov:
|
@@ -43,6 +43,8 @@
|
|
43
43
|
# The cached schema is dumped in Marshal format, since it is the fastest
|
44
44
|
# and it handles all ruby objects used in the schema hash. Because of this,
|
45
45
|
# you should not attempt to load the schema from a untrusted file.
|
46
|
+
#
|
47
|
+
# Related module: Sequel::SchemaCaching
|
46
48
|
|
47
49
|
#
|
48
50
|
module Sequel
|
@@ -14,6 +14,7 @@ module Sequel
|
|
14
14
|
@association_reflections = {}
|
15
15
|
@autoreloading_associations = {}
|
16
16
|
@cache_associations = true
|
17
|
+
@default_association_options = {}
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
@@ -489,40 +490,21 @@ module Sequel
|
|
489
490
|
|
490
491
|
private
|
491
492
|
|
492
|
-
|
493
|
-
#
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
Sequel.synchronize{return h[key] if h.has_key?(key)}
|
500
|
-
value = yield
|
501
|
-
Sequel.synchronize{h[key] = value}
|
502
|
-
end
|
503
|
-
end
|
504
|
-
|
505
|
-
# Cache the value at the given key, synchronizing access.
|
506
|
-
def cached_set(key, value)
|
507
|
-
return unless h = self[:cache]
|
493
|
+
# On non-GVL rubies, assume the need to synchronize access. Store the key
|
494
|
+
# in a special sub-hash that always uses this method to synchronize access.
|
495
|
+
def cached_fetch(key)
|
496
|
+
fetch(key) do
|
497
|
+
return yield unless h = self[:cache]
|
498
|
+
Sequel.synchronize{return h[key] if h.has_key?(key)}
|
499
|
+
value = yield
|
508
500
|
Sequel.synchronize{h[key] = value}
|
509
501
|
end
|
510
|
-
|
511
|
-
else
|
512
|
-
# On MRI, use a plain fetch, since the GVL will synchronize access.
|
513
|
-
def cached_fetch(key)
|
514
|
-
fetch(key) do
|
515
|
-
return yield unless h = self[:cache]
|
516
|
-
h.fetch(key){h[key] = yield}
|
517
|
-
end
|
518
|
-
end
|
502
|
+
end
|
519
503
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
h[key] = value
|
525
|
-
end
|
504
|
+
# Cache the value at the given key, synchronizing access.
|
505
|
+
def cached_set(key, value)
|
506
|
+
return unless h = self[:cache]
|
507
|
+
Sequel.synchronize{h[key] = value}
|
526
508
|
end
|
527
509
|
|
528
510
|
# The base dataset used for the association, before any order/conditions
|
@@ -1436,11 +1418,14 @@ module Sequel
|
|
1436
1418
|
attr_reader :autoreloading_associations
|
1437
1419
|
|
1438
1420
|
# Whether association metadata should be cached in the association reflection. If not cached, it will be computed
|
1439
|
-
# on demand. In general you only want to set this to
|
1421
|
+
# on demand. In general you only want to set this to false when using code reloading. When using code reloading,
|
1440
1422
|
# setting this will make sure that if an associated class is removed or modified, this class will not hang on to
|
1441
1423
|
# the previous class.
|
1442
1424
|
attr_accessor :cache_associations
|
1443
1425
|
|
1426
|
+
# The default options to use for all associations.
|
1427
|
+
attr_accessor :default_association_options
|
1428
|
+
|
1444
1429
|
# The default :eager_limit_strategy option to use for limited or offset associations (default: true, causing Sequel
|
1445
1430
|
# to use what it considers the most appropriate strategy).
|
1446
1431
|
attr_accessor :default_eager_limit_strategy
|
@@ -1674,7 +1659,7 @@ module Sequel
|
|
1674
1659
|
orig_opts = cloned_assoc[:orig_opts].merge(orig_opts)
|
1675
1660
|
end
|
1676
1661
|
|
1677
|
-
opts = orig_opts.merge(:type => type, :name => name, :cache=>({} if cache_associations), :model => self)
|
1662
|
+
opts = default_association_options.merge(orig_opts).merge(:type => type, :name => name, :cache=>({} if cache_associations), :model => self)
|
1678
1663
|
opts[:block] = block if block
|
1679
1664
|
if !opts.has_key?(:instance_specific) && (block || orig_opts[:block] || orig_opts[:dataset])
|
1680
1665
|
# It's possible the association is instance specific, in that it depends on
|
@@ -1757,7 +1742,7 @@ module Sequel
|
|
1757
1742
|
associate(:one_to_one, name, opts, &block)
|
1758
1743
|
end
|
1759
1744
|
|
1760
|
-
Plugins.inherited_instance_variables(self, :@association_reflections=>:dup, :@autoreloading_associations=>:hash_dup, :@cache_associations=>nil, :@default_eager_limit_strategy=>nil)
|
1745
|
+
Plugins.inherited_instance_variables(self, :@association_reflections=>:dup, :@autoreloading_associations=>:hash_dup, :@default_association_options=>:dup, :@cache_associations=>nil, :@default_eager_limit_strategy=>nil)
|
1761
1746
|
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])
|
1762
1747
|
|
1763
1748
|
private
|
@@ -1818,7 +1803,6 @@ module Sequel
|
|
1818
1803
|
# Configures many_to_many and one_through_one association reflection and adds the related association methods
|
1819
1804
|
def def_many_to_many(opts)
|
1820
1805
|
one_through_one = opts[:type] == :one_through_one
|
1821
|
-
opts[:read_only] = true if one_through_one
|
1822
1806
|
left = (opts[:left_key] ||= opts.default_left_key)
|
1823
1807
|
lcks = opts[:left_keys] = Array(left)
|
1824
1808
|
right = (opts[:right_key] ||= opts.default_right_key)
|
@@ -1872,21 +1856,54 @@ module Sequel
|
|
1872
1856
|
end
|
1873
1857
|
end
|
1874
1858
|
|
1875
|
-
return if opts[:read_only]
|
1859
|
+
return if opts[:read_only]
|
1876
1860
|
|
1877
|
-
|
1878
|
-
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
1882
|
-
end
|
1861
|
+
if one_through_one
|
1862
|
+
opts[:setter] ||= proc do |o|
|
1863
|
+
h = {}
|
1864
|
+
lh = lcks.zip(lcpks.map{|k| get_column_value(k)})
|
1865
|
+
jtds = _join_table_dataset(opts).where(lh)
|
1883
1866
|
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
1867
|
+
checked_transaction do
|
1868
|
+
current = jtds.first
|
1869
|
+
|
1870
|
+
if o
|
1871
|
+
new_values = []
|
1872
|
+
rcks.zip(opts.right_primary_key_methods).each{|k, pk| new_values << (h[k] = o.get_column_value(pk))}
|
1873
|
+
end
|
1887
1874
|
|
1888
|
-
|
1889
|
-
|
1875
|
+
if current
|
1876
|
+
current_values = rcks.map{|k| current[k]}
|
1877
|
+
jtds = jtds.where(rcks.zip(current_values))
|
1878
|
+
if o
|
1879
|
+
if current_values != new_values
|
1880
|
+
jtds.update(h)
|
1881
|
+
end
|
1882
|
+
else
|
1883
|
+
jtds.delete
|
1884
|
+
end
|
1885
|
+
elsif o
|
1886
|
+
lh.each{|k,v| h[k] = v}
|
1887
|
+
jtds.insert(h)
|
1888
|
+
end
|
1889
|
+
end
|
1890
|
+
end
|
1891
|
+
opts[:_setter] = proc{|o| set_one_through_one_associated_object(opts, o)}
|
1892
|
+
else
|
1893
|
+
opts[:adder] ||= proc do |o|
|
1894
|
+
h = {}
|
1895
|
+
lcks.zip(lcpks).each{|k, pk| h[k] = get_column_value(pk)}
|
1896
|
+
rcks.zip(opts.right_primary_key_methods).each{|k, pk| h[k] = o.get_column_value(pk)}
|
1897
|
+
_join_table_dataset(opts).insert(h)
|
1898
|
+
end
|
1899
|
+
|
1900
|
+
opts[:remover] ||= proc do |o|
|
1901
|
+
_join_table_dataset(opts).where(lcks.zip(lcpks.map{|k| get_column_value(k)}) + rcks.zip(opts.right_primary_key_methods.map{|k| o.get_column_value(k)})).delete
|
1902
|
+
end
|
1903
|
+
|
1904
|
+
opts[:clearer] ||= proc do
|
1905
|
+
_join_table_dataset(opts).where(lcks.zip(lcpks.map{|k| get_column_value(k)})).delete
|
1906
|
+
end
|
1890
1907
|
end
|
1891
1908
|
end
|
1892
1909
|
|
@@ -2242,18 +2259,34 @@ module Sequel
|
|
2242
2259
|
self
|
2243
2260
|
end
|
2244
2261
|
|
2245
|
-
#
|
2246
|
-
|
2247
|
-
|
2248
|
-
|
2249
|
-
|
2250
|
-
|
2262
|
+
# Handle parsing of options when loading associations. For historical
|
2263
|
+
# reasons, you can pass true/false/nil or a callable argument to
|
2264
|
+
# associations. That will be going away in Sequel 5, but we'll still
|
2265
|
+
# support it until then.
|
2266
|
+
def load_association_objects_options(dynamic_opts, &block)
|
2267
|
+
dynamic_opts = case dynamic_opts
|
2268
|
+
when true, false, nil
|
2269
|
+
{:reload=>dynamic_opts}
|
2270
|
+
when Hash
|
2271
|
+
Hash[dynamic_opts]
|
2272
|
+
else
|
2273
|
+
if dynamic_opts.respond_to?(:call)
|
2274
|
+
{:callback=>dynamic_opts}
|
2275
|
+
end
|
2251
2276
|
end
|
2277
|
+
|
2252
2278
|
if block_given?
|
2253
|
-
dynamic_opts =
|
2279
|
+
dynamic_opts[:callback] = block
|
2254
2280
|
end
|
2281
|
+
|
2282
|
+
dynamic_opts
|
2283
|
+
end
|
2284
|
+
|
2285
|
+
# Load the associated objects using the dataset, handling callbacks, reciprocals, and caching.
|
2286
|
+
def load_associated_objects(opts, dynamic_opts=nil, &block)
|
2287
|
+
dynamic_opts = load_association_objects_options(dynamic_opts, &block)
|
2255
2288
|
name = opts[:name]
|
2256
|
-
if associations.include?(name)
|
2289
|
+
if associations.include?(name) && !dynamic_opts[:callback] && !dynamic_opts[:reload]
|
2257
2290
|
associations[name]
|
2258
2291
|
else
|
2259
2292
|
objs = _load_associated_objects(opts, dynamic_opts)
|
@@ -2386,6 +2419,13 @@ module Sequel
|
|
2386
2419
|
_set_associated_object(opts, o)
|
2387
2420
|
end
|
2388
2421
|
|
2422
|
+
# Set the given object as the associated object for the given one_through_one association reflection
|
2423
|
+
def set_one_through_one_associated_object(opts, o)
|
2424
|
+
raise(Error, "object #{inspect} does not have a primary key") unless pk
|
2425
|
+
raise(Error, "associated object #{o.inspect} does not have a primary key") if o && !o.pk
|
2426
|
+
_set_associated_object(opts, o)
|
2427
|
+
end
|
2428
|
+
|
2389
2429
|
# Set the given object as the associated object for the given one_to_one association reflection
|
2390
2430
|
def set_one_to_one_associated_object(opts, o)
|
2391
2431
|
raise(Error, "object #{inspect} does not have a primary key") unless pk
|