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