sequel 4.18.0 → 4.19.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|