sequel 4.18.0 → 4.19.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 +18 -0
- data/MIT-LICENSE +1 -1
- data/doc/advanced_associations.rdoc +1 -1
- data/doc/association_basics.rdoc +55 -34
- data/doc/model_hooks.rdoc +7 -5
- data/doc/release_notes/4.19.0.txt +45 -0
- data/doc/validations.rdoc +4 -0
- data/lib/sequel/adapters/shared/mysql.rb +5 -3
- data/lib/sequel/adapters/shared/sqlanywhere.rb +3 -2
- data/lib/sequel/dataset/sql.rb +1 -1
- data/lib/sequel/extensions/migration.rb +12 -8
- data/lib/sequel/model/associations.rb +24 -24
- data/lib/sequel/model/base.rb +39 -8
- data/lib/sequel/plugins/accessed_columns.rb +61 -0
- data/lib/sequel/plugins/association_pks.rb +4 -4
- data/lib/sequel/plugins/boolean_readers.rb +1 -1
- data/lib/sequel/plugins/class_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/column_conflicts.rb +93 -0
- data/lib/sequel/plugins/composition.rb +3 -3
- data/lib/sequel/plugins/dirty.rb +6 -6
- data/lib/sequel/plugins/json_serializer.rb +1 -1
- data/lib/sequel/plugins/list.rb +4 -4
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +2 -2
- data/lib/sequel/plugins/optimistic_locking.rb +3 -3
- data/lib/sequel/plugins/pg_array_associations.rb +23 -23
- data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +2 -2
- data/lib/sequel/plugins/serialization.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/timestamps.rb +2 -2
- data/lib/sequel/plugins/typecast_on_load.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +4 -4
- data/lib/sequel/plugins/validation_helpers.rb +2 -2
- data/lib/sequel/version.rb +1 -1
- data/spec/core/dataset_spec.rb +7 -0
- data/spec/extensions/accessed_columns_spec.rb +51 -0
- data/spec/extensions/column_conflicts_spec.rb +55 -0
- data/spec/extensions/hook_class_methods_spec.rb +18 -5
- data/spec/extensions/migration_spec.rb +4 -1
- data/spec/extensions/static_cache_spec.rb +3 -3
- data/spec/model/hooks_spec.rb +76 -9
- data/spec/model/record_spec.rb +43 -2
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce1762f276f7bfdac15fe395f0eef9696c185397
|
4
|
+
data.tar.gz: f1164599a6a4bccd41e20d7ff36f443e6a46551f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31ecc2aef0b4d68eb9424f60cd2b1b7256b8916ca57d5fe6b74c5d3681e0b72a73014fa7225c4a87c87ee23656699ea85d027d919ac30613aa99269007676f22
|
7
|
+
data.tar.gz: fe8a6d58fab4a544a5cc5168b6721dc7d72c93567b8d17d04a940efd0ac4fb5dcf5bbe6968ed8fe9e6d52c30dbde418d571567b7f49103ec20f9f86cf9a82a7c
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
=== 4.19.0 (2015-02-01)
|
2
|
+
|
3
|
+
* Make jdbc/sqlanywhere correctly set :auto_increment entry in schema hashes (jeremyevans)
|
4
|
+
|
5
|
+
* Add Model#cancel_action for canceling actions in before hooks, instead of having the hooks return false (jeremyevans)
|
6
|
+
|
7
|
+
* Support not setting @@wait_timeout on MySQL via :timeout=>nil Database option (jeremyevans)
|
8
|
+
|
9
|
+
* Add accessed_columns plugin, recording which columns have been accessed for a model instance (jeremyevans)
|
10
|
+
|
11
|
+
* Use correct migration version when using IntegerMigrator with :allow_missing_migration_files (blerins) (#938)
|
12
|
+
|
13
|
+
* Make Dataset#union, #intersect, and #except automatically handle datasets with raw SQL (jeremyevans) (#934)
|
14
|
+
|
15
|
+
* Add column_conflicts plugin to automatically handle columns that conflict with method names (jeremyevans) (#929)
|
16
|
+
|
17
|
+
* Add Model#get_column_value and #set_column_value to get/set column values (jeremyevans) (#929)
|
18
|
+
|
1
19
|
=== 4.18.0 (2015-01-02)
|
2
20
|
|
3
21
|
* Make Dataset#empty? work when the dataset is ordered by a non-column expression (pete) (#923)
|
data/MIT-LICENSE
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
Copyright (c) 2007-2008 Sharon Rosner
|
2
|
-
Copyright (c) 2008-
|
2
|
+
Copyright (c) 2008-2015 Jeremy Evans
|
3
3
|
|
4
4
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
of this software and associated documentation files (the "Software"), to
|
@@ -457,7 +457,7 @@ array of symbols and procs. For <tt>:after_load</tt> with a *_to_many associati
|
|
457
457
|
the associated object argument is an array of associated objects.
|
458
458
|
|
459
459
|
If any of the before callbacks return +false+, the adding/removing
|
460
|
-
does not happen and it either raises a <tt>Sequel::
|
460
|
+
does not happen and it either raises a <tt>Sequel::HookFailed</tt> (the default), or
|
461
461
|
returns false (if +raise_on_save_failure+ is false).
|
462
462
|
|
463
463
|
=== Association extensions
|
data/doc/association_basics.rdoc
CHANGED
@@ -304,6 +304,11 @@ Examples:
|
|
304
304
|
|
305
305
|
one_through_one associations do not have any modification methods added.
|
306
306
|
|
307
|
+
Note that the remove_all_* method does not call remove hooks defined on
|
308
|
+
the association, it just issues a single query to the database. If you
|
309
|
+
want to remove all associated objects and call remove hooks, iterate
|
310
|
+
over the array of associated objects and call remove_* for each.
|
311
|
+
|
307
312
|
== Caching
|
308
313
|
|
309
314
|
Associations are cached after being retrieved:
|
@@ -1165,16 +1170,18 @@ Called after adding an object to the association:
|
|
1165
1170
|
|
1166
1171
|
==== :before_remove [+one_to_many+, +many_to_many+]
|
1167
1172
|
|
1168
|
-
Called before removing an object from the association
|
1173
|
+
Called before removing an object from the association using <tt>remove_<i>association</i></tt>:
|
1169
1174
|
|
1170
1175
|
class Artist
|
1171
1176
|
# Don't allow removing a self-titled album
|
1172
1177
|
one_to_many :albums, :before_remove=>proc{|ar, al| false if al.name == ar.name}
|
1173
1178
|
end
|
1174
1179
|
|
1180
|
+
This is not called when using <tt>remove_all_<i>association</i></tt>.
|
1181
|
+
|
1175
1182
|
==== :after_remove [+one_to_many+, +many_to_many+]
|
1176
1183
|
|
1177
|
-
Called after removing an object from the association
|
1184
|
+
Called after removing an object from the association using <tt>remove_<i>association</i></tt>:
|
1178
1185
|
|
1179
1186
|
class Artist
|
1180
1187
|
# Log all disassociations of albums to an audit logging table
|
@@ -1187,6 +1194,8 @@ Called after removing an object from the association:
|
|
1187
1194
|
end
|
1188
1195
|
end
|
1189
1196
|
|
1197
|
+
This is not called when using <tt>remove_all_<i>association</i></tt>.
|
1198
|
+
|
1190
1199
|
==== :before_set [+many_to_one+, +one_to_one+]
|
1191
1200
|
|
1192
1201
|
Called before the _<i>association</i>= method is called to modify the objects:
|
@@ -1490,72 +1499,84 @@ by the foreign/primary keys. This option causes the
|
|
1490
1499
|
you want to replace the default foreign/primary key conditions that Sequel
|
1491
1500
|
would use when eagerly graphing.
|
1492
1501
|
|
1493
|
-
===
|
1502
|
+
=== Associations Based on SQL Expressions Options
|
1494
1503
|
|
1495
|
-
Sequel's
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
if you want to name the association the same name as an existing column, or
|
1501
|
-
if the column has the same name as an already defined method such as
|
1502
|
-
<tt>object_id</tt>.
|
1504
|
+
Sequel's associations can work not just with columns, but also with
|
1505
|
+
arbitrary SQL expressions. For example, on PostgreSQL, you can store
|
1506
|
+
foreign keys to other tables in hstore, json, or jsonb columns, and Sequel
|
1507
|
+
can automatically work with such constructs, including full support for
|
1508
|
+
eager loading.
|
1503
1509
|
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1510
|
+
There's actually two parts to supporting associations based on SQL
|
1511
|
+
expressions. First is you must have an instance method in the model
|
1512
|
+
that returns the value that the SQL expression would return. Second
|
1513
|
+
is you must have an SQL expression object. If Sequel has access to
|
1514
|
+
a model instance and needs to get the value of the expression, it
|
1515
|
+
calls the method to get the value. If Sequel does not have access
|
1516
|
+
to a model instance, but needs to use the SQL expression in a query,
|
1517
|
+
it will use the SQL expression object.
|
1518
|
+
|
1519
|
+
Below is an example storing foreign keys to other tables in a
|
1520
|
+
PostgreSQL hstore column, using the +pg_hstore+ and +pg_hstore_ops+
|
1521
|
+
extensions.
|
1508
1522
|
|
1509
1523
|
# Example schema:
|
1510
|
-
# albums
|
1511
|
-
# :id
|
1512
|
-
# :
|
1524
|
+
# albums artists
|
1525
|
+
# :id /---> :id
|
1526
|
+
# :meta ---/ :name
|
1513
1527
|
# :name
|
1514
1528
|
class Album < Sequel::Model
|
1515
|
-
|
1516
|
-
|
1529
|
+
many_to_one :artist, :key_column=>Sequel.cast(Sequel.hstore(:meta)['artist_id'], Integer)
|
1530
|
+
|
1531
|
+
def artist_id
|
1532
|
+
meta['artist_id'].to_i
|
1533
|
+
end
|
1534
|
+
end
|
1535
|
+
class Artist < Sequel::Model
|
1536
|
+
one_to_many :albums, :key=>Sequel.cast(Sequel.hstore(:meta)['artist_id'], Integer), :key_method=>:artist_id
|
1517
1537
|
end
|
1518
1538
|
|
1519
1539
|
# Example schema:
|
1520
|
-
#
|
1521
|
-
# :id
|
1522
|
-
# :
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1540
|
+
# albums albums_artists artists
|
1541
|
+
# :id <----- :meta -------> :id
|
1542
|
+
# :name :name
|
1543
|
+
class Album < Sequel::Model
|
1544
|
+
many_to_many :artists, :left_key=>Sequel.cast(Sequel.hstore(:meta)['album_id'], Integer),
|
1545
|
+
:right_key=>Sequel.cast(Sequel.hstore(:meta)['artist_id'], Integer)
|
1526
1546
|
end
|
1527
|
-
class
|
1528
|
-
|
1547
|
+
class Artist < Sequel::Model
|
1548
|
+
many_to_many :albums, :left_key=>Sequel.cast(Sequel.hstore(:meta)['artist_id'], Integer),
|
1549
|
+
:right_key=>Sequel.cast(Sequel.hstore(:meta)['album_id'], Integer)
|
1529
1550
|
end
|
1530
1551
|
|
1531
1552
|
==== :key_column [+many_to_one+]
|
1532
1553
|
|
1533
1554
|
Like the :key option, but :key references the method name, while
|
1534
|
-
:key_column references the underlying column.
|
1555
|
+
:key_column references the underlying column/expression.
|
1535
1556
|
|
1536
1557
|
==== :primary_key_method [+many_to_one+]
|
1537
1558
|
|
1538
|
-
Like the :primary_key option, but :primary_key references the column
|
1559
|
+
Like the :primary_key option, but :primary_key references the column/expression
|
1539
1560
|
name, while :primary_key_method references the method name.
|
1540
1561
|
|
1541
1562
|
==== :primary_key_column [+one_to_many+, +one_to_one+]
|
1542
1563
|
|
1543
1564
|
Like the :primary_key option, but :primary_key references the method name, while
|
1544
|
-
:primary_key_column references the underlying column.
|
1565
|
+
:primary_key_column references the underlying column/expression.
|
1545
1566
|
|
1546
1567
|
==== :key_method [+one_to_many+, +one_to_one+]
|
1547
1568
|
|
1548
|
-
Like the :key option, but :key references the column
|
1569
|
+
Like the :key option, but :key references the column/expression
|
1549
1570
|
name, while :key_method references the method name.
|
1550
1571
|
|
1551
1572
|
==== :left_primary_key_column [+many_to_many+, +one_through_one+]
|
1552
1573
|
|
1553
1574
|
Like the :left_primary_key option, but :left_primary_key references the method name, while
|
1554
|
-
:left_primary_key_column references the underlying column.
|
1575
|
+
:left_primary_key_column references the underlying column/expression.
|
1555
1576
|
|
1556
1577
|
==== :right_primary_key_method [+many_to_many+, +one_through_one+]
|
1557
1578
|
|
1558
|
-
Like the :right_primary_key option, but :right_primary_key references the column
|
1579
|
+
Like the :right_primary_key option, but :right_primary_key references the column/expression
|
1559
1580
|
name, while :right_primary_key_method references the method name.
|
1560
1581
|
|
1561
1582
|
=== Private Method Overriding Options
|
data/doc/model_hooks.rdoc
CHANGED
@@ -127,20 +127,22 @@ If you want to insert a row into the model's table without running the creation
|
|
127
127
|
|
128
128
|
Album.insert(:name=>'RF') # does not run hooks
|
129
129
|
|
130
|
-
==
|
130
|
+
== Canceling Actions in Hooks
|
131
131
|
|
132
|
-
|
132
|
+
Sometimes want to cancel an action in a before hook, so the action is not performed. For example, you may want to not allow destroying or saving a record in certain cases. In those cases, you can call +cancel_action+ inside the <tt>before_*</tt> hook, which will stop processing the hook and will either raise a <tt>Sequel::HookFailed</tt> exception (the default), or return +nil+ if +raise_on_save_failure+ is +false+). You can use this to implement validation-like behavior, that will run even if validations are skipped:
|
133
133
|
|
134
134
|
class Album < Sequel::Model
|
135
135
|
def before_save
|
136
|
-
|
136
|
+
cancel_action if name == ''
|
137
137
|
super
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
|
-
|
141
|
+
For backwards compatibility, Sequel also treats the <tt>before_*</tt> hook methods returning +false+ as an indication that the action should be canceled. This usage is discouraged in new code, but you should be aware of this behavior so that you do not inadvertently return false.
|
142
142
|
|
143
|
-
|
143
|
+
For around hooks, neglecting to call +super+ halts hook processing in the same way as calling +cancel_action+ in a before hook. It's probably a bad idea to use +cancel_action+ hook processing in after hooks, or after yielding in around hooks, since by then the main processing has already taken place.
|
144
|
+
|
145
|
+
By default, Sequel runs hooks other than validation hooks inside a transaction, so if you cancel the action by calling +cancel_action+ in any hook, Sequel will rollback the transaction. However, note that the implicit use of transactions when saving and destroying model objects is conditional (it depends on the model instance's +use_transactions+ setting and the <tt>:transaction</tt> option passed to save).
|
144
146
|
|
145
147
|
== Conditional Hooks
|
146
148
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* Model#get_column_value and #set_column_value have been added for
|
4
|
+
getting/setting column values. Historically, to get column
|
5
|
+
values, you would just send the column name, and to set column
|
6
|
+
values you would send the column name suffixed by =. However,
|
7
|
+
this doesn't work when such methods are already defined by
|
8
|
+
ruby or Sequel itself (e.g. class, model, object_id).
|
9
|
+
|
10
|
+
Both #get_column_value and #set_column_value are just aliases to
|
11
|
+
#send, but you can safely override the methods to handle column
|
12
|
+
names that conflict with existing method names. Both the core
|
13
|
+
model code and all of the plugins that ship with Sequel have
|
14
|
+
been updated to use these new methods. External plugins are
|
15
|
+
strongly encouraged to switch to these new methods.
|
16
|
+
|
17
|
+
* A column_conflicts plugin has been added to automatically handle
|
18
|
+
columns that conflict with existing method names. So if you
|
19
|
+
have a column named "model" in your table, you can just load the
|
20
|
+
column_conflicts plugin and Sequel will handle things correctly.
|
21
|
+
|
22
|
+
* A accessed_columns plugin has been added, which records which
|
23
|
+
columns have been accessed for a model instance. This is useful
|
24
|
+
in development when you are planning on restricted the columns
|
25
|
+
selected by the dataset that retrieved the instance. SELECTing
|
26
|
+
only the columns you need can result in significant performance
|
27
|
+
increases, and the accessed_columns plugin makes that easier.
|
28
|
+
|
29
|
+
* Model#cancel_action has been added for canceling actions in
|
30
|
+
before hooks, instead of having the before hook methods return
|
31
|
+
false (which is still supported). In addition to being easier to
|
32
|
+
use, this also makes it possible to use custom exception messages
|
33
|
+
for hook failures, if you are using the default behavior of raising
|
34
|
+
exceptions on save failures.
|
35
|
+
|
36
|
+
= Other Improvements
|
37
|
+
|
38
|
+
* Dataset#union, #intersect, and #except now automatically handle
|
39
|
+
datasets with raw SQL, by wrapping such datasets in subqueries.
|
40
|
+
|
41
|
+
* The integer migrator now stores the correct migration number
|
42
|
+
when migrating with allow_missing_migration_files set.
|
43
|
+
|
44
|
+
* A :timeout=>nil Database option on MySQL no longer sets a
|
45
|
+
wait_timeout.
|
data/doc/validations.rdoc
CHANGED
@@ -353,6 +353,10 @@ The <tt>:allow_blank</tt> is similar to the <tt>:allow_nil</tt> option, but inst
|
|
353
353
|
a.website = ''
|
354
354
|
a.valid? # true
|
355
355
|
|
356
|
+
If you are going to use <tt>:allow_blank</tt> you should make sure that all objects respond to the blank? method. Sequel ships with an extension that will do this for you:
|
357
|
+
|
358
|
+
Sequel.extension :blank
|
359
|
+
|
356
360
|
=== <tt>:allow_missing</tt>
|
357
361
|
|
358
362
|
The <tt>:allow_missing</tt> option is different from the <tt>:allow_nil</tt> option, in that instead of checking if the attribute value is nil, it checks if the attribute is present in the model instance's values hash. <tt>:allow_nil</tt> will skip the validation when the attribute is in the values hash and has a nil value and when the attribute is not in the values hash. <tt>:allow_missing</tt> will only skip the validation when the attribute is not in the values hash. If the attribute is in the values hash but has a nil value, <tt>:allow_missing</tt> will not skip it.
|
@@ -274,9 +274,11 @@ module Sequel
|
|
274
274
|
def mysql_connection_setting_sqls
|
275
275
|
sqls = []
|
276
276
|
|
277
|
-
|
278
|
-
|
279
|
-
|
277
|
+
if wait_timeout = opts.fetch(:timeout, 2147483)
|
278
|
+
# Increase timeout so mysql server doesn't disconnect us
|
279
|
+
# Value used by default is maximum allowed value on Windows.
|
280
|
+
sqls << "SET @@wait_timeout = #{wait_timeout}"
|
281
|
+
end
|
280
282
|
|
281
283
|
# By default, MySQL 'where id is null' selects the last inserted id
|
282
284
|
sqls << "SET SQL_AUTO_IS_NULL=0" unless opts[:auto_is_null]
|
@@ -56,8 +56,9 @@ module Sequel
|
|
56
56
|
from{sa_describe_query("select * from #{im.call(table)}").as(:a)}.
|
57
57
|
join(:syscolumn___b, :table_id=>:base_table_id, :column_id=>:base_column_id).
|
58
58
|
order(:a__column_number).
|
59
|
-
|
60
|
-
|
59
|
+
map do |row|
|
60
|
+
auto_increment = row.delete(:is_autoincrement)
|
61
|
+
row[:auto_increment] = auto_increment == 1 || auto_increment == true
|
61
62
|
row[:primary_key] = row.delete(:pkey) == 'Y'
|
62
63
|
row[:allow_null] = row[:nulls_allowed].is_a?(Fixnum) ? row.delete(:nulls_allowed) == 1 : row.delete(:nulls_allowed)
|
63
64
|
row[:db_type] = row.delete(:domain_name)
|
data/lib/sequel/dataset/sql.rb
CHANGED
@@ -827,7 +827,7 @@ module Sequel
|
|
827
827
|
# Return a from_self dataset if an order or limit is specified, so it works as expected
|
828
828
|
# with UNION, EXCEPT, and INTERSECT clauses.
|
829
829
|
def compound_from_self
|
830
|
-
(@opts[:limit] || @opts[:order]) ? from_self : self
|
830
|
+
(@opts[:sql] || @opts[:limit] || @opts[:order]) ? from_self : self
|
831
831
|
end
|
832
832
|
|
833
833
|
private
|
@@ -523,13 +523,12 @@ module Sequel
|
|
523
523
|
def run
|
524
524
|
migrations.zip(version_numbers).each do |m, v|
|
525
525
|
t = Time.now
|
526
|
-
|
527
|
-
db.log_info("Begin applying migration version #{lv}, direction: #{direction}")
|
526
|
+
db.log_info("Begin applying migration version #{v}, direction: #{direction}")
|
528
527
|
checked_transaction(m) do
|
529
528
|
m.apply(db, direction)
|
530
|
-
set_migration_version(v)
|
529
|
+
set_migration_version(up? ? v : v-1)
|
531
530
|
end
|
532
|
-
db.log_info("Finished applying migration version #{
|
531
|
+
db.log_info("Finished applying migration version #{v}, direction: #{direction}, took #{sprintf('%0.6f', Time.now - t)} seconds")
|
533
532
|
end
|
534
533
|
|
535
534
|
target
|
@@ -565,11 +564,10 @@ module Sequel
|
|
565
564
|
remove_migration_classes
|
566
565
|
|
567
566
|
# load migration files
|
568
|
-
|
567
|
+
version_numbers.each{|n| load(files[n])}
|
569
568
|
|
570
569
|
# get migration classes
|
571
|
-
|
572
|
-
up? ? classes : classes.reverse
|
570
|
+
Migration.descendants
|
573
571
|
end
|
574
572
|
|
575
573
|
# Returns the latest version available in the specified directory.
|
@@ -606,7 +604,13 @@ module Sequel
|
|
606
604
|
# so that each number in the array is the migration version
|
607
605
|
# that will be in affect after the migration is run.
|
608
606
|
def version_numbers
|
609
|
-
|
607
|
+
versions = files.
|
608
|
+
compact.
|
609
|
+
map{|f| migration_version_from_file(File.basename(f))}.
|
610
|
+
select{|v| up? ? (v > current && v <= target) : (v <= current && v > target)}.
|
611
|
+
sort
|
612
|
+
versions.reverse! unless up?
|
613
|
+
versions
|
610
614
|
end
|
611
615
|
end
|
612
616
|
|
@@ -355,7 +355,7 @@ module Sequel
|
|
355
355
|
|
356
356
|
# The values that predicate_keys should match for objects to be associated.
|
357
357
|
def predicate_key_values(object)
|
358
|
-
predicate_key_methods.map{|k| object.
|
358
|
+
predicate_key_methods.map{|k| object.get_column_value(k)}
|
359
359
|
end
|
360
360
|
|
361
361
|
# Qualify +col+ with the given table name. If +col+ is an array of columns,
|
@@ -732,7 +732,7 @@ module Sequel
|
|
732
732
|
# many_to_one associations can only have associated objects if none of
|
733
733
|
# the :keys options have a nil value.
|
734
734
|
def can_have_associated_objects?(obj)
|
735
|
-
!self[:keys].any?{|k| obj.
|
735
|
+
!self[:keys].any?{|k| obj.get_column_value(k).nil?}
|
736
736
|
end
|
737
737
|
|
738
738
|
# Whether the dataset needs a primary key to function, false for many_to_one associations.
|
@@ -897,7 +897,7 @@ module Sequel
|
|
897
897
|
# one_to_many associations can only have associated objects if none of
|
898
898
|
# the :keys options have a nil value.
|
899
899
|
def can_have_associated_objects?(obj)
|
900
|
-
!self[:primary_keys].any?{|k| obj.
|
900
|
+
!self[:primary_keys].any?{|k| obj.get_column_value(k).nil?}
|
901
901
|
end
|
902
902
|
|
903
903
|
# one_to_many and one_to_one associations can be clones
|
@@ -1120,7 +1120,7 @@ module Sequel
|
|
1120
1120
|
# many_to_many associations can only have associated objects if none of
|
1121
1121
|
# the :left_primary_keys options have a nil value.
|
1122
1122
|
def can_have_associated_objects?(obj)
|
1123
|
-
!self[:left_primary_keys].any?{|k| obj.
|
1123
|
+
!self[:left_primary_keys].any?{|k| obj.get_column_value(k).nil?}
|
1124
1124
|
end
|
1125
1125
|
|
1126
1126
|
# one_through_one and many_to_many associations can be clones
|
@@ -1851,17 +1851,17 @@ module Sequel
|
|
1851
1851
|
|
1852
1852
|
opts[:adder] ||= proc do |o|
|
1853
1853
|
h = {}
|
1854
|
-
lcks.zip(lcpks).each{|k, pk| h[k] =
|
1855
|
-
rcks.zip(opts.right_primary_key_methods).each{|k, pk| h[k] = o.
|
1854
|
+
lcks.zip(lcpks).each{|k, pk| h[k] = get_column_value(pk)}
|
1855
|
+
rcks.zip(opts.right_primary_key_methods).each{|k, pk| h[k] = o.get_column_value(pk)}
|
1856
1856
|
_join_table_dataset(opts).insert(h)
|
1857
1857
|
end
|
1858
1858
|
|
1859
1859
|
opts[:remover] ||= proc do |o|
|
1860
|
-
_join_table_dataset(opts).where(lcks.zip(lcpks.map{|k|
|
1860
|
+
_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
|
1861
1861
|
end
|
1862
1862
|
|
1863
1863
|
opts[:clearer] ||= proc do
|
1864
|
-
_join_table_dataset(opts).where(lcks.zip(lcpks.map{|k|
|
1864
|
+
_join_table_dataset(opts).where(lcks.zip(lcpks.map{|k| get_column_value(k)})).delete
|
1865
1865
|
end
|
1866
1866
|
end
|
1867
1867
|
|
@@ -1898,7 +1898,7 @@ module Sequel
|
|
1898
1898
|
pk_meths = opts.primary_key_methods
|
1899
1899
|
|
1900
1900
|
eager_load_results(opts, eo) do |assoc_record|
|
1901
|
-
hash_key = uses_cks ? pk_meths.map{|k| assoc_record.
|
1901
|
+
hash_key = uses_cks ? pk_meths.map{|k| assoc_record.get_column_value(k)} : assoc_record.get_column_value(opts.primary_key_method)
|
1902
1902
|
if objects = h[hash_key]
|
1903
1903
|
objects.each{|object| object.associations[name] = assoc_record}
|
1904
1904
|
end
|
@@ -1919,7 +1919,7 @@ module Sequel
|
|
1919
1919
|
|
1920
1920
|
return if opts[:read_only]
|
1921
1921
|
|
1922
|
-
opts[:setter] ||= proc{|o| cks.zip(opts.primary_key_methods).each{|k, pk|
|
1922
|
+
opts[:setter] ||= proc{|o| cks.zip(opts.primary_key_methods).each{|k, pk| set_column_value(:"#{k}=", (o.get_column_value(pk) if o))}}
|
1923
1923
|
opts[:_setter] = proc{|o| set_associated_object(opts, o)}
|
1924
1924
|
end
|
1925
1925
|
|
@@ -1947,7 +1947,7 @@ module Sequel
|
|
1947
1947
|
|
1948
1948
|
eager_load_results(opts, eo) do |assoc_record|
|
1949
1949
|
assoc_record.values.delete(delete_rn) if delete_rn
|
1950
|
-
hash_key = uses_cks ? km.map{|k| assoc_record.
|
1950
|
+
hash_key = uses_cks ? km.map{|k| assoc_record.get_column_value(k)} : assoc_record.get_column_value(km)
|
1951
1951
|
next unless objects = h[hash_key]
|
1952
1952
|
if assign_singular
|
1953
1953
|
objects.each do |object|
|
@@ -1988,10 +1988,10 @@ module Sequel
|
|
1988
1988
|
|
1989
1989
|
if one_to_one
|
1990
1990
|
opts[:setter] ||= proc do |o|
|
1991
|
-
up_ds = _apply_association_options(opts, opts.associated_dataset.where(cks.zip(cpks.map{|k|
|
1991
|
+
up_ds = _apply_association_options(opts, opts.associated_dataset.where(cks.zip(cpks.map{|k| get_column_value(k)})))
|
1992
1992
|
if o
|
1993
1993
|
up_ds = up_ds.exclude(o.pk_hash) unless o.new?
|
1994
|
-
cks.zip(cpks).each{|k, pk| o.
|
1994
|
+
cks.zip(cpks).each{|k, pk| o.set_column_value(:"#{k}=", get_column_value(pk))}
|
1995
1995
|
end
|
1996
1996
|
checked_transaction do
|
1997
1997
|
up_ds.update(ck_nil_hash)
|
@@ -2003,17 +2003,17 @@ module Sequel
|
|
2003
2003
|
save_opts[:raise_on_failure] = opts[:raise_on_save_failure] != false
|
2004
2004
|
|
2005
2005
|
opts[:adder] ||= proc do |o|
|
2006
|
-
cks.zip(cpks).each{|k, pk| o.
|
2006
|
+
cks.zip(cpks).each{|k, pk| o.set_column_value(:"#{k}=", get_column_value(pk))}
|
2007
2007
|
o.save(save_opts)
|
2008
2008
|
end
|
2009
2009
|
|
2010
2010
|
opts[:remover] ||= proc do |o|
|
2011
|
-
cks.each{|k| o.
|
2011
|
+
cks.each{|k| o.set_column_value(:"#{k}=", nil)}
|
2012
2012
|
o.save(save_opts)
|
2013
2013
|
end
|
2014
2014
|
|
2015
2015
|
opts[:clearer] ||= proc do
|
2016
|
-
_apply_association_options(opts, opts.associated_dataset.where(cks.zip(cpks.map{|k|
|
2016
|
+
_apply_association_options(opts, opts.associated_dataset.where(cks.zip(cpks.map{|k| get_column_value(k)}))).update(ck_nil_hash)
|
2017
2017
|
end
|
2018
2018
|
end
|
2019
2019
|
end
|
@@ -2115,7 +2115,7 @@ module Sequel
|
|
2115
2115
|
|
2116
2116
|
# Return the associated single object using a primary key lookup on the associated class.
|
2117
2117
|
def _load_associated_object_via_primary_key(opts)
|
2118
|
-
opts.associated_class.send(:primary_key_lookup, ((fk = opts[:key]).is_a?(Array) ? fk.map{|c|
|
2118
|
+
opts.associated_class.send(:primary_key_lookup, ((fk = opts[:key]).is_a?(Array) ? fk.map{|c| get_column_value(c)} : get_column_value(fk)))
|
2119
2119
|
end
|
2120
2120
|
|
2121
2121
|
# Load the associated objects for the given association reflection and dynamic options
|
@@ -2315,7 +2315,7 @@ module Sequel
|
|
2315
2315
|
raise Error, "callbacks should either be Procs or Symbols"
|
2316
2316
|
end
|
2317
2317
|
if res == false and stop_on_false
|
2318
|
-
raise(
|
2318
|
+
raise(HookFailed, "Unable to modify association for #{inspect}: one of the #{callback_type} hooks returned false") if raise_error
|
2319
2319
|
return false
|
2320
2320
|
end
|
2321
2321
|
end
|
@@ -2729,17 +2729,17 @@ END
|
|
2729
2729
|
vals = if obj.is_a?(Sequel::Dataset)
|
2730
2730
|
{(keys.length == 1 ? keys.first : keys)=>obj.select(*meths).exclude(Sequel::SQL::BooleanExpression.from_value_pairs(meths.zip([]), :OR))}
|
2731
2731
|
else
|
2732
|
-
vals = Array(obj).reject{|o| !meths.all?{|m| o.
|
2732
|
+
vals = Array(obj).reject{|o| !meths.all?{|m| o.get_column_value(m)}}
|
2733
2733
|
return SQL::Constants::FALSE if vals.empty?
|
2734
2734
|
if obj.is_a?(Array)
|
2735
2735
|
if keys.length == 1
|
2736
2736
|
meth = meths.first
|
2737
|
-
{keys.first=>vals.map{|o| o.
|
2737
|
+
{keys.first=>vals.map{|o| o.get_column_value(meth)}}
|
2738
2738
|
else
|
2739
|
-
{keys=>vals.map{|o| meths.map{|m| o.
|
2739
|
+
{keys=>vals.map{|o| meths.map{|m| o.get_column_value(m)}}}
|
2740
2740
|
end
|
2741
2741
|
else
|
2742
|
-
keys.zip(meths.map{|k| obj.
|
2742
|
+
keys.zip(meths.map{|k| obj.get_column_value(k)})
|
2743
2743
|
end
|
2744
2744
|
end
|
2745
2745
|
SQL::BooleanExpression.from_value_pairs(vals)
|
@@ -2786,11 +2786,11 @@ END
|
|
2786
2786
|
a.each do |rec|
|
2787
2787
|
case key
|
2788
2788
|
when Array
|
2789
|
-
if (k = key.map{|k2| rec.
|
2789
|
+
if (k = key.map{|k2| rec.get_column_value(k2)}) && k.all?
|
2790
2790
|
id_map[k] << rec
|
2791
2791
|
end
|
2792
2792
|
when Symbol
|
2793
|
-
if k = rec.
|
2793
|
+
if k = rec.get_column_value(key)
|
2794
2794
|
id_map[k] << rec
|
2795
2795
|
end
|
2796
2796
|
else
|