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/dataset_basics.rdoc
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
== Introduction
|
4
4
|
|
5
|
-
Datasets are
|
5
|
+
Datasets are the primary way Sequel uses to access the database. While most database libraries have specific support for updating all records or only a single record, Sequel's ability to represent SQL queries themselves as objects is what gives Sequel most of its power. However, if you haven't been exposed to the dataset concept before, it can be a little disorienting. This document aims to give a basic introduction to datasets and how to use them.
|
6
6
|
|
7
7
|
== What a Dataset Represents
|
8
8
|
|
@@ -24,23 +24,23 @@ Here, DB represents your Sequel::Database object, and ds is your dataset, with t
|
|
24
24
|
|
25
25
|
One of the core dataset ideas that should be understood is that datasets use a functional style of modification, in which methods called on the dataset return modified copies of the dataset, they don't modify the dataset themselves:
|
26
26
|
|
27
|
-
ds2 = ds.
|
27
|
+
ds2 = ds.where(:id=>1)
|
28
28
|
ds2
|
29
29
|
# SELECT * FROM posts WHERE id = 1
|
30
30
|
ds
|
31
31
|
# SELECT * FROM posts
|
32
32
|
|
33
|
-
Note how ds itself is not modified. This is because ds.
|
33
|
+
Note how ds itself is not modified. This is because ds.where returns a modified copy of ds, instead of modifying ds itself. This makes using datasets both thread safe and easy to chain:
|
34
34
|
|
35
35
|
# Thread safe:
|
36
36
|
100.times do |i|
|
37
37
|
Thread.new do
|
38
|
-
ds.
|
38
|
+
ds.where(:id=>i).first
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
# Easy to chain:
|
43
|
-
ds3 = ds.select(:id, :name).order(:name).
|
43
|
+
ds3 = ds.select(:id, :name).order(:name).where{id < 100}
|
44
44
|
# SELECT id, name FROM posts WHERE id < 100 ORDER BY name
|
45
45
|
|
46
46
|
Thread safety you don't really need to worry about, but chainability is core to how Sequel is generally used. Almost all dataset methods that affect the SQL produced return modified copies of the receiving dataset.
|
data/doc/dataset_filtering.rdoc
CHANGED
@@ -4,59 +4,63 @@ Sequel is very flexibile when it comes to filtering records. You can specify you
|
|
4
4
|
|
5
5
|
== Filtering using a custom filter string
|
6
6
|
|
7
|
-
If you wish to write your SQL by hand, you can just supply it to the dataset's #
|
7
|
+
If you wish to write your SQL by hand, you can just supply it to the dataset's #where method:
|
8
8
|
|
9
|
-
items.
|
9
|
+
items.where('x < 10').sql
|
10
10
|
#=> "SELECT * FROM items WHERE x < 10"
|
11
11
|
|
12
12
|
In order to prevent SQL injection, you can replace literal values with question marks and supply the values as additional arguments:
|
13
13
|
|
14
|
-
items.
|
14
|
+
items.where('category = ?', 'ruby').sql
|
15
15
|
#=> "SELECT * FROM items WHERE category = 'ruby'"
|
16
16
|
|
17
17
|
You can also use placeholders with :placeholder and a hash of placeholder values:
|
18
18
|
|
19
|
-
items.
|
19
|
+
items.where('category = :category', :category=>'ruby').sql
|
20
20
|
#=> "SELECT * FROM items WHERE category = 'ruby'"
|
21
21
|
|
22
22
|
=== Specifying SQL functions
|
23
23
|
|
24
|
-
Sequel also allows you to specify functions by using the
|
24
|
+
Sequel also allows you to specify functions by using the Sequel.function method:
|
25
25
|
|
26
|
-
items.literal(
|
26
|
+
items.literal(Sequel.function(:avg, :price)) #=> "avg(price)"
|
27
27
|
|
28
28
|
If you are specifying a filter/selection/order, you can use a virtual row block:
|
29
29
|
|
30
30
|
items.select{avg(price)}
|
31
31
|
|
32
|
+
You can also use the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html] and the +sql_function+ method:
|
33
|
+
|
34
|
+
:avg.sql_function(:price)
|
35
|
+
|
32
36
|
== Filtering using a hash
|
33
37
|
|
34
38
|
If you just need to compare records against values, you can supply a hash:
|
35
39
|
|
36
|
-
items.
|
40
|
+
items.where(:category => 'ruby').sql
|
37
41
|
#=> "SELECT * FROM items WHERE (category = 'ruby')"
|
38
42
|
|
39
43
|
Sequel can check for null values:
|
40
44
|
|
41
|
-
items.
|
45
|
+
items.where(:category => nil).sql
|
42
46
|
#=> "SELECT * FROM items WHERE (category IS NULL)"
|
43
47
|
|
44
48
|
Or compare two columns:
|
45
49
|
|
46
|
-
items.
|
50
|
+
items.where(:x => :some_table__y).sql
|
47
51
|
#=> "SELECT * FROM items WHERE (x = some_table.y)"
|
48
52
|
|
49
53
|
And also compare against multiple values:
|
50
54
|
|
51
|
-
items.
|
55
|
+
items.where(:category => ['ruby', 'perl']).sql
|
52
56
|
#=> "SELECT * FROM items WHERE (category IN ('ruby', 'perl'))"
|
53
57
|
|
54
58
|
Ranges (both inclusive and exclusive) can also be used:
|
55
59
|
|
56
|
-
items.
|
60
|
+
items.where(:price => 100..200).sql
|
57
61
|
#=> "SELECT * FROM items WHERE (price >= 100 AND price <= 200)"
|
58
62
|
|
59
|
-
items.
|
63
|
+
items.where(:price => 100...200).sql
|
60
64
|
#=> "SELECT * FROM items WHERE (price >= 100 AND price < 200)"
|
61
65
|
|
62
66
|
== Filtering using an array
|
@@ -64,119 +68,119 @@ Ranges (both inclusive and exclusive) can also be used:
|
|
64
68
|
If you need to select multiple items from a dataset, you can supply an array:
|
65
69
|
|
66
70
|
item_array = [1, 38, 47, 99]
|
67
|
-
items.
|
71
|
+
items.where(:id => item_array).sql
|
68
72
|
#=> "SELECT * FROM items WHERE (id IN (1, 38, 47, 99))"
|
69
73
|
|
70
74
|
== Filtering using expressions
|
71
75
|
|
72
|
-
|
76
|
+
You can pass a block to where, which is evaluated in a special context:
|
73
77
|
|
74
|
-
items.
|
78
|
+
items.where{price * 2 < 50}.sql
|
75
79
|
#=> "SELECT * FROM items WHERE ((price * 2) < 50)
|
76
80
|
|
77
|
-
This works for the standard inequality and arithmetic operators
|
81
|
+
This works for the standard inequality and arithmetic operators:
|
78
82
|
|
79
|
-
items.
|
83
|
+
items.where{price + 100 < 200}.sql
|
80
84
|
#=> "SELECT * FROM items WHERE ((price + 100) < 200)
|
81
85
|
|
82
|
-
items.
|
86
|
+
items.where{price - 100 > 200}.sql
|
83
87
|
#=> "SELECT * FROM items WHERE ((price - 100) > 200)
|
84
88
|
|
85
|
-
items.
|
89
|
+
items.where{price * 100 <= 200}.sql
|
86
90
|
#=> "SELECT * FROM items WHERE ((price * 100) <= 200)
|
87
91
|
|
88
|
-
items.
|
92
|
+
items.where{price / 100 >= 200}.sql
|
89
93
|
#=> "SELECT * FROM items WHERE ((price / 100) >= 200)
|
90
94
|
|
91
95
|
You use the overloaded bitwise and (&) and or (|) operators to combine expressions:
|
92
96
|
|
93
|
-
items.
|
97
|
+
items.where{(price + 100 < 200) & (price * 100 <= 200)}.sql
|
94
98
|
#=> "SELECT * FROM items WHERE (((price + 100) < 200) AND ((price * 100) <= 200))
|
95
99
|
|
96
|
-
items.
|
100
|
+
items.where{(price - 100 > 200) | (price / 100 >= 200)}.sql
|
97
101
|
#=> "SELECT * FROM items WHERE (((price - 100) > 200) OR ((price / 100) >= 200))
|
98
102
|
|
99
|
-
To filter by equality, you use the standard hash, which can be combined with other
|
103
|
+
To filter by equality, you use the standard hash, which can be combined with other expressions using Sequel.& and Sequel.|:
|
100
104
|
|
101
|
-
items.
|
105
|
+
items.where{Sequel.&({:category => 'ruby'}, (price + 100 < 200))}.sql
|
102
106
|
#=> "SELECT * FROM items WHERE ((category = 'ruby') AND ((price + 100) < 200))"
|
103
107
|
|
104
108
|
This works with other hash values, such as arrays and ranges:
|
105
109
|
|
106
|
-
items.
|
110
|
+
items.where{Sequel.|({:category => ['ruby', 'other']}, (:price - 100 > 200))}.sql
|
107
111
|
#=> "SELECT * FROM items WHERE ((category IN ('ruby', 'other')) OR ((price - 100) <= 200))"
|
108
112
|
|
109
|
-
items.
|
113
|
+
items.where{Sequel.&({:price => (100..200)}, :active)).sql
|
110
114
|
#=> "SELECT * FROM items WHERE ((price >= 100 AND price <= 200) AND active)"
|
111
115
|
|
112
116
|
=== Negating conditions
|
113
117
|
|
114
|
-
You can use the
|
118
|
+
You can use the exclude method to exclude conditions:
|
115
119
|
|
116
|
-
items.
|
120
|
+
items.exclude(:category => 'ruby').sql
|
117
121
|
#=> "SELECT * FROM items WHERE (category != 'ruby')"
|
118
122
|
|
119
|
-
items.
|
123
|
+
items.exclude(:active).sql
|
120
124
|
#=> "SELECT * FROM items WHERE NOT active"
|
121
125
|
|
122
|
-
items.
|
126
|
+
items.exclude{price / 100 >= 200}.sql
|
123
127
|
#=> "SELECT * FROM items WHERE ((price / 100) < 200)
|
124
128
|
|
125
129
|
=== Comparing against column references
|
126
130
|
|
127
131
|
You can also compare against other columns:
|
128
132
|
|
129
|
-
items.
|
133
|
+
items.where{credit > debit}.sql
|
130
134
|
#=> "SELECT * FROM items WHERE (credit > debit)
|
131
135
|
|
132
136
|
Or against SQL functions:
|
133
137
|
|
134
|
-
items.
|
138
|
+
items.where{price - 100 < max(price)}.sql
|
135
139
|
#=> "SELECT * FROM items WHERE ((price - 100) < max(price))"
|
136
140
|
|
137
141
|
== String search functions
|
138
142
|
|
139
|
-
You can search SQL strings using the
|
143
|
+
You can search SQL strings using the Sequel.like method:
|
140
144
|
|
141
|
-
items.
|
145
|
+
items.where(Sequel.like(:name, 'Acme%')).sql
|
142
146
|
#=> "SELECT * FROM items WHERE (name LIKE 'Acme%')"
|
143
147
|
|
144
148
|
You can specify a Regexp as a like argument, but this will probably only work
|
145
149
|
on PostgreSQL and MySQL:
|
146
150
|
|
147
|
-
items.
|
151
|
+
items.where(Sequel.like(:name, /Acme.*/)).sql
|
148
152
|
#=> "SELECT * FROM items WHERE (name ~ 'Acme.*')"
|
149
153
|
|
150
154
|
Like can also take more than one argument:
|
151
155
|
|
152
|
-
items.
|
156
|
+
items.where(Sequel.like(:name, 'Acme%', /Beta.*/)).sql
|
153
157
|
#=> "SELECT * FROM items WHERE ((name LIKE 'Acme%') OR (name ~ 'Beta.*'))"
|
154
158
|
|
155
159
|
== String concatenation
|
156
160
|
|
157
|
-
You can concatenate SQL strings using
|
161
|
+
You can concatenate SQL strings using Sequel.join:
|
158
162
|
|
159
|
-
items.
|
163
|
+
items.where(Sequel.join([:name, :comment]).like('%acme%')).sql
|
160
164
|
#=> "SELECT * FROM items WHERE ((name || comment) LIKE 'Acme%')"
|
161
165
|
|
162
166
|
Array#sql_string_join also takes a join argument:
|
163
167
|
|
164
|
-
items.filter([:name, :comment]
|
168
|
+
items.filter(Sequel.join([:name, :comment], ' ').like('%acme%')).sql
|
165
169
|
#=> "SELECT * FROM items WHERE ((name || ' ' || comment) LIKE 'Acme%')"
|
166
170
|
|
167
171
|
== Filtering using sub-queries
|
168
172
|
|
169
173
|
One of the best features of Sequel is the ability to use datasets as sub-queries. Sub-queries can be very useful for filtering records, and many times provide a simpler alternative to table joins. Sub-queries can be used in all forms of filters:
|
170
174
|
|
171
|
-
refs = consumer_refs.
|
172
|
-
consumers.
|
175
|
+
refs = consumer_refs.where(:logged_in).select(:consumer_id)
|
176
|
+
consumers.where(:id => refs).sql
|
173
177
|
#=> "SELECT * FROM consumers WHERE (id IN (SELECT consumer_id FROM consumer_refs WHERE logged_in))"
|
174
178
|
|
175
179
|
Note that if you are checking for the inclusion of a single column in a subselect, the subselect should only select a single column.
|
176
180
|
|
177
181
|
== Using OR instead of AND
|
178
182
|
|
179
|
-
By default, if you chain calls to +
|
183
|
+
By default, if you chain calls to +where+, the conditions get ANDed together. If you want to use an OR for a condition, you can use the +or+ method:
|
180
184
|
|
181
|
-
items.
|
185
|
+
items.where(:name=>'Food').or(:vendor=>1).sql
|
182
186
|
#=> "SELECT * FROM items WHERE ((name = 'Food') OR (vendor = 1))"
|
data/doc/mass_assignment.rdoc
CHANGED
@@ -25,7 +25,7 @@ To handle cases where different columns are allowed in different cases, you can
|
|
25
25
|
# admin case
|
26
26
|
post.set_only(params[:post], :title, :body, :deleted)
|
27
27
|
|
28
|
-
In this case, only the <tt>title=</tt> and <tt>body=</tt> methods will be allowed in the mass assignment.
|
28
|
+
In this case, only the <tt>title=</tt> and <tt>body=</tt> methods will be allowed in the mass assignment in the user case, and only <tt>title=</tt>, <tt>body=</tt>, and <tt>deleted=</tt> will be allowed for mass assignment in the admin case.
|
29
29
|
|
30
30
|
By default, if an invalid setter method call is attempted, Sequel raises a <tt>Sequel::Error</tt> exception. You can have Sequel silently ignore invalid calls by doing:
|
31
31
|
|
data/doc/migration.rdoc
CHANGED
@@ -523,11 +523,10 @@ The main difference between the two is that <tt>-d</tt> will use the type method
|
|
523
523
|
with the database independent ruby class types, while <tt>-D</tt> will use
|
524
524
|
the +column+ method with string types.
|
525
525
|
|
526
|
-
Note that Sequel cannot dump constraints other than primary key
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
dumper.
|
526
|
+
Note that Sequel cannot dump constraints other than primary key and possibly
|
527
|
+
foreign key constraints constraints. If you are using database features such
|
528
|
+
as constraints or triggers, you should use your database's dump and restore
|
529
|
+
programs instead of Sequel's schema dumper.
|
531
530
|
|
532
531
|
You can take the migration created by the schema dumper to another computer
|
533
532
|
with an empty database, and attempt to recreate the schema using:
|
data/doc/model_hooks.rdoc
CHANGED
@@ -45,7 +45,7 @@ Sequel calls hooks in the following order when saving an existing object:
|
|
45
45
|
* +before_save+
|
46
46
|
* +around_update+
|
47
47
|
* +before_update+
|
48
|
-
*
|
48
|
+
* UPDATE QUERY
|
49
49
|
* +after_update+
|
50
50
|
* +after_save+
|
51
51
|
|
@@ -89,10 +89,10 @@ Sequel does not provide a simple way to turn off the running of save/create/upda
|
|
89
89
|
|
90
90
|
However, you should note that there are plenty of ways to modify the database without saving a model object. One example is by using plain datasets, or one of the model's dataset methods:
|
91
91
|
|
92
|
-
Album.
|
92
|
+
Album.where(:name=>'RF').update(:copies_sold=>:copies_sold + 1)
|
93
93
|
# UPDATE albums SET copies_sold = copies_sold + 1 WHERE name = 'RF'
|
94
94
|
|
95
|
-
In this case, the +update+ method is called on the dataset returned by <tt>Album.
|
95
|
+
In this case, the +update+ method is called on the dataset returned by <tt>Album.where</tt>. Even if there is only a single object with the name RF, this will not call any hooks. If you want model hooks to be called, you need to make sure to operate on a model object:
|
96
96
|
|
97
97
|
album = Album.first(:name=>'RF')
|
98
98
|
album.update(:copies_sold=>album.copies_sold + 1)
|
data/doc/object_model.rdoc
CHANGED
@@ -204,6 +204,8 @@ If Sequel needs to represent an SQL concept that does not map directly to an exi
|
|
204
204
|
ruby class, it will generally use a Sequel::SQL::Expression subclass to represent that
|
205
205
|
concept.
|
206
206
|
|
207
|
+
Some of the examples below show examples that require the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html].
|
208
|
+
|
207
209
|
=== Sequel::LiteralString
|
208
210
|
|
209
211
|
Sequel::LiteralString is not actually a Sequel::SQL::Expression subclass. It is
|
@@ -215,7 +217,7 @@ as literal SQL code, instead of as an SQL string that needs to be escaped:
|
|
215
217
|
The following shortcuts exist for creating Sequel::LiteralString objects:
|
216
218
|
|
217
219
|
Sequel.lit("co'de")
|
218
|
-
"co'de".lit
|
220
|
+
"co'de".lit # core_extensions extension
|
219
221
|
|
220
222
|
=== Sequel::SQL::Blob
|
221
223
|
|
@@ -228,7 +230,7 @@ than SQL strings do:
|
|
228
230
|
The following shortcuts exist for creating Sequel::SQL::Blob objects:
|
229
231
|
|
230
232
|
Sequel.blob("blob")
|
231
|
-
"blob".to_sequel_blob
|
233
|
+
"blob".to_sequel_blob # core_extensions extension
|
232
234
|
|
233
235
|
=== Sequel::SQLTime
|
234
236
|
|
@@ -256,7 +258,7 @@ where they are required.
|
|
256
258
|
The following shortcuts exist for creating Sequel::SQL::ValueList objects:
|
257
259
|
|
258
260
|
Sequel.value_list([[1, 2], [3, 4]])
|
259
|
-
[[1, 2], [3, 4]].sql_value_list
|
261
|
+
[[1, 2], [3, 4]].sql_value_list # core_extensions extension
|
260
262
|
|
261
263
|
=== Sequel::SQL::Identifier
|
262
264
|
|
@@ -268,8 +270,9 @@ automatic qualification or aliasing happens for them:
|
|
268
270
|
|
269
271
|
The following shortcuts exist for creating Sequel::SQL::Identifier objects:
|
270
272
|
|
273
|
+
Sequel.expr(:column)
|
271
274
|
Sequel.identifier(:col__umn)
|
272
|
-
:col__umn.identifier
|
275
|
+
:col__umn.identifier # core_extensions extension
|
273
276
|
|
274
277
|
=== Sequel::SQL::QualifiedIdentifier
|
275
278
|
|
@@ -279,8 +282,9 @@ Sequel::SQL::QualifiedIdentifier objects represent qualified identifiers:
|
|
279
282
|
|
280
283
|
The following shortcuts exist for creating Sequel::SQL::QualifiedIdentifier objects:
|
281
284
|
|
285
|
+
Sequel.expr(:table__column)
|
282
286
|
Sequel.qualify(:table, :column)
|
283
|
-
:column.qualify(:table)
|
287
|
+
:column.qualify(:table) # core_extensions extension
|
284
288
|
|
285
289
|
=== Sequel::SQL::AliasedExpression
|
286
290
|
|
@@ -291,8 +295,9 @@ is treated as an identifier, but the expression can be an arbitrary Sequel expre
|
|
291
295
|
|
292
296
|
The following shortcuts exist for creating Sequel::SQL::AliasedExpression objects:
|
293
297
|
|
298
|
+
Sequel.expr(:column___alias)
|
294
299
|
Sequel.as(:column, :alias)
|
295
|
-
:column.as(:alias)
|
300
|
+
:column.as(:alias) # core_extensions extension
|
296
301
|
|
297
302
|
=== Sequel::SQL::ComplexExpression
|
298
303
|
|
@@ -309,13 +314,13 @@ There are separate subclasses for representing boolean operations such as AND an
|
|
309
314
|
There are many shortcuts for creating Sequel::SQL::ComplexExpression objects:
|
310
315
|
|
311
316
|
Sequel.or(:col1, :col2)
|
312
|
-
:col1 | :col2
|
317
|
+
:col1 | :col2 # core_extensions extension
|
313
318
|
|
314
319
|
Sequel.+(:column, 2)
|
315
|
-
:column + 2
|
320
|
+
:column + 2 # core_extensions extension
|
316
321
|
|
317
322
|
Sequel.join([:column, 'b'])
|
318
|
-
:column + 'b'
|
323
|
+
:column + 'b' # core_extensions extension
|
319
324
|
|
320
325
|
=== Sequel::SQL::CaseExpression
|
321
326
|
|
@@ -339,8 +344,8 @@ The following shortcuts exist for creating Sequel::SQL::CaseExpression objects:
|
|
339
344
|
Sequel.case({2=>1}, 0, :a)
|
340
345
|
Sequel.case({{:a=>2}=>1}, 0)
|
341
346
|
|
342
|
-
{2=>1}.case(0, :a)
|
343
|
-
{{:a=>2}=>1}.case(0)
|
347
|
+
{2=>1}.case(0, :a) # core_extensions extension
|
348
|
+
{{:a=>2}=>1}.case(0) # core_extensions extension
|
344
349
|
|
345
350
|
=== Sequel::SQL::Cast
|
346
351
|
|
@@ -360,8 +365,8 @@ The following shortcuts exist for creating Sequel::SQL::Cast objects:
|
|
360
365
|
Sequel.cast(:a, String)
|
361
366
|
Sequel.cast(:a, :int4)
|
362
367
|
|
363
|
-
:a.cast(String)
|
364
|
-
:a.cast(:int4)
|
368
|
+
:a.cast(String) # core_extensions extension
|
369
|
+
:a.cast(:int4) # core_extensions extension
|
365
370
|
|
366
371
|
=== Sequel::SQL::ColumnAll
|
367
372
|
|
@@ -374,7 +379,8 @@ take arguments. Still, it's possible they are still useful in some code:
|
|
374
379
|
|
375
380
|
The following shortcut exists for creating Sequel::SQL::Cast objects:
|
376
381
|
|
377
|
-
:table.*
|
382
|
+
Sequel.expr(:table).*
|
383
|
+
:table.* # core_extensions extension
|
378
384
|
|
379
385
|
=== Sequel::SQL::Constant
|
380
386
|
|
@@ -399,7 +405,7 @@ name and any arguments:
|
|
399
405
|
The following shortcuts exist for creating Sequel::SQL::Function objects:
|
400
406
|
|
401
407
|
Sequel.function(:func, :a, 2)
|
402
|
-
:func.sql_function(:a, 2)
|
408
|
+
:func.sql_function(:a, 2) # core_extensions extension
|
403
409
|
|
404
410
|
=== Sequel::SQL::JoinClause
|
405
411
|
|
@@ -436,8 +442,8 @@ objects:
|
|
436
442
|
Sequel.lit(':b = :v', :b=>:a, :v=>1)
|
437
443
|
Sequel.lit(['', ' = '], :a, 1)
|
438
444
|
|
439
|
-
'? = ?'.lit(:a, 1)
|
440
|
-
':b = :v'.lit(:b=>:a, :v=>1)
|
445
|
+
'? = ?'.lit(:a, 1) # core_extensions extension
|
446
|
+
':b = :v'.lit(:b=>:a, :v=>1) # core_extensions extension
|
441
447
|
|
442
448
|
=== Sequel::SQL::OrderedExpression
|
443
449
|
|
@@ -461,10 +467,10 @@ The following shortcuts exist for creating Sequel::SQL::OrderedExpression object
|
|
461
467
|
Sequel.asc(:a, :nulls=>:first)
|
462
468
|
Sequel.desc(:a, :nulls=>:last)
|
463
469
|
|
464
|
-
:a.asc
|
465
|
-
:a.desc
|
466
|
-
:a.asc(:nulls=>:first)
|
467
|
-
:a.desc(:nulls=>:last)
|
470
|
+
:a.asc # core_extensions extension
|
471
|
+
:a.desc # core_extensions extension
|
472
|
+
:a.asc(:nulls=>:first) # core_extensions extension
|
473
|
+
:a.desc(:nulls=>:last) # core_extensions extension
|
468
474
|
|
469
475
|
=== Sequel::SQL::Subscript
|
470
476
|
|
@@ -479,17 +485,17 @@ The following shortcuts exist for creating Sequel::SQL::Subscript objects:
|
|
479
485
|
Sequel.subscript(:a, 1)
|
480
486
|
Sequel.subscript(:a, 1, 2)
|
481
487
|
|
482
|
-
:a.sql_subscript(1)
|
483
|
-
:a.sql_subscript(1, 2)
|
488
|
+
:a.sql_subscript(1) # core_extensions extension
|
489
|
+
:a.sql_subscript(1, 2) # core_extensions extension
|
484
490
|
|
485
491
|
=== Sequel::SQL::VirtualRow
|
486
492
|
|
487
493
|
Sequel::SQL::VirtualRow is a BasicObject subclass that is the backbone behind the
|
488
494
|
block expression support:
|
489
495
|
|
490
|
-
DB[:table].
|
496
|
+
DB[:table].where{a < 1}
|
491
497
|
|
492
|
-
In the above code, the block is instance-evaled
|
498
|
+
In the above code, the block is instance-evaled inside a VirtualRow instance.
|
493
499
|
|
494
500
|
These objects are usually not instantiated manually. See the
|
495
501
|
{Virtual Row Guide}[link:files/doc/virtual_rows_rdoc.html] for details.
|