sequel 4.13.0 → 4.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +24 -0
- data/doc/active_record.rdoc +4 -4
- data/doc/advanced_associations.rdoc +2 -2
- data/doc/association_basics.rdoc +11 -11
- data/doc/cheat_sheet.rdoc +7 -7
- data/doc/core_extensions.rdoc +1 -1
- data/doc/dataset_filtering.rdoc +1 -1
- data/doc/extensions.rdoc +1 -1
- data/doc/migration.rdoc +3 -3
- data/doc/model_hooks.rdoc +1 -1
- data/doc/opening_databases.rdoc +4 -0
- data/doc/postgresql.rdoc +2 -2
- data/doc/prepared_statements.rdoc +1 -1
- data/doc/querying.rdoc +31 -31
- data/doc/release_notes/4.13.0.txt +1 -1
- data/doc/release_notes/4.14.0.txt +68 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/sharding.rdoc +2 -2
- data/doc/sql.rdoc +1 -1
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/jdbc/jtds.rb +4 -0
- data/lib/sequel/adapters/mysql.rb +18 -18
- data/lib/sequel/adapters/mysql2.rb +7 -7
- data/lib/sequel/adapters/shared/mysql.rb +15 -5
- data/lib/sequel/adapters/shared/postgres.rb +71 -58
- data/lib/sequel/adapters/shared/sqlite.rb +2 -2
- data/lib/sequel/ast_transformer.rb +1 -1
- data/lib/sequel/connection_pool/sharded_single.rb +8 -8
- data/lib/sequel/connection_pool/sharded_threaded.rb +8 -8
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +12 -0
- data/lib/sequel/database/schema_methods.rb +8 -7
- data/lib/sequel/database/transactions.rb +1 -2
- data/lib/sequel/dataset/actions.rb +4 -4
- data/lib/sequel/dataset/graph.rb +4 -0
- data/lib/sequel/dataset/query.rb +18 -18
- data/lib/sequel/dataset/sql.rb +3 -3
- data/lib/sequel/extensions/_pretty_table.rb +1 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +3 -2
- data/lib/sequel/extensions/columns_introspection.rb +1 -0
- data/lib/sequel/extensions/connection_validator.rb +1 -0
- data/lib/sequel/extensions/constraint_validations.rb +1 -0
- data/lib/sequel/extensions/current_datetime_timestamp.rb +1 -0
- data/lib/sequel/extensions/dataset_source_alias.rb +1 -0
- data/lib/sequel/extensions/date_arithmetic.rb +1 -0
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +1 -0
- data/lib/sequel/extensions/error_sql.rb +1 -0
- data/lib/sequel/extensions/eval_inspect.rb +1 -0
- data/lib/sequel/extensions/filter_having.rb +1 -0
- data/lib/sequel/extensions/from_block.rb +1 -0
- data/lib/sequel/extensions/graph_each.rb +1 -0
- data/lib/sequel/extensions/hash_aliases.rb +1 -0
- data/lib/sequel/extensions/looser_typecasting.rb +1 -0
- data/lib/sequel/extensions/meta_def.rb +1 -0
- data/lib/sequel/extensions/migration.rb +1 -0
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +1 -0
- data/lib/sequel/extensions/named_timezones.rb +1 -0
- data/lib/sequel/extensions/null_dataset.rb +1 -0
- data/lib/sequel/extensions/pagination.rb +1 -0
- data/lib/sequel/extensions/pg_array.rb +2 -2
- data/lib/sequel/extensions/pg_array_ops.rb +1 -0
- data/lib/sequel/extensions/pg_enum.rb +1 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +1 -0
- data/lib/sequel/extensions/pg_json_ops.rb +1 -0
- data/lib/sequel/extensions/pg_loose_count.rb +1 -0
- data/lib/sequel/extensions/pg_range_ops.rb +1 -0
- data/lib/sequel/extensions/pg_row_ops.rb +1 -0
- data/lib/sequel/extensions/pg_static_cache_updater.rb +1 -0
- data/lib/sequel/extensions/pretty_table.rb +1 -0
- data/lib/sequel/extensions/query.rb +1 -0
- data/lib/sequel/extensions/query_literals.rb +1 -0
- data/lib/sequel/extensions/schema_caching.rb +1 -0
- data/lib/sequel/extensions/schema_dumper.rb +1 -1
- data/lib/sequel/extensions/select_remove.rb +1 -0
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +1 -0
- data/lib/sequel/extensions/server_block.rb +1 -0
- data/lib/sequel/extensions/set_overrides.rb +1 -0
- data/lib/sequel/extensions/split_array_nil.rb +1 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -0
- data/lib/sequel/extensions/to_dot.rb +1 -0
- data/lib/sequel/model/associations.rb +5 -5
- data/lib/sequel/model/base.rb +3 -3
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/caching.rb +8 -3
- data/lib/sequel/plugins/class_table_inheritance.rb +20 -11
- data/lib/sequel/plugins/composition.rb +18 -18
- data/lib/sequel/plugins/json_serializer.rb +3 -3
- data/lib/sequel/plugins/lazy_attributes.rb +23 -9
- data/lib/sequel/plugins/many_through_many.rb +21 -21
- data/lib/sequel/plugins/nested_attributes.rb +7 -3
- data/lib/sequel/plugins/pg_row.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +13 -13
- data/lib/sequel/plugins/sharding.rb +6 -6
- data/lib/sequel/plugins/timestamps.rb +4 -4
- data/lib/sequel/plugins/touch.rb +7 -7
- data/lib/sequel/plugins/tree.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +36 -36
- data/lib/sequel/plugins/validation_helpers.rb +3 -4
- data/lib/sequel/plugins/xml_serializer.rb +29 -29
- data/lib/sequel/sql.rb +22 -11
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +10 -0
- data/spec/core/database_spec.rb +3 -4
- data/spec/core/dataset_spec.rb +16 -1
- data/spec/core/expression_filters_spec.rb +12 -0
- data/spec/core/object_graph_spec.rb +5 -0
- data/spec/core/placeholder_literalizer_spec.rb +8 -0
- data/spec/extensions/caching_spec.rb +18 -0
- data/spec/extensions/class_table_inheritance_spec.rb +34 -0
- data/spec/extensions/many_through_many_spec.rb +4 -0
- data/spec/extensions/nested_attributes_spec.rb +59 -4
- data/spec/extensions/pg_array_associations_spec.rb +5 -0
- data/spec/extensions/single_table_inheritance_spec.rb +23 -1
- data/spec/integration/plugin_test.rb +17 -0
- data/spec/model/eager_loading_spec.rb +8 -0
- metadata +4 -2
|
@@ -18,17 +18,17 @@ module Sequel
|
|
|
18
18
|
# album.to_json(:only=>:name)
|
|
19
19
|
# album.to_json(:except=>[:id, :artist_id])
|
|
20
20
|
# # => '{"json_class"="Album","name"=>"RF"}'
|
|
21
|
-
#
|
|
21
|
+
#
|
|
22
22
|
# album.to_json(:include=>:artist)
|
|
23
23
|
# # => '{"json_class":"Album","id":1,"name":"RF","artist_id":2,
|
|
24
|
-
#
|
|
24
|
+
# # "artist":{"json_class":"Artist","id":2,"name":"YJM"}}'
|
|
25
25
|
#
|
|
26
26
|
# You can use a hash value with <tt>:include</tt> to pass options
|
|
27
27
|
# to associations:
|
|
28
28
|
#
|
|
29
29
|
# album.to_json(:include=>{:artist=>{:only=>:name}})
|
|
30
30
|
# # => '{"json_class":"Album","id":1,"name":"RF","artist_id":2,
|
|
31
|
-
#
|
|
31
|
+
# # "artist":{"json_class":"Artist","name":"YJM"}}'
|
|
32
32
|
#
|
|
33
33
|
# You can specify the <tt>:root</tt> option to nest the JSON under the
|
|
34
34
|
# name of the model:
|
|
@@ -53,13 +53,15 @@ module Sequel
|
|
|
53
53
|
|
|
54
54
|
private
|
|
55
55
|
|
|
56
|
-
# Add a lazy attribute getter method to the lazy_attributes_module
|
|
57
|
-
|
|
56
|
+
# Add a lazy attribute getter method to the lazy_attributes_module. Options:
|
|
57
|
+
# :dataset :: The base dataset to use for the lazy attribute lookup
|
|
58
|
+
# :table :: The table name to use to qualify the attribute and primary key columns.
|
|
59
|
+
def define_lazy_attribute_getter(a, opts=OPTS)
|
|
58
60
|
include(self.lazy_attributes_module ||= Module.new) unless lazy_attributes_module
|
|
59
61
|
lazy_attributes_module.class_eval do
|
|
60
62
|
define_method(a) do
|
|
61
63
|
if !values.has_key?(a) && !new?
|
|
62
|
-
lazy_attribute_lookup(a)
|
|
64
|
+
lazy_attribute_lookup(a, opts)
|
|
63
65
|
else
|
|
64
66
|
super()
|
|
65
67
|
end
|
|
@@ -75,10 +77,22 @@ module Sequel
|
|
|
75
77
|
# attribute for all of those objects. If not, query the database for
|
|
76
78
|
# the attribute for just the current object. Return the value of
|
|
77
79
|
# the attribute for the current object.
|
|
78
|
-
def lazy_attribute_lookup(a)
|
|
79
|
-
|
|
80
|
+
def lazy_attribute_lookup(a, opts=OPTS)
|
|
81
|
+
unless table = opts[:table]
|
|
82
|
+
table = model.table_name
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
if base_ds = opts[:dataset]
|
|
86
|
+
ds = base_ds.where(model.qualified_primary_key_hash(pk, table))
|
|
87
|
+
else
|
|
88
|
+
base_ds = model.dataset
|
|
89
|
+
ds = this
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
selection = Sequel.qualify(table, a)
|
|
93
|
+
|
|
80
94
|
if frozen?
|
|
81
|
-
return
|
|
95
|
+
return ds.dup.get(selection)
|
|
82
96
|
end
|
|
83
97
|
|
|
84
98
|
if retrieved_with
|
|
@@ -86,15 +100,15 @@ module Sequel
|
|
|
86
100
|
composite_pk = true if primary_key.is_a?(Array)
|
|
87
101
|
id_map = {}
|
|
88
102
|
retrieved_with.each{|o| id_map[o.pk] = o unless o.values.has_key?(a) || o.frozen?}
|
|
89
|
-
predicate_key = composite_pk ? primary_key.map{|k| Sequel.qualify(
|
|
90
|
-
|
|
103
|
+
predicate_key = composite_pk ? primary_key.map{|k| Sequel.qualify(table, k)} : Sequel.qualify(table, primary_key)
|
|
104
|
+
base_ds.select(*(Array(primary_key).map{|k| Sequel.qualify(table, k)} + [selection])).where(predicate_key=>id_map.keys).naked.each do |row|
|
|
91
105
|
obj = id_map[composite_pk ? row.values_at(*primary_key) : row[primary_key]]
|
|
92
106
|
if obj && !obj.values.has_key?(a)
|
|
93
107
|
obj.values[a] = row[a]
|
|
94
108
|
end
|
|
95
109
|
end
|
|
96
110
|
end
|
|
97
|
-
values[a] =
|
|
111
|
+
values[a] = ds.get(selection) unless values.has_key?(a)
|
|
98
112
|
values[a]
|
|
99
113
|
end
|
|
100
114
|
end
|
|
@@ -20,9 +20,9 @@ module Sequel
|
|
|
20
20
|
#
|
|
21
21
|
# This argument is an array of arrays with three elements. Each entry in the main array represents a JOIN in SQL:
|
|
22
22
|
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
23
|
+
# first element :: represents the name of the table to join.
|
|
24
|
+
# second element :: represents the column used to join to the previous table.
|
|
25
|
+
# third element :: represents the column used to join to the next table.
|
|
26
26
|
#
|
|
27
27
|
# So the "Artist.many_through_many :tags" is translated into something similar to:
|
|
28
28
|
#
|
|
@@ -180,21 +180,21 @@ module Sequel
|
|
|
180
180
|
|
|
181
181
|
module ClassMethods
|
|
182
182
|
# Create a many_through_many association. Arguments:
|
|
183
|
-
#
|
|
184
|
-
#
|
|
185
|
-
#
|
|
186
|
-
#
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
#
|
|
190
|
-
#
|
|
191
|
-
#
|
|
192
|
-
#
|
|
193
|
-
#
|
|
194
|
-
#
|
|
195
|
-
#
|
|
196
|
-
#
|
|
197
|
-
#
|
|
183
|
+
# name :: Same as associate, the name of the association.
|
|
184
|
+
# through :: The tables and keys to join between the current table and the associated table.
|
|
185
|
+
# Must be an array, with elements that are either 3 element arrays, or hashes with keys :table, :left, and :right.
|
|
186
|
+
# The required entries in the array/hash are:
|
|
187
|
+
# :table (first array element) :: The name of the table to join.
|
|
188
|
+
# :left (middle array element) :: The key joining the table to the previous table. Can use an
|
|
189
|
+
# array of symbols for a composite key association.
|
|
190
|
+
# :right (last array element) :: The key joining the table to the next table. Can use an
|
|
191
|
+
# array of symbols for a composite key association.
|
|
192
|
+
# If a hash is provided, the following keys are respected when using eager_graph:
|
|
193
|
+
# :block :: A proc to use as the block argument to join.
|
|
194
|
+
# :conditions :: Extra conditions to add to the JOIN ON clause. Must be a hash or array of two pairs.
|
|
195
|
+
# :join_type :: The join type to use for the join, defaults to :left_outer.
|
|
196
|
+
# :only_conditions :: Conditions to use for the join instead of the ones specified by the keys.
|
|
197
|
+
# opts :: The options for the associaion. Takes the same options as many_to_many.
|
|
198
198
|
def many_through_many(name, through, opts=OPTS, &block)
|
|
199
199
|
associate(:many_through_many, name, opts.merge(through.is_a?(Hash) ? through : {:through=>through}), &block)
|
|
200
200
|
end
|
|
@@ -257,14 +257,14 @@ module Sequel
|
|
|
257
257
|
select_all(egds.first_source).
|
|
258
258
|
select_append(*associated_key_array)
|
|
259
259
|
egds = opts.apply_eager_graph_limit_strategy(egls, egds)
|
|
260
|
-
ds.graph(egds, associated_key_array.map{|v| v.alias}.zip(Array(lpkcs)) + conditions, :qualify=>:deep, :table_alias=>eo[:table_alias], :implicit_qualifier=>iq, :join_type=>eo[:join_type]||join_type, :from_self_alias=>eo[:from_self_alias], :select=>select||orig_egds.columns, &graph_block)
|
|
260
|
+
ds.graph(egds, associated_key_array.map{|v| v.alias}.zip(Array(lpkcs)) + conditions, :qualify=>:deep, :table_alias=>eo[:table_alias], :implicit_qualifier=>iq, :join_type=>eo[:join_type]||join_type, :join_only=>eo[:join_only], :from_self_alias=>eo[:from_self_alias], :select=>select||orig_egds.columns, &graph_block)
|
|
261
261
|
else
|
|
262
262
|
opts.edges.each do |t|
|
|
263
|
-
ds = ds.graph(t[:table], t.fetch(:only_conditions, (Array(t[:right]).zip(Array(t[:left])) + t[:conditions])), :select=>false, :table_alias=>ds.unused_table_alias(t[:table]), :join_type=>eo[:join_type]||t[:join_type], :qualify=>:deep, :implicit_qualifier=>iq, :from_self_alias=>eo[:from_self_alias], &t[:block])
|
|
263
|
+
ds = ds.graph(t[:table], t.fetch(:only_conditions, (Array(t[:right]).zip(Array(t[:left])) + t[:conditions])), :select=>false, :table_alias=>ds.unused_table_alias(t[:table]), :join_type=>eo[:join_type]||t[:join_type], :join_only=>eo[:join_only], :qualify=>:deep, :implicit_qualifier=>iq, :from_self_alias=>eo[:from_self_alias], &t[:block])
|
|
264
264
|
iq = nil
|
|
265
265
|
end
|
|
266
266
|
fe = opts.final_edge
|
|
267
|
-
ds.graph(opts.associated_class, use_only_conditions ? only_conditions : (Array(opts.right_primary_key).zip(Array(fe[:left])) + conditions), :select=>select, :table_alias=>eo[:table_alias], :qualify=>:deep, :join_type=>eo[:join_type]||join_type, &graph_block)
|
|
267
|
+
ds.graph(opts.associated_class, use_only_conditions ? only_conditions : (Array(opts.right_primary_key).zip(Array(fe[:left])) + conditions), :select=>select, :table_alias=>eo[:table_alias], :qualify=>:deep, :join_type=>eo[:join_type]||join_type, :join_only=>eo[:join_only], &graph_block)
|
|
268
268
|
end
|
|
269
269
|
end
|
|
270
270
|
end
|
|
@@ -62,7 +62,7 @@ module Sequel
|
|
|
62
62
|
#
|
|
63
63
|
# Your web stack will probably parse that into a nested hash similar to:
|
|
64
64
|
#
|
|
65
|
-
# {:artist=>{:name
|
|
65
|
+
# {:artist=>{:name=>'Y', :albums_attributes=>{0=>{:name=>'X'}, 1=>{:id=>'2', :name=>'Z'}}}}
|
|
66
66
|
#
|
|
67
67
|
# Then you can do:
|
|
68
68
|
#
|
|
@@ -218,6 +218,9 @@ module Sequel
|
|
|
218
218
|
end
|
|
219
219
|
end
|
|
220
220
|
after_save_hook{obj.destroy} if opts[:destroy]
|
|
221
|
+
if reflection.returns_array?
|
|
222
|
+
associations[reflection[:name]].delete(obj)
|
|
223
|
+
end
|
|
221
224
|
obj
|
|
222
225
|
end
|
|
223
226
|
|
|
@@ -304,8 +307,9 @@ module Sequel
|
|
|
304
307
|
# which will fail if we validate before saving the current object. If there is
|
|
305
308
|
# no value for the foreign key, set it to the current primary key value, or a dummy
|
|
306
309
|
# value of 0 if we haven't saved the current object.
|
|
307
|
-
|
|
308
|
-
key =
|
|
310
|
+
p_key = pk unless pk.is_a?(Array)
|
|
311
|
+
obj.values[key] = p_key || 0
|
|
312
|
+
key = nil if p_key
|
|
309
313
|
end
|
|
310
314
|
obj.errors.full_messages.each{|m| errors.add(association, m)} unless obj.valid?
|
|
311
315
|
if key && !pk_val
|
|
@@ -28,7 +28,7 @@ module Sequel
|
|
|
28
28
|
#
|
|
29
29
|
# DB[:company].first
|
|
30
30
|
# # => {:name=>'MS', :address=>
|
|
31
|
-
#
|
|
31
|
+
# # Address.load(:street=>'123 Foo St', :city=>'Bar Town', :zip=>'12345')}
|
|
32
32
|
#
|
|
33
33
|
# If you want a lot of your models to be used as row types, you can load the
|
|
34
34
|
# plugin into Sequel::Model itself:
|
|
@@ -66,10 +66,10 @@ module Sequel
|
|
|
66
66
|
# You can override the options for any specific association by making
|
|
67
67
|
# sure the plugin options contain one of the following keys:
|
|
68
68
|
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
69
|
+
# :parent :: hash of options for the parent association
|
|
70
|
+
# :children :: hash of options for the children association
|
|
71
|
+
# :ancestors :: hash of options for the ancestors association
|
|
72
|
+
# :descendants :: hash of options for the descendants association
|
|
73
73
|
#
|
|
74
74
|
# Note that you can change the name of the above associations by specifying
|
|
75
75
|
# a :name key in the appropriate hash of options above. For example:
|
|
@@ -80,15 +80,15 @@ module Sequel
|
|
|
80
80
|
# Any other keys in the main options hash are treated as options shared by
|
|
81
81
|
# all of the associations. Here's a few options that affect the plugin:
|
|
82
82
|
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
#
|
|
83
|
+
# :key :: The foreign key in the table that points to the primary key
|
|
84
|
+
# of the parent (default: :parent_id)
|
|
85
|
+
# :primary_key :: The primary key to use (default: the model's primary key)
|
|
86
|
+
# :key_alias :: The symbol identifier to use for aliasing when eager
|
|
87
|
+
# loading (default: :x_root_x)
|
|
88
|
+
# :cte_name :: The symbol identifier to use for the common table expression
|
|
89
|
+
# (default: :t)
|
|
90
|
+
# :level_alias :: The symbol identifier to use when eagerly loading descendants
|
|
91
|
+
# up to a given level (default: :x_level_x)
|
|
92
92
|
module RcteTree
|
|
93
93
|
# Create the appropriate parent, children, ancestors, and descendants
|
|
94
94
|
# associations for the model.
|
|
@@ -3,12 +3,12 @@ module Sequel
|
|
|
3
3
|
# The sharding plugin augments Sequel's default model sharding support
|
|
4
4
|
# in the following ways:
|
|
5
5
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
6
|
+
# * It automatically sets model instances to be saved back to the
|
|
7
|
+
# shard they were retreived from.
|
|
8
|
+
# * It makes model associations use the same shard as the model
|
|
9
|
+
# object.
|
|
10
|
+
# * It adds a slightly nicer API for creating model instances on
|
|
11
|
+
# specific shards.
|
|
12
12
|
#
|
|
13
13
|
# Usage:
|
|
14
14
|
#
|
|
@@ -22,10 +22,10 @@ module Sequel
|
|
|
22
22
|
# Configure the plugin by setting the available options. Note that
|
|
23
23
|
# if this method is run more than once, previous settings are ignored,
|
|
24
24
|
# and it will just use the settings given or the default settings. Options:
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
25
|
+
# :create :: The field to hold the create timestamp (default: :created_at)
|
|
26
|
+
# :force :: Whether to overwrite an existing create timestamp (default: false)
|
|
27
|
+
# :update :: The field to hold the update timestamp (default: :updated_at)
|
|
28
|
+
# :update_on_create :: Whether to set the update timestamp to the create timestamp when creating (default: false)
|
|
29
29
|
def self.configure(model, opts=OPTS)
|
|
30
30
|
model.instance_eval do
|
|
31
31
|
@create_timestamp_field = opts[:create]||:created_at
|
data/lib/sequel/plugins/touch.rb
CHANGED
|
@@ -36,13 +36,13 @@ module Sequel
|
|
|
36
36
|
|
|
37
37
|
# Set the touch_column and touched_associations variables for the model.
|
|
38
38
|
# Options:
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
39
|
+
# :associations :: The associations to touch when a model instance is
|
|
40
|
+
# updated or destroyed. Can be a symbol for a single association,
|
|
41
|
+
# a hash with association keys and column values, or an array of
|
|
42
|
+
# symbols and/or hashes. If a symbol is used, the column used
|
|
43
|
+
# when updating the associated objects is the model's touch_column.
|
|
44
|
+
# If a hash is used, the value is used as the column to update.
|
|
45
|
+
# :column :: The column to modify when touching a model instance.
|
|
46
46
|
def self.configure(model, opts=OPTS)
|
|
47
47
|
model.touch_column = opts[:column] || TOUCH_COLUMN_DEFAULT if opts[:column] || !model.touch_column
|
|
48
48
|
model.touch_associations(opts[:associations]) if opts[:associations]
|
data/lib/sequel/plugins/tree.rb
CHANGED
|
@@ -70,7 +70,7 @@ module Sequel
|
|
|
70
70
|
|
|
71
71
|
# Returns the dataset for retrieval of all root nodes
|
|
72
72
|
#
|
|
73
|
-
# TreeClass.roots_dataset => Sequel
|
|
73
|
+
# TreeClass.roots_dataset # => Sequel::Dataset instance
|
|
74
74
|
def roots_dataset
|
|
75
75
|
ds = where(Sequel.or(Array(parent_column).zip([])))
|
|
76
76
|
ds = ds.order(*tree_order) if tree_order
|
|
@@ -116,8 +116,8 @@ module Sequel
|
|
|
116
116
|
# :allow_nil is assumed to be true instead of false.
|
|
117
117
|
#
|
|
118
118
|
# Possible Options:
|
|
119
|
-
#
|
|
120
|
-
#
|
|
119
|
+
# :accept :: The value required for the object to be valid (default: '1')
|
|
120
|
+
# :message :: The message to use (default: 'is not accepted')
|
|
121
121
|
def validates_acceptance_of(*atts)
|
|
122
122
|
opts = {
|
|
123
123
|
:message => 'is not accepted',
|
|
@@ -141,7 +141,7 @@ module Sequel
|
|
|
141
141
|
# or email addresses on web forms.
|
|
142
142
|
#
|
|
143
143
|
# Possible Options:
|
|
144
|
-
#
|
|
144
|
+
# :message :: The message to use (default: 'is not confirmed')
|
|
145
145
|
def validates_confirmation_of(*atts)
|
|
146
146
|
opts = {
|
|
147
147
|
:message => 'is not confirmed',
|
|
@@ -163,20 +163,20 @@ module Sequel
|
|
|
163
163
|
# end
|
|
164
164
|
#
|
|
165
165
|
# Possible Options:
|
|
166
|
-
#
|
|
167
|
-
#
|
|
168
|
-
#
|
|
169
|
-
#
|
|
170
|
-
#
|
|
171
|
-
#
|
|
172
|
-
#
|
|
173
|
-
#
|
|
174
|
-
#
|
|
175
|
-
#
|
|
176
|
-
#
|
|
177
|
-
#
|
|
178
|
-
#
|
|
179
|
-
#
|
|
166
|
+
# :allow_blank :: Whether to skip the validation if the value is blank.
|
|
167
|
+
# :allow_missing :: Whether to skip the validation if the attribute isn't a key in the
|
|
168
|
+
# values hash. This is different from allow_nil, because Sequel only sends the attributes
|
|
169
|
+
# in the values when doing an insert or update. If the attribute is not present, Sequel
|
|
170
|
+
# doesn't specify it, so the database will use the table's default value. This is different
|
|
171
|
+
# from having an attribute in values with a value of nil, which Sequel will send as NULL.
|
|
172
|
+
# If your database table has a non NULL default, this may be a good option to use. You
|
|
173
|
+
# don't want to use allow_nil, because if the attribute is in values but has a value nil,
|
|
174
|
+
# Sequel will attempt to insert a NULL value into the database, instead of using the
|
|
175
|
+
# database's default.
|
|
176
|
+
# :allow_nil :: Whether to skip the validation if the value is nil.
|
|
177
|
+
# :if :: A symbol (indicating an instance_method) or proc (which is instance_evaled)
|
|
178
|
+
# skipping this validation if it returns nil or false.
|
|
179
|
+
# :tag :: The tag to use for this validation.
|
|
180
180
|
def validates_each(*atts, &block)
|
|
181
181
|
opts = extract_options!(atts)
|
|
182
182
|
blk = if (i = opts[:if]) || (am = opts[:allow_missing]) || (an = opts[:allow_nil]) || (ab = opts[:allow_blank])
|
|
@@ -205,8 +205,8 @@ module Sequel
|
|
|
205
205
|
# value against the regular expression provided by the :with option.
|
|
206
206
|
#
|
|
207
207
|
# Possible Options:
|
|
208
|
-
#
|
|
209
|
-
#
|
|
208
|
+
# :message :: The message to use (default: 'is invalid')
|
|
209
|
+
# :with :: The regular expression to validate the value with (required).
|
|
210
210
|
def validates_format_of(*atts)
|
|
211
211
|
opts = {
|
|
212
212
|
:message => 'is invalid',
|
|
@@ -227,16 +227,16 @@ module Sequel
|
|
|
227
227
|
# Validates the length of an attribute.
|
|
228
228
|
#
|
|
229
229
|
# Possible Options:
|
|
230
|
-
#
|
|
231
|
-
#
|
|
232
|
-
#
|
|
233
|
-
#
|
|
234
|
-
#
|
|
235
|
-
#
|
|
236
|
-
#
|
|
237
|
-
#
|
|
238
|
-
#
|
|
239
|
-
#
|
|
230
|
+
# :is :: The exact size required for the value to be valid (no default)
|
|
231
|
+
# :maximum :: The maximum size allowed for the value (no default)
|
|
232
|
+
# :message :: The message to use (no default, overrides :nil_message, :too_long, :too_short, and :wrong_length
|
|
233
|
+
# options if present)
|
|
234
|
+
# :minimum :: The minimum size allowed for the value (no default)
|
|
235
|
+
# :nil_message :: The message to use use if :maximum option is used and the value is nil (default: 'is not present')
|
|
236
|
+
# :too_long :: The message to use use if it the value is too long (default: 'is too long')
|
|
237
|
+
# :too_short :: The message to use use if it the value is too short (default: 'is too short')
|
|
238
|
+
# :within :: The array/range that must include the size of the value for it to be valid (no default)
|
|
239
|
+
# :wrong_length :: The message to use use if it the value is not valid (default: 'is the wrong length')
|
|
240
240
|
def validates_length_of(*atts)
|
|
241
241
|
opts = {
|
|
242
242
|
:nil_message => 'is not present',
|
|
@@ -267,8 +267,8 @@ module Sequel
|
|
|
267
267
|
# Validates whether an attribute is a number.
|
|
268
268
|
#
|
|
269
269
|
# Possible Options:
|
|
270
|
-
#
|
|
271
|
-
#
|
|
270
|
+
# :message :: The message to use (default: 'is not a number')
|
|
271
|
+
# :only_integer :: Whether only integers are valid values (default: false)
|
|
272
272
|
def validates_numericality_of(*atts)
|
|
273
273
|
opts = {
|
|
274
274
|
:message => 'is not a number',
|
|
@@ -293,7 +293,7 @@ module Sequel
|
|
|
293
293
|
# with false considered present instead of absent.
|
|
294
294
|
#
|
|
295
295
|
# Possible Options:
|
|
296
|
-
#
|
|
296
|
+
# :message :: The message to use (default: 'is not present')
|
|
297
297
|
def validates_presence_of(*atts)
|
|
298
298
|
opts = {
|
|
299
299
|
:message => 'is not present',
|
|
@@ -309,8 +309,8 @@ module Sequel
|
|
|
309
309
|
# Validates that an attribute is within a specified range or set of values.
|
|
310
310
|
#
|
|
311
311
|
# Possible Options:
|
|
312
|
-
#
|
|
313
|
-
#
|
|
312
|
+
# :in :: An array or range of values to check for validity (required)
|
|
313
|
+
# :message :: The message to use (default: 'is not in range or set: <specified range>')
|
|
314
314
|
def validates_inclusion_of(*atts)
|
|
315
315
|
opts = extract_options!(atts)
|
|
316
316
|
n = opts[:in]
|
|
@@ -331,7 +331,7 @@ module Sequel
|
|
|
331
331
|
# time instead of at setter time.
|
|
332
332
|
#
|
|
333
333
|
# Possible Options:
|
|
334
|
-
#
|
|
334
|
+
# :message :: The message to use (default: 'is not a valid (integer|datetime|etc.)')
|
|
335
335
|
def validates_schema_type(*atts)
|
|
336
336
|
opts = {
|
|
337
337
|
:tag => :schema_type,
|
|
@@ -362,7 +362,7 @@ module Sequel
|
|
|
362
362
|
# database, as this suffers from a fairly obvious race condition.
|
|
363
363
|
#
|
|
364
364
|
# Possible Options:
|
|
365
|
-
#
|
|
365
|
+
# :message :: The message to use (default: 'is already taken')
|
|
366
366
|
def validates_uniqueness_of(*atts)
|
|
367
367
|
opts = {
|
|
368
368
|
:message => 'is already taken',
|
|
@@ -19,7 +19,7 @@ module Sequel
|
|
|
19
19
|
# Options:
|
|
20
20
|
# :allow_blank :: Whether to skip the validation if the value is blank. You should
|
|
21
21
|
# make sure all objects respond to blank if you use this option, which you can do by:
|
|
22
|
-
#
|
|
22
|
+
# Sequel.extension :blank
|
|
23
23
|
# :allow_missing :: Whether to skip the validation if the attribute isn't a key in the
|
|
24
24
|
# values hash. This is different from allow_nil, because Sequel only sends the attributes
|
|
25
25
|
# in the values when doing an insert or update. If the attribute is not present, Sequel
|
|
@@ -44,8 +44,7 @@ module Sequel
|
|
|
44
44
|
#
|
|
45
45
|
# Sequel::Plugins::ValidationHelpers::DEFAULT_OPTIONS.merge!(
|
|
46
46
|
# :exact_length=>{:message=>lambda{|exact| I18n.t("errors.exact_length", :exact => exact)}},
|
|
47
|
-
# :integer=>{:message=>lambda{I18n.t("errors.integer")}}
|
|
48
|
-
# ...
|
|
47
|
+
# :integer=>{:message=>lambda{I18n.t("errors.integer")}}
|
|
49
48
|
# )
|
|
50
49
|
#
|
|
51
50
|
# and then use something like this in your yaml translation file:
|
|
@@ -215,7 +214,7 @@ module Sequel
|
|
|
215
214
|
# If you want to to a case insensitive uniqueness validation on a database that
|
|
216
215
|
# is case sensitive by default, you can use:
|
|
217
216
|
#
|
|
218
|
-
# :where=>(proc do |ds, obj, cols|
|
|
217
|
+
# validates_unique :column, :where=>(proc do |ds, obj, cols|
|
|
219
218
|
# ds.where(cols.map do |c|
|
|
220
219
|
# v = obj.send(c)
|
|
221
220
|
# v = v.downcase if v
|