sequel 3.37.0 → 3.38.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +56 -0
- data/README.rdoc +82 -58
- data/Rakefile +6 -5
- data/bin/sequel +1 -1
- data/doc/active_record.rdoc +67 -52
- data/doc/advanced_associations.rdoc +33 -48
- data/doc/association_basics.rdoc +41 -51
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +47 -43
- data/doc/mass_assignment.rdoc +1 -1
- data/doc/migration.rdoc +4 -5
- data/doc/model_hooks.rdoc +3 -3
- data/doc/object_model.rdoc +31 -25
- data/doc/opening_databases.rdoc +19 -5
- data/doc/prepared_statements.rdoc +2 -2
- data/doc/querying.rdoc +109 -52
- data/doc/reflection.rdoc +6 -6
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/schema_modification.rdoc +22 -13
- data/doc/sharding.rdoc +8 -9
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +47 -7
- data/doc/thread_safety.rdoc +1 -1
- data/doc/transactions.rdoc +1 -1
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +29 -43
- data/lib/sequel/adapters/do/postgres.rb +1 -4
- data/lib/sequel/adapters/jdbc.rb +14 -3
- data/lib/sequel/adapters/jdbc/db2.rb +9 -0
- data/lib/sequel/adapters/jdbc/derby.rb +41 -4
- data/lib/sequel/adapters/jdbc/jtds.rb +11 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -6
- data/lib/sequel/adapters/mock.rb +10 -4
- data/lib/sequel/adapters/postgres.rb +1 -28
- data/lib/sequel/adapters/shared/mssql.rb +23 -13
- data/lib/sequel/adapters/shared/postgres.rb +46 -0
- data/lib/sequel/adapters/swift.rb +21 -13
- data/lib/sequel/adapters/swift/mysql.rb +1 -0
- data/lib/sequel/adapters/swift/postgres.rb +4 -5
- data/lib/sequel/adapters/swift/sqlite.rb +2 -1
- data/lib/sequel/adapters/tinytds.rb +14 -2
- data/lib/sequel/adapters/utils/pg_types.rb +5 -0
- data/lib/sequel/core.rb +29 -17
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +3 -0
- data/lib/sequel/dataset/actions.rb +5 -6
- data/lib/sequel/dataset/query.rb +7 -7
- data/lib/sequel/dataset/sql.rb +5 -18
- data/lib/sequel/extensions/core_extensions.rb +8 -12
- data/lib/sequel/extensions/pg_array.rb +59 -33
- data/lib/sequel/extensions/pg_array_ops.rb +32 -4
- data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -1
- data/lib/sequel/extensions/pg_hstore.rb +32 -17
- data/lib/sequel/extensions/pg_hstore_ops.rb +32 -3
- data/lib/sequel/extensions/pg_inet.rb +1 -2
- data/lib/sequel/extensions/pg_interval.rb +0 -1
- data/lib/sequel/extensions/pg_json.rb +41 -23
- data/lib/sequel/extensions/pg_range.rb +36 -11
- data/lib/sequel/extensions/pg_range_ops.rb +32 -4
- data/lib/sequel/extensions/pg_row.rb +572 -0
- data/lib/sequel/extensions/pg_row_ops.rb +164 -0
- data/lib/sequel/extensions/query.rb +3 -3
- data/lib/sequel/extensions/schema_dumper.rb +7 -8
- data/lib/sequel/extensions/select_remove.rb +1 -1
- data/lib/sequel/model/base.rb +1 -0
- data/lib/sequel/no_core_ext.rb +1 -1
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/validation_helpers.rb +31 -0
- data/lib/sequel/sql.rb +64 -44
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +37 -12
- data/spec/adapters/mysql_spec.rb +39 -75
- data/spec/adapters/oracle_spec.rb +11 -11
- data/spec/adapters/postgres_spec.rb +414 -237
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +14 -14
- data/spec/core/database_spec.rb +6 -6
- data/spec/core/dataset_spec.rb +169 -205
- data/spec/core/expression_filters_spec.rb +182 -295
- data/spec/core/object_graph_spec.rb +6 -6
- data/spec/core/schema_spec.rb +14 -14
- data/spec/core/spec_helper.rb +1 -0
- data/spec/{extensions/core_extensions_spec.rb → core_extensions_spec.rb} +208 -14
- data/spec/extensions/columns_introspection_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +28 -36
- data/spec/extensions/many_through_many_spec.rb +4 -4
- data/spec/extensions/pg_array_ops_spec.rb +15 -7
- data/spec/extensions/pg_array_spec.rb +81 -48
- data/spec/extensions/pg_auto_parameterize_spec.rb +2 -2
- data/spec/extensions/pg_hstore_ops_spec.rb +13 -9
- data/spec/extensions/pg_hstore_spec.rb +66 -65
- data/spec/extensions/pg_inet_spec.rb +2 -4
- data/spec/extensions/pg_interval_spec.rb +2 -3
- data/spec/extensions/pg_json_spec.rb +20 -18
- data/spec/extensions/pg_range_ops_spec.rb +11 -4
- data/spec/extensions/pg_range_spec.rb +30 -7
- data/spec/extensions/pg_row_ops_spec.rb +48 -0
- data/spec/extensions/pg_row_plugin_spec.rb +45 -0
- data/spec/extensions/pg_row_spec.rb +323 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/query_literals_spec.rb +11 -11
- data/spec/extensions/query_spec.rb +3 -3
- data/spec/extensions/schema_dumper_spec.rb +20 -4
- data/spec/extensions/schema_spec.rb +18 -41
- data/spec/extensions/select_remove_spec.rb +4 -4
- data/spec/extensions/spec_helper.rb +4 -8
- data/spec/extensions/to_dot_spec.rb +5 -5
- data/spec/extensions/validation_class_methods_spec.rb +28 -16
- data/spec/integration/associations_test.rb +20 -20
- data/spec/integration/dataset_test.rb +98 -98
- data/spec/integration/eager_loader_test.rb +13 -27
- data/spec/integration/plugin_test.rb +5 -5
- data/spec/integration/prepared_statement_test.rb +22 -13
- data/spec/integration/schema_test.rb +28 -18
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/integration/timezone_test.rb +2 -2
- data/spec/integration/type_test.rb +15 -6
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +4 -4
- data/spec/model/base_spec.rb +5 -5
- data/spec/model/eager_loading_spec.rb +15 -15
- data/spec/model/model_spec.rb +32 -32
- data/spec/model/record_spec.rb +16 -0
- data/spec/model/spec_helper.rb +2 -6
- data/spec/model/validations_spec.rb +1 -1
- metadata +16 -4
data/doc/association_basics.rdoc
CHANGED
@@ -345,7 +345,7 @@ The association dataset is just like any other Sequel dataset, in that
|
|
345
345
|
it can be further filtered, ordered, etc.:
|
346
346
|
|
347
347
|
@artist.albums_dataset.
|
348
|
-
|
348
|
+
where(Sequel.like(:name, 'A%')).
|
349
349
|
order(:copies_sold).
|
350
350
|
limit(10)
|
351
351
|
# SELECT * FROM albums
|
@@ -364,8 +364,8 @@ Similar to the +_dataset+ method, you can provide a block to the association
|
|
364
364
|
method to customize the dataset that will be used to retrieve the records. So
|
365
365
|
you can apply a filter in either of these two ways:
|
366
366
|
|
367
|
-
@artist.albums_dataset.
|
368
|
-
@artist.albums{|ds| ds.
|
367
|
+
@artist.albums_dataset.where(Sequel.like(:name, 'A%'))
|
368
|
+
@artist.albums{|ds| ds.where(Sequel.like(:name, 'A%'))}
|
369
369
|
|
370
370
|
While they both apply the same filter, using the +_dataset+ method does not
|
371
371
|
apply any of the association callbacks or handle association reciprocals (see
|
@@ -373,11 +373,6 @@ below for details about callbacks and reciprocals). Using a block instead handl
|
|
373
373
|
all those things, and also caches its results in the associations cache (ignoring
|
374
374
|
any previously cached value).
|
375
375
|
|
376
|
-
Note that if you are using ruby 1.8.6, you can't pass a block to the association
|
377
|
-
method, you have to pass a proc as an argument:
|
378
|
-
|
379
|
-
@artist.albums(proc{|ds| ds.filter(:name.like('A%'))})
|
380
|
-
|
381
376
|
== Filtering By Associations
|
382
377
|
|
383
378
|
In addition to using the association method to get associated objects, you
|
@@ -389,35 +384,35 @@ all albums for a given artist, you would usually do:
|
|
389
384
|
|
390
385
|
You can also do the following:
|
391
386
|
|
392
|
-
Album.
|
387
|
+
Album.where(:artist=>@artist).all
|
393
388
|
# or leave off the .all for a dataset
|
394
389
|
|
395
390
|
For filtering by a single association, this isn't very useful. However, unlike
|
396
391
|
using the association method, using a filter allows you to filter by multiple
|
397
392
|
associations:
|
398
393
|
|
399
|
-
Album.
|
394
|
+
Album.where(:artist=>@artist, :publisher=>@publisher)
|
400
395
|
|
401
396
|
This will return all albums by that artist and published by that publisher.
|
402
397
|
This isn't possible using just the association method approach, though you
|
403
398
|
can combine the approaches:
|
404
399
|
|
405
|
-
@artist.albums_dataset.
|
400
|
+
@artist.albums_dataset.where(:publisher=>@publisher)
|
406
401
|
|
407
402
|
This doesn't just work for +many_to_one+ associations, it also works for
|
408
403
|
+one_to_one+, +one_to_many+, and +many_to_many+ associations:
|
409
404
|
|
410
405
|
Album.one_to_one :album_info
|
411
406
|
# The album related to that AlbumInfo instance
|
412
|
-
Album.
|
407
|
+
Album.where(:album_info=>AlbumInfo[2])
|
413
408
|
|
414
409
|
Album.one_to_many :tracks
|
415
410
|
# The album related to that Track instance
|
416
|
-
Album.
|
411
|
+
Album.where(:tracks=>Track[3])
|
417
412
|
|
418
413
|
Album.many_to_many :tags
|
419
414
|
# All albums related to that Tag instance
|
420
|
-
Album.
|
415
|
+
Album.where(:tags=>Tag[4])
|
421
416
|
|
422
417
|
Note that for +one_to_many+ and +many_to_many+ associations, you still
|
423
418
|
use the plural form even though only a single model object is given.
|
@@ -430,7 +425,7 @@ This will return all albums not by that artist.
|
|
430
425
|
|
431
426
|
You can also provide an array with multiple model objects:
|
432
427
|
|
433
|
-
Album.
|
428
|
+
Album.where(:artist=>[@artist1, @artist2]).all
|
434
429
|
|
435
430
|
Similar to using an array of integers or strings, this will return
|
436
431
|
all albums whose artist is one of those two artists. You can also
|
@@ -442,28 +437,28 @@ If you are using a +one_to_many+ or +many_to_many+ association, you
|
|
442
437
|
may want to return records where the records matches all of multiple
|
443
438
|
records, instead of matching any of them. For example:
|
444
439
|
|
445
|
-
Album.
|
440
|
+
Album.where(:tags=>[@tag1, @tag2])
|
446
441
|
|
447
442
|
This matches albums that are associated with either @tag1 or @tag2 or
|
448
443
|
both. If you only want ones that you are associated with both, you can
|
449
444
|
use separate filter calls:
|
450
445
|
|
451
|
-
Album.
|
446
|
+
Album.where(:tags=>@tag1).where(:tags=>@tag2)
|
452
447
|
|
453
448
|
Or the the array form of condition specifiers:
|
454
449
|
|
455
|
-
Album.
|
450
|
+
Album.where([[:tags, @tag1], [:tags, @tag2]])
|
456
451
|
|
457
452
|
These will return albums associated with both @tag1 and @tag2.
|
458
453
|
|
459
454
|
You can also provide a dataset value when filtering by associations:
|
460
455
|
|
461
|
-
Album.
|
456
|
+
Album.where(:artist=>Artist.where(Sequel.like(:name, 'A%'))).all
|
462
457
|
|
463
458
|
This will return all albums whose artist starts with 'A'. Like
|
464
459
|
the other forms, this can be inverted:
|
465
460
|
|
466
|
-
Album.exclude(:artist=>Artist.
|
461
|
+
Album.exclude(:artist=>Artist.where(Sequel.like(:name, 'A%'))).all
|
467
462
|
|
468
463
|
This will return all albums whose artist does not start with 'A'.
|
469
464
|
|
@@ -562,6 +557,8 @@ wanted to add an albums_artists join table to create the following schema:
|
|
562
557
|
|
563
558
|
You could use the following Sequel code:
|
564
559
|
|
560
|
+
DB.create_join_table(:album_id=>:albums, :artist_id=>:artists)
|
561
|
+
# or
|
565
562
|
DB.create_table(:albums_artists) do
|
566
563
|
foreign_key :album_id, :albums
|
567
564
|
foreign_key :artist_id, :artists
|
@@ -717,7 +714,7 @@ The <i>association</i>_dataset method returns a dataset that represents
|
|
717
714
|
all associated objects. This dataset is like any other Sequel dataset,
|
718
715
|
in that it can be filtered, ordered, etc.:
|
719
716
|
|
720
|
-
ds = @artist.albums_dataset.
|
717
|
+
ds = @artist.albums_dataset.where(Sequel.like(:name, 'A%')).order(:copies_sold)
|
721
718
|
|
722
719
|
Unlike most other Sequel datasets, association datasets have a couple of
|
723
720
|
added methods:
|
@@ -828,7 +825,7 @@ that returns all albums of an artist that went gold (sold at least
|
|
828
825
|
500,000 copies):
|
829
826
|
|
830
827
|
Artist.one_to_many :gold_albums, :class=>:Album do |ds|
|
831
|
-
ds.
|
828
|
+
ds.where{copies_sold > 500000}
|
832
829
|
end
|
833
830
|
|
834
831
|
==== :class
|
@@ -847,7 +844,7 @@ default class guessed will be wrong:
|
|
847
844
|
|
848
845
|
# guesses GoldAlbum
|
849
846
|
Artist.one_to_many :gold_albums do |ds|
|
850
|
-
ds.
|
847
|
+
ds.where{copies_sold > 500000}
|
851
848
|
end
|
852
849
|
|
853
850
|
You can specify the :class option using the class itself, a Symbol,
|
@@ -872,13 +869,13 @@ symbol. Defaults to :"#{self.name.underscore}_id".
|
|
872
869
|
|
873
870
|
Artist.one_to_many :albums # :key=>:artist_id
|
874
871
|
|
875
|
-
In both cases an array of symbols for a composite key association:
|
872
|
+
In both cases an array of symbols can be used for a composite key association:
|
876
873
|
|
877
874
|
Apartment.many_to_one :building # :key=>[:city, :address]
|
878
875
|
|
879
876
|
==== :conditions
|
880
877
|
|
881
|
-
The conditions to use to filter the association, can be any argument passed to
|
878
|
+
The conditions to use to filter the association, can be any argument passed to +where+.
|
882
879
|
If you use a hash or an array of two element arrays, this will also be used as a
|
883
880
|
filter when using eager_graph to load the association.
|
884
881
|
|
@@ -911,7 +908,7 @@ columns that have the same name in both the join table and the associated
|
|
911
908
|
table. Example:
|
912
909
|
|
913
910
|
Artist.one_to_many :albums, :select=>[:id, :name]
|
914
|
-
Album.many_to_many :tags, :select=>[:tags.*, :albums_tags__number]
|
911
|
+
Album.many_to_many :tags, :select=>[Sequel.expr(:tags).*, :albums_tags__number]
|
915
912
|
|
916
913
|
==== :limit
|
917
914
|
|
@@ -928,8 +925,6 @@ Use an array with two arguments for the value to specify a limit and an offset.
|
|
928
925
|
This probably doesn't make a lot of sense for *_to_one associations, though you
|
929
926
|
could use it to specify an offset.
|
930
927
|
|
931
|
-
This option is ignored when eager loading.
|
932
|
-
|
933
928
|
==== :join_table [+many_to_many+]
|
934
929
|
|
935
930
|
Name of table that includes the foreign keys to both the current model and the
|
@@ -944,7 +939,7 @@ Here's an example of the defaults:
|
|
944
939
|
==== :left_key [+many_to_many+]
|
945
940
|
|
946
941
|
Foreign key in join table that points to current model's primary key, as a
|
947
|
-
symbol. Defaults to :"#{
|
942
|
+
symbol. Defaults to :"#{model_name.underscore}_id".
|
948
943
|
|
949
944
|
Album.many_to_many :tags # :left_key=>:album_id
|
950
945
|
|
@@ -953,9 +948,9 @@ Can use an array of symbols for a composite key association.
|
|
953
948
|
==== :right_key [+many_to_many+]
|
954
949
|
|
955
950
|
Foreign key in join table that points to associated model's primary key, as a
|
956
|
-
symbol. Defaults to :"#{
|
951
|
+
symbol. Defaults to :"#{association_name.singularize}_id".
|
957
952
|
|
958
|
-
Album.many_to_many :tags # :
|
953
|
+
Album.many_to_many :tags # :right_key=>:tag_id
|
959
954
|
|
960
955
|
Can use an array of symbols for a composite key association.
|
961
956
|
|
@@ -1006,7 +1001,7 @@ Here's an example of an association of songs to artists through lyrics, where
|
|
1006
1001
|
the artist can perform any one of four tasks for the lyric:
|
1007
1002
|
|
1008
1003
|
Album.one_to_many :songs, :dataset=>(proc do
|
1009
|
-
Song.
|
1004
|
+
Song.select_all(:songs).
|
1010
1005
|
join(Lyric, :id=>:lyricid,
|
1011
1006
|
id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])
|
1012
1007
|
end)
|
@@ -1025,8 +1020,8 @@ set up association extensions. For more information , please see the
|
|
1025
1020
|
==== :primary_key
|
1026
1021
|
|
1027
1022
|
The column that the :key option references, as a symbol. For +many_to_one+
|
1028
|
-
associations, this column in the associated table. For +one_to_one+ and
|
1029
|
-
+one_to_many+ associations, this column in the current table. In both cases,
|
1023
|
+
associations, this column is in the associated table. For +one_to_one+ and
|
1024
|
+
+one_to_many+ associations, this column is in the current table. In both cases,
|
1030
1025
|
it defaults to the primary key of the table. Can use an
|
1031
1026
|
array of symbols for a composite key association.
|
1032
1027
|
|
@@ -1063,7 +1058,7 @@ applies to the join table. It can be used to make sure additional columns are
|
|
1063
1058
|
used when inserting, or that filters are used when deleting.
|
1064
1059
|
|
1065
1060
|
Artist.many_to_many :lead_guitar_albums, :join_table_block=>proc do |ds|
|
1066
|
-
ds.
|
1061
|
+
ds.where(:instrument_id=>5).set_overrides(:instrument_id=>5)
|
1067
1062
|
end
|
1068
1063
|
|
1069
1064
|
=== Callback Options
|
@@ -1158,8 +1153,7 @@ Called after the _<i>association</i>= method is called to modify the objects:
|
|
1158
1153
|
|
1159
1154
|
==== :after_load
|
1160
1155
|
|
1161
|
-
Called after retrieving the associated records from the database.
|
1162
|
-
when eager loading via eager_graph, but called when eager loading via eager.
|
1156
|
+
Called after retrieving the associated records from the database.
|
1163
1157
|
|
1164
1158
|
class Artist
|
1165
1159
|
# Cache all album names to a single string when retrieving the
|
@@ -1176,8 +1170,7 @@ when eager loading via eager_graph, but called when eager loading via eager.
|
|
1176
1170
|
end
|
1177
1171
|
|
1178
1172
|
Generally used if you know you will always want a certain action done
|
1179
|
-
when retrieving the association.
|
1180
|
-
also plan on using eager_graph to eagerly load the association.
|
1173
|
+
when retrieving the association.
|
1181
1174
|
|
1182
1175
|
For +one_to_many+ and +many_to_many+ associations, both the argument to
|
1183
1176
|
symbol callbacks and the second argument to proc callbacks will be an
|
@@ -1242,7 +1235,7 @@ association based on dependent associations:
|
|
1242
1235
|
|
1243
1236
|
Artist.one_to_many :albums_with_short_tracks, :class=>:Album,
|
1244
1237
|
:eager_graph=>:tracks do |ds|
|
1245
|
-
ds.
|
1238
|
+
ds.where{tracks__seconds < 120}
|
1246
1239
|
end
|
1247
1240
|
Artist.one_to_many :albums_by_track_name, :class=>:Album,
|
1248
1241
|
:eager_graph=>:tracks do |ds|
|
@@ -1274,13 +1267,13 @@ via eager_graph. This is useful to specify conditions that can't be specified
|
|
1274
1267
|
in a hash or array of two element arrays.
|
1275
1268
|
|
1276
1269
|
Artist.one_to_many :gold_albums, :class=>:Album,
|
1277
|
-
:graph_block=>proc{|j,lj,js|
|
1270
|
+
:graph_block=>proc{|j,lj,js| Sequel.qualify(j, :copies_sold) > 500000}
|
1278
1271
|
|
1279
1272
|
==== :graph_join_type
|
1280
1273
|
|
1281
1274
|
The type of SQL join to use when eagerly loading the association via
|
1282
1275
|
eager_graph. Defaults to :left_outer. This is useful if you want to
|
1283
|
-
ensure that
|
1276
|
+
ensure that only artists that have albums are returned:
|
1284
1277
|
|
1285
1278
|
Artist.one_to_many :albums, :graph_join_type=>:inner
|
1286
1279
|
# Will exclude artists without an album
|
@@ -1306,8 +1299,8 @@ where the artist's name differs in case:
|
|
1306
1299
|
|
1307
1300
|
Artist.one_to_many :albums, :key=>:artist_name,
|
1308
1301
|
:graph_only_conditions=>nil,
|
1309
|
-
:graph_block=>proc{|j,lj,js| {:lower.
|
1310
|
-
:lower.
|
1302
|
+
:graph_block=>proc{|j,lj,js| {Sequel.function(:lower, Sequel.qualify(j, :artist_name))=>
|
1303
|
+
Sequel.function(:lower, Sequel.qualify(lj, :name))}}
|
1311
1304
|
|
1312
1305
|
Note how :graph_only_conditions is set to nil to ignore any existing conditions,
|
1313
1306
|
and :graph_block is used to set up the case insensitive comparison.
|
@@ -1345,8 +1338,8 @@ Sets up a custom grapher to use when eager loading the objects via eager_graph.
|
|
1345
1338
|
This is the eager_graph analogue to the :eager_loader option. This isn't generally
|
1346
1339
|
needed, as one of the other eager_graph related association options is usually sufficient.
|
1347
1340
|
|
1348
|
-
If specified, should be a proc that accepts
|
1349
|
-
|
1341
|
+
If specified, should be a proc that accepts a single hash argument, which will contain
|
1342
|
+
at least the following keys:
|
1350
1343
|
|
1351
1344
|
:self :: The dataset that is doing the eager loading
|
1352
1345
|
:table_alias :: An alias to use for the table to graph for this association.
|
@@ -1355,10 +1348,7 @@ If the proc takes one argument, it will be given a hash with the following keys:
|
|
1355
1348
|
current dataset, before such graphing is done. This is nil if no callback
|
1356
1349
|
proc is used.
|
1357
1350
|
|
1358
|
-
|
1359
|
-
and :table_alias values. The 3 argument procs are allowed for backwards
|
1360
|
-
compatibility, and it is recommended to use the 1 argument proc format
|
1361
|
-
for new code.
|
1351
|
+
Example:
|
1362
1352
|
|
1363
1353
|
Artist.one_to_many :self_title_albums, :class=>:Album,
|
1364
1354
|
:eager_grapher=>(proc do |eo|
|
@@ -1407,7 +1397,7 @@ has received a bachelor's degree (degree starting with B):
|
|
1407
1397
|
|
1408
1398
|
Person.many_to_many :bachelor_degree_colleges, :class=>:College,
|
1409
1399
|
:join_table=>:degrees_received,
|
1410
|
-
:graph_join_table_block=>proc{|j,lj,js|
|
1400
|
+
:graph_join_table_block=>proc{|j,lj,js| Sequel.qualify(j, :degree).like('B%')}
|
1411
1401
|
|
1412
1402
|
This should be done when graphing the join table, instead of when graphing the
|
1413
1403
|
final table, as :degree is a column of the join table.
|
data/doc/cheat_sheet.rdoc
CHANGED
@@ -53,8 +53,8 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
53
53
|
|
54
54
|
== Update/Delete rows
|
55
55
|
|
56
|
-
dataset.
|
57
|
-
dataset.
|
56
|
+
dataset.exclude(:active).delete
|
57
|
+
dataset.where('price < ?', 100).update(:active => true)
|
58
58
|
|
59
59
|
== Datasets are Enumerable
|
60
60
|
|
@@ -64,21 +64,21 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
64
64
|
dataset.inject(0){|sum, r| sum + r[:value]}
|
65
65
|
dataset.sum(:value) # same as above
|
66
66
|
|
67
|
-
== Filtering (see also doc/
|
67
|
+
== Filtering (see also {Dataset Filtering}[link:files/doc/dataset_filtering_rdoc.html])
|
68
68
|
|
69
69
|
=== Equality
|
70
70
|
|
71
|
-
dataset.
|
72
|
-
dataset.
|
71
|
+
dataset.where(:name => 'abc')
|
72
|
+
dataset.where('name = ?', 'abc')
|
73
73
|
|
74
74
|
=== Inequality
|
75
75
|
|
76
|
-
dataset.
|
76
|
+
dataset.where{value > 100}
|
77
77
|
dataset.exclude{value <= 100}
|
78
78
|
|
79
79
|
=== Inclusion
|
80
80
|
|
81
|
-
dataset.
|
81
|
+
dataset.where(:value => 50..100)
|
82
82
|
dataset.where{(value >= 50) & (value <= 100)}
|
83
83
|
|
84
84
|
dataset.where('value IN ?', [50,75,100])
|
@@ -89,34 +89,34 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
89
89
|
=== Subselects as scalar values
|
90
90
|
|
91
91
|
dataset.where('price > (SELECT avg(price) + 100 FROM table)')
|
92
|
-
dataset.
|
92
|
+
dataset.where{price > dataset.select(avg(price) + 100)}
|
93
93
|
|
94
94
|
=== LIKE/Regexp
|
95
95
|
|
96
|
-
DB[:items].
|
97
|
-
DB[:items].
|
96
|
+
DB[:items].where(Sequel.like(:name, 'AL%'))
|
97
|
+
DB[:items].where(:name => /^AL/)
|
98
98
|
|
99
99
|
=== AND/OR/NOT
|
100
100
|
|
101
|
-
DB[:items].
|
101
|
+
DB[:items].where{(x > 5) & (y > 10)}.sql
|
102
102
|
# SELECT * FROM items WHERE ((x > 5) AND (y > 10))
|
103
103
|
|
104
|
-
DB[:items].
|
104
|
+
DB[:items].where({:x => 1, :y => 2}.sql_or & Sequel.~(:z => 3)).sql
|
105
105
|
# SELECT * FROM items WHERE (((x = 1) OR (y = 2)) AND (z != 3))
|
106
106
|
|
107
107
|
=== Mathematical operators
|
108
108
|
|
109
|
-
DB[:items].
|
109
|
+
DB[:items].where{x + y > z}.sql
|
110
110
|
# SELECT * FROM items WHERE ((x + y) > z)
|
111
111
|
|
112
|
-
DB[:items].
|
112
|
+
DB[:items].where{price - 100 < avg(price)}.sql
|
113
113
|
# SELECT * FROM items WHERE ((price - 100) < avg(price))
|
114
114
|
|
115
115
|
== Ordering
|
116
116
|
|
117
117
|
dataset.order(:kind)
|
118
118
|
dataset.reverse_order(:kind)
|
119
|
-
dataset.order(:kind
|
119
|
+
dataset.order(Sequel.desc(:kind), :name)
|
120
120
|
|
121
121
|
== Limit/Offset
|
122
122
|
|
@@ -140,15 +140,15 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
140
140
|
dataset.sum(:stock)
|
141
141
|
|
142
142
|
dataset.group_and_count(:category)
|
143
|
-
dataset.group(:category).select(:category,
|
143
|
+
dataset.group(:category).select(:category, Sequel.function(:AVG, :price))
|
144
144
|
|
145
145
|
== SQL Functions / Literals
|
146
146
|
|
147
|
-
dataset.update(:updated_at => :NOW
|
148
|
-
dataset.update(:updated_at => 'NOW()'
|
147
|
+
dataset.update(:updated_at => Sequel.function(:NOW))
|
148
|
+
dataset.update(:updated_at => Sequel.lit('NOW()'))
|
149
149
|
|
150
|
-
dataset.update(:updated_at => "DateValue('1/1/2001')"
|
151
|
-
dataset.update(:updated_at => :DateValue
|
150
|
+
dataset.update(:updated_at => Sequel.lit("DateValue('1/1/2001')")
|
151
|
+
dataset.update(:updated_at => Sequel.function(:DateValue, '1/1/2001'))
|
152
152
|
|
153
153
|
== Schema Manipulation
|
154
154
|
|
@@ -171,7 +171,7 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
171
171
|
|
172
172
|
== Aliasing
|
173
173
|
|
174
|
-
DB[:items].select(
|
174
|
+
DB[:items].select(Sequel.as(:name, :item_name))
|
175
175
|
DB[:items].select(:name___item_name)
|
176
176
|
DB[:items___items_table].select(:items_table__name___item_name)
|
177
177
|
# SELECT items_table.name AS item_name FROM items AS items_table
|
@@ -0,0 +1,374 @@
|
|
1
|
+
= Sequel's Core Extensions
|
2
|
+
|
3
|
+
== Background
|
4
|
+
|
5
|
+
Historically, Sequel added methods to many of the core classes, and usage of those methods was the primary and recommended way to use Sequel. For example:
|
6
|
+
|
7
|
+
DB[:table].select(:column.cast(Integer)). # Symbol#cast
|
8
|
+
where(:column.like('A%')). # Symbol#like
|
9
|
+
order({1=>2}.case(0, :a)) # Hash#case
|
10
|
+
|
11
|
+
While Sequel never override any methods defined by ruby, it is possible that other libraries could define the same methods that Sequel defines, which could cause problems. Also, some rubyists do not like using libraries that add methods to the core classes.
|
12
|
+
|
13
|
+
Alternatives for the core extension methods where added to Sequel, so the query above could be written as:
|
14
|
+
|
15
|
+
DB[:table].select(Sequel.cast(:column, Integer)).
|
16
|
+
where(Sequel.like(:column, 'A%')).
|
17
|
+
order(Sequel.case({1=>2}, 0, :a))
|
18
|
+
|
19
|
+
Almost all of the core extension methods have a replacement on the Sequel module. So it is now up to the user which style to use. Using the methods on the Sequel module results in slightly more verbose code, but allows the code to work without modifications to the core classes.
|
20
|
+
|
21
|
+
== Issues
|
22
|
+
|
23
|
+
There is no recommendation on whether the core_extensions should be used or not. It is very rare that any of the methods added by core_extensions actually causes a problem, but some of them can make it more difficult to find other problems. For example, if you type:
|
24
|
+
|
25
|
+
do_somehting if value | other_value
|
26
|
+
|
27
|
+
while meaning to type:
|
28
|
+
|
29
|
+
do_something if value || other_value
|
30
|
+
|
31
|
+
and value is a Symbol, instead of a NoMethodError being raised because Symbol#| is not implemented by default, <tt>value | other_value</tt> will return a Sequel expression object, which if will evaluate as true, and do_something will be called.
|
32
|
+
|
33
|
+
== Usage
|
34
|
+
|
35
|
+
All of Sequel's extensions to the core classes are stored in Sequel's core_extensions extension, which you can load via:
|
36
|
+
|
37
|
+
Sequel.extension :core_extensions
|
38
|
+
|
39
|
+
For backwards compatibility, the core_extensions are loaded by default in Sequel 3. Starting in Sequel 4, the core extensions will no longer be loaded by default, so you will have to load the core_extensions extension manually using the above code. If you plan to use the core extensions, it's recommended that you manually load the extension, even in Sequel 3. If you do not plan to use the core extensions, you can change from:
|
40
|
+
|
41
|
+
require 'sequel'
|
42
|
+
|
43
|
+
to:
|
44
|
+
|
45
|
+
require 'sequel/no_core_ext'
|
46
|
+
|
47
|
+
which will load Sequel without the core extensions.
|
48
|
+
|
49
|
+
== No Internal Dependency
|
50
|
+
|
51
|
+
Sequel has no internal dependency on the core extensions. This includes Sequel's core, Sequel::Model, and all plugins and extensions that ship with Sequel. However, it is possible that external plugins and extensions will depend on the core extensions. Such plugins and extensions should be updated so that they no longer depend on the core extensions.
|
52
|
+
|
53
|
+
== Core Extension Methods
|
54
|
+
|
55
|
+
This section will briefly describe all of the methods added to the core classes, and what the alternative method is that doesn't require the core extensions.
|
56
|
+
|
57
|
+
=== Symbol & String
|
58
|
+
|
59
|
+
==== as
|
60
|
+
|
61
|
+
Symbol#as and String#as return Sequel aliased expressions using the provided alias:
|
62
|
+
|
63
|
+
:a.as(:b) # SQL: a AS b
|
64
|
+
'a'.as(:b) # SQL: 'a' AS b
|
65
|
+
|
66
|
+
Alternative: Sequel.as:
|
67
|
+
|
68
|
+
Sequel.as(:a, :b)
|
69
|
+
|
70
|
+
==== cast
|
71
|
+
|
72
|
+
Symbol#cast and String#cast return Sequel cast expressions for typecasting in the database:
|
73
|
+
|
74
|
+
:a.cast(Integer) # SQL: CAST(a AS integer)
|
75
|
+
'a'.cast(Integer) # SQL: CAST('a' AS integer)
|
76
|
+
|
77
|
+
Alternative: Sequel.cast:
|
78
|
+
|
79
|
+
Sequel.cast(:a, Integer)
|
80
|
+
|
81
|
+
==== cast_numeric
|
82
|
+
|
83
|
+
Symbol#cast_numeric and String#cast_numeric return Sequel cast expressions for typecasting in the database, defaulting to integers, where the returned expression is treated as an numeric value:
|
84
|
+
|
85
|
+
:a.cast_numeric # SQL: CAST(a AS integer)
|
86
|
+
'a'.cast_numeric(Float) # SQL: CAST('a' AS double precision)
|
87
|
+
|
88
|
+
Alternative: Sequel.cast_numeric:
|
89
|
+
|
90
|
+
Sequel.cast_numeric(:a)
|
91
|
+
|
92
|
+
==== cast_string
|
93
|
+
|
94
|
+
Symbol#cast_string and String#cast_string return Sequel cast expressions for typecasting in the database, defaulting to strings, where the returned expression is treated as a string value:
|
95
|
+
|
96
|
+
:a.cast_string # SQL: CAST(a AS varchar(255))
|
97
|
+
'a'.cast_string(:text) # SQL: CAST('a' AS text)
|
98
|
+
|
99
|
+
Alternative: Sequel.cast_string:
|
100
|
+
|
101
|
+
Sequel.cast_string(:a)
|
102
|
+
|
103
|
+
=== Symbol
|
104
|
+
|
105
|
+
==== identifier
|
106
|
+
|
107
|
+
Symbol#identifier wraps the symbol in a single identifier that will not be split. By default, Sequel will split symbols with double or triple underscores to do qualifying and aliasing.
|
108
|
+
|
109
|
+
:table__column.identifier # SQL: table__column
|
110
|
+
|
111
|
+
Alternative: Sequel.identifier:
|
112
|
+
|
113
|
+
Sequel.identifier(:table__column)
|
114
|
+
|
115
|
+
==== asc
|
116
|
+
|
117
|
+
Symbol#asc is used to define an ascending order on a column. It exists mostly for consistency with #desc, since ascending is the default order:
|
118
|
+
|
119
|
+
:a.asc # SQL: a ASC
|
120
|
+
|
121
|
+
Alternative: Sequel.asc:
|
122
|
+
|
123
|
+
Sequel.asc(:a)
|
124
|
+
|
125
|
+
==== desc
|
126
|
+
|
127
|
+
Symbol#desc is used to defined a descending order on a column. The returned value is usually passed to one of the dataset order methods.
|
128
|
+
|
129
|
+
:a.desc # SQL: a DESC
|
130
|
+
|
131
|
+
Alternative: Sequel.desc:
|
132
|
+
|
133
|
+
Sequel.desc(:a)
|
134
|
+
|
135
|
+
==== +, -, *, /
|
136
|
+
|
137
|
+
The standard mathematical operators are defined on Symbol, and return a Sequel numeric expression object representing the operation:
|
138
|
+
|
139
|
+
:a + :b # SQL: a + b
|
140
|
+
:a - :b # SQL: a - b
|
141
|
+
:a * :b # SQL: a * b
|
142
|
+
:a / :b # SQL: a / b
|
143
|
+
|
144
|
+
Alternatives:
|
145
|
+
|
146
|
+
Sequel.+(:a, :b)
|
147
|
+
Sequel.-(:a, :b)
|
148
|
+
Sequel.*(:a, :b)
|
149
|
+
Sequel./(:a, :b)
|
150
|
+
|
151
|
+
==== *
|
152
|
+
|
153
|
+
The * operator is overloaded on Symbol such that if it is called with no arguments, it represents a selection of all columns in the table:
|
154
|
+
|
155
|
+
:a.* # SQL: a.*
|
156
|
+
|
157
|
+
Alternative: Sequel.expr.*:
|
158
|
+
|
159
|
+
Sequel.expr(:a).*
|
160
|
+
|
161
|
+
==== qualify
|
162
|
+
|
163
|
+
Symbol#qualify qualifies the identifier (e.g. a column) with a another identifier (e.g. a table):
|
164
|
+
|
165
|
+
:column.qualify(:table) # SQL: table.column
|
166
|
+
|
167
|
+
Alternative: Sequel.qualify:
|
168
|
+
|
169
|
+
Sequel.qualify(:table, :column)
|
170
|
+
|
171
|
+
Note the reversed order of the arguments. For the Symbol#qualify method, the argument is the qualifier, while for Sequel.qualify, the qualifier is the first argument.
|
172
|
+
|
173
|
+
==== like
|
174
|
+
|
175
|
+
Symbol#like returns a case sensitive LIKE expression between the identifier and the given argument:
|
176
|
+
|
177
|
+
:a.like('b%') # SQL: a LIKE 'b%'
|
178
|
+
|
179
|
+
Alternative: Sequel.like:
|
180
|
+
|
181
|
+
Sequel.like(:a, 'b%')
|
182
|
+
|
183
|
+
==== like
|
184
|
+
|
185
|
+
Symbol#ilike returns a case insensitive LIKE expression between the identifier and the given argument:
|
186
|
+
|
187
|
+
:a.ilike('b%') # SQL: a ILIKE 'b%'
|
188
|
+
|
189
|
+
Alternative: Sequel.ilike:
|
190
|
+
|
191
|
+
Sequel.ilike(:a, 'b%')
|
192
|
+
|
193
|
+
==== sql_subscript
|
194
|
+
|
195
|
+
Symbol#sql_subscript returns a Sequel expression representing an SQL array access:
|
196
|
+
|
197
|
+
:a.sql_subscript(1) # SQL: a[1]
|
198
|
+
|
199
|
+
Alternative: Sequel.subscript:
|
200
|
+
|
201
|
+
Sequel.subscript(:a, 1)
|
202
|
+
|
203
|
+
==== extract
|
204
|
+
|
205
|
+
Symbol#extract does a datetime part extraction from the receiver:
|
206
|
+
|
207
|
+
:a.extract(:year) # SQL: extract(year FROM a)
|
208
|
+
|
209
|
+
Alternative: Sequel.extract:
|
210
|
+
|
211
|
+
Sequel.extract(:year, :a)
|
212
|
+
|
213
|
+
Note the reversed order of the arguments. In Symbol#extract, the datetime part is the argument, while in Sequel.extract, the datetime part is the first argument.
|
214
|
+
|
215
|
+
==== sql_boolean, sql_number, sql_string
|
216
|
+
|
217
|
+
These Symbol methods are used to force the treating of the object as a specific SQL type, instead of as a general SQL type. For example:
|
218
|
+
|
219
|
+
:a.sql_boolean + 1 # NoMethodError
|
220
|
+
:a.sql_number << 1 # SQL: a << 1
|
221
|
+
:a.sql_string + 'a' # SQL: a || 'a'
|
222
|
+
|
223
|
+
Alternative: Sequel.expr:
|
224
|
+
|
225
|
+
Sequel.expr(:a).sql_boolean
|
226
|
+
Sequel.expr(:a).sql_number
|
227
|
+
Sequel.expr(:a).sql_string
|
228
|
+
|
229
|
+
==== sql_function
|
230
|
+
|
231
|
+
Symbol#sql_function returns an SQL function call expression object:
|
232
|
+
|
233
|
+
:now.sql_function # SQL: now()
|
234
|
+
:sum.sql_function(:a) # SQL: sum(a)
|
235
|
+
:concat.sql_function(:a, :b) # SQL: concat(a, b)
|
236
|
+
|
237
|
+
Alternative: Sequel.function:
|
238
|
+
|
239
|
+
Sequel.function(:now, :a)
|
240
|
+
|
241
|
+
=== String
|
242
|
+
|
243
|
+
==== lit
|
244
|
+
|
245
|
+
String#lit creates a literal string, using placeholders if any arguments are given. Literal strings are not escaped, they are treated as SQL code, not as an SQL string:
|
246
|
+
|
247
|
+
'a'.lit # SQL: a
|
248
|
+
'"a" = ?'.lit(1) # SQL: "a" = 1
|
249
|
+
|
250
|
+
Alternative: Sequel.lit:
|
251
|
+
|
252
|
+
Sequel.lit('a')
|
253
|
+
|
254
|
+
==== to_sequel_blob
|
255
|
+
|
256
|
+
String#to_sequel_blob returns the string wrapper in Sequel blob object. Often blobs need to be handled differently than regular strings by the database adapters.
|
257
|
+
|
258
|
+
"a\0".to_sequel_blob # SQL: X'6100'
|
259
|
+
|
260
|
+
Alternative: Sequel.blob:
|
261
|
+
|
262
|
+
Sequel.blob("a\0")
|
263
|
+
|
264
|
+
=== Hash, Array, & Symbol
|
265
|
+
|
266
|
+
==== ~
|
267
|
+
|
268
|
+
Array#~, Hash#~, and Symbol#~ treat the receiver as a conditions specifier, not matching all of the conditions:
|
269
|
+
|
270
|
+
~{:a=>1, :b=>[2, 3]} # SQL: a != 1 OR b NOT IN (2, 3)
|
271
|
+
~[[:a, 1], [:b, [1, 2]]] # SQL: a != 1 OR b NOT IN (1, 2)
|
272
|
+
|
273
|
+
Alternative: Sequel.~:
|
274
|
+
|
275
|
+
Sequel.~(:a=>1, :b=>[2, 3])
|
276
|
+
|
277
|
+
=== Hash & Array
|
278
|
+
|
279
|
+
==== case
|
280
|
+
|
281
|
+
Array#case and Hash#case return an SQL CASE expression, where the keys are conditions and the values are results:
|
282
|
+
|
283
|
+
{{:a=>[2,3]}=>1}.case(0) # SQL: CASE WHEN a IN (2, 3) THEN 1 ELSE 0 END
|
284
|
+
[[{:a=>[2,3]}, 1]].case(0) # SQL: CASE WHEN a IN (2, 3) THEN 1 ELSE 0 END
|
285
|
+
|
286
|
+
Alternative: Sequel.case:
|
287
|
+
|
288
|
+
Sequel.case({:a=>[2,3]}=>1}, 0)
|
289
|
+
|
290
|
+
==== sql_expr
|
291
|
+
|
292
|
+
Array#sql_expr and Hash#sql_expr treat the receiver as a conditions specifier, matching all of the conditions in the array.
|
293
|
+
|
294
|
+
{:a=>1, :b=>[2, 3]}.sql_expr # SQL: a = 1 AND b IN (2, 3)
|
295
|
+
[[:a, 1], [:b, [2, 3]]].sql_expr # SQL: a = 1 AND b IN (2, 3)
|
296
|
+
|
297
|
+
Alternative: Sequel.expr:
|
298
|
+
|
299
|
+
Sequel.expr(:a=>1, :b=>[2, 3])
|
300
|
+
|
301
|
+
==== sql_negate
|
302
|
+
|
303
|
+
Array#sql_negate and Hash#sql_negate treat the receiver as a conditions specifier, matching none of the conditions in the array:
|
304
|
+
|
305
|
+
{:a=>1, :b=>[2, 3]}.sql_negate # SQL: a != 1 AND b NOT IN (2, 3)
|
306
|
+
[[:a, 1], [:b, [2, 3]]].sql_negate # SQL: a != 1 AND b NOT IN (2, 3)
|
307
|
+
|
308
|
+
Alternative: Sequel.negate:
|
309
|
+
|
310
|
+
Sequel.negate(:a=>1, :b=>[2, 3])
|
311
|
+
|
312
|
+
==== sql_or
|
313
|
+
|
314
|
+
Array#sql_or nd Hash#sql_or treat the receiver as a conditions specifier, matching any of the conditions in the array:
|
315
|
+
|
316
|
+
{:a=>1, :b=>[2, 3]}.sql_or # SQL: a = 1 OR b IN (2, 3)
|
317
|
+
[[:a, 1], [:b, [2, 3]]].sql_or # SQL: a = 1 OR b IN (2, 3)
|
318
|
+
|
319
|
+
Alternative: Sequel.or:
|
320
|
+
|
321
|
+
Sequel.or(:a=>1, :b=>[2, 3])
|
322
|
+
|
323
|
+
=== Array
|
324
|
+
|
325
|
+
==== sql_value_list
|
326
|
+
|
327
|
+
Array#sql_value_list wraps the array in an array subclass, which Sequel will always treat as a value list and not a conditions specifier. By default, Sequel treats arrays of two element arrays as a conditions specifier.
|
328
|
+
|
329
|
+
DB[:a].filter('(a, b) IN ?', [[1, 2], [3, 4]]) # SQL: (a, b) IN ((1 = 2) AND (3 = 4))
|
330
|
+
DB[:a].filter('(a, b) IN ?', [[1, 2], [3, 4]].sql_value_list) # SQL: (a, b) IN ((1, 2), (3, 4))
|
331
|
+
|
332
|
+
Alternative: Sequel.value_list:
|
333
|
+
|
334
|
+
Sequel.value_list([[1, 2], [3, 4]])
|
335
|
+
|
336
|
+
==== sql_string_join
|
337
|
+
|
338
|
+
Array#sql_string_join joins all of the elements in the array in an SQL string concatentation expression:
|
339
|
+
|
340
|
+
[:a].sql_string_join # SQL: a
|
341
|
+
[:a, :b].sql_string_join # SQL: a || b
|
342
|
+
[:a, 'b'].sql_string_join # SQL: a || 'b'
|
343
|
+
['a', :b].sql_string_join(' ') # SQL: 'a' || ' ' || b
|
344
|
+
|
345
|
+
Alternative: Sequel.join:
|
346
|
+
|
347
|
+
Sequel.join(['a', :b], ' ')
|
348
|
+
|
349
|
+
=== Hash & Symbol
|
350
|
+
|
351
|
+
==== &
|
352
|
+
|
353
|
+
Hash#& and Symbol#& return a Sequel boolean expression, matching the condition specified by the receiver and the condition specified by the given argument:
|
354
|
+
|
355
|
+
:a & :b # SQL: a AND b
|
356
|
+
{:a=>1} & :b # SQL: a = 1 AND b
|
357
|
+
{:a=>true} & :b # SQL: a IS TRUE AND b
|
358
|
+
|
359
|
+
Alternative: Sequel.&:
|
360
|
+
|
361
|
+
Sequel.&({:a=>1}, :b)
|
362
|
+
|
363
|
+
==== |
|
364
|
+
|
365
|
+
Hash#| returns a Sequel boolean expression, matching the condition specified by the receiver or the condition specified by the given argument:
|
366
|
+
|
367
|
+
:a | :b # SQL: a OR b
|
368
|
+
{:a=>1} | :b # SQL: a = 1 OR b
|
369
|
+
{:a=>true} | :b # SQL: a IS TRUE OR b
|
370
|
+
|
371
|
+
Alternative: Sequel.|:
|
372
|
+
|
373
|
+
Sequel.|({:a=>1}, :b)
|
374
|
+
|