sequel 4.22.0 → 4.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +22 -0
- data/README.rdoc +6 -0
- data/Rakefile +59 -81
- data/doc/migration.rdoc +2 -0
- data/doc/release_notes/4.23.0.txt +65 -0
- data/doc/sharding.rdoc +16 -14
- data/doc/testing.rdoc +61 -77
- data/lib/sequel/adapters/jdbc.rb +1 -0
- data/lib/sequel/adapters/mock.rb +0 -1
- data/lib/sequel/adapters/postgres.rb +1 -0
- data/lib/sequel/adapters/postgresql.rb +1 -0
- data/lib/sequel/adapters/shared/postgres.rb +3 -3
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +9 -1
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/transactions.rb +2 -1
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +12 -12
- data/lib/sequel/extensions/date_arithmetic.rb +0 -4
- data/lib/sequel/extensions/pagination.rb +14 -2
- data/lib/sequel/extensions/pg_enum.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/delay_add_association.rb +50 -0
- data/lib/sequel/plugins/list.rb +2 -2
- data/lib/sequel/plugins/nested_attributes.rb +8 -28
- data/lib/sequel/plugins/update_refresh.rb +50 -0
- data/lib/sequel/plugins/validate_associated.rb +55 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +29 -29
- data/spec/adapters/firebird_spec.rb +97 -103
- data/spec/adapters/informix_spec.rb +25 -25
- data/spec/adapters/mssql_spec.rb +156 -172
- data/spec/adapters/mysql_spec.rb +334 -359
- data/spec/adapters/oracle_spec.rb +67 -69
- data/spec/adapters/postgres_spec.rb +1298 -1249
- data/spec/adapters/spec_helper.rb +2 -35
- data/spec/adapters/sqlanywhere_spec.rb +39 -39
- data/spec/adapters/sqlite_spec.rb +203 -200
- data/spec/bin_spec.rb +57 -59
- data/spec/core/connection_pool_spec.rb +402 -401
- data/spec/core/database_spec.rb +953 -944
- data/spec/core/dataset_spec.rb +2178 -2168
- data/spec/core/deprecated_spec.rb +19 -19
- data/spec/core/expression_filters_spec.rb +415 -415
- data/spec/core/mock_adapter_spec.rb +212 -212
- data/spec/core/object_graph_spec.rb +73 -73
- data/spec/core/placeholder_literalizer_spec.rb +71 -71
- data/spec/core/schema_generator_spec.rb +44 -44
- data/spec/core/schema_spec.rb +470 -472
- data/spec/core/spec_helper.rb +5 -20
- data/spec/core/version_spec.rb +2 -2
- data/spec/core_extensions_spec.rb +320 -320
- data/spec/extensions/accessed_columns_spec.rb +12 -12
- data/spec/extensions/active_model_spec.rb +3 -3
- data/spec/extensions/after_initialize_spec.rb +2 -2
- data/spec/extensions/arbitrary_servers_spec.rb +23 -23
- data/spec/extensions/association_dependencies_spec.rb +34 -34
- data/spec/extensions/association_pks_spec.rb +98 -98
- data/spec/extensions/association_proxies_spec.rb +33 -33
- data/spec/extensions/auto_validations_spec.rb +46 -46
- data/spec/extensions/blacklist_security_spec.rb +19 -18
- data/spec/extensions/blank_spec.rb +36 -36
- data/spec/extensions/boolean_readers_spec.rb +36 -36
- data/spec/extensions/caching_spec.rb +82 -82
- data/spec/extensions/class_table_inheritance_spec.rb +72 -72
- data/spec/extensions/column_conflicts_spec.rb +19 -14
- data/spec/extensions/column_select_spec.rb +19 -19
- data/spec/extensions/columns_introspection_spec.rb +43 -43
- data/spec/extensions/composition_spec.rb +64 -64
- data/spec/extensions/connection_validator_spec.rb +92 -90
- data/spec/extensions/constraint_validations_plugin_spec.rb +92 -92
- data/spec/extensions/constraint_validations_spec.rb +80 -80
- data/spec/extensions/core_refinements_spec.rb +220 -220
- data/spec/extensions/csv_serializer_spec.rb +44 -44
- data/spec/extensions/current_datetime_timestamp_spec.rb +8 -8
- data/spec/extensions/dataset_associations_spec.rb +65 -65
- data/spec/extensions/dataset_source_alias_spec.rb +16 -16
- data/spec/extensions/date_arithmetic_spec.rb +51 -58
- data/spec/extensions/defaults_setter_spec.rb +19 -19
- data/spec/extensions/delay_add_association_spec.rb +52 -0
- data/spec/extensions/dirty_spec.rb +51 -51
- data/spec/extensions/eager_each_spec.rb +8 -8
- data/spec/extensions/empty_array_ignore_nulls_spec.rb +10 -10
- data/spec/extensions/error_splitter_spec.rb +2 -2
- data/spec/extensions/error_sql_spec.rb +4 -4
- data/spec/extensions/eval_inspect_spec.rb +3 -3
- data/spec/extensions/filter_having_spec.rb +8 -8
- data/spec/extensions/force_encoding_spec.rb +30 -30
- data/spec/extensions/from_block_spec.rb +7 -7
- data/spec/extensions/graph_each_spec.rb +19 -19
- data/spec/extensions/hash_aliases_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +100 -100
- data/spec/extensions/inflector_spec.rb +54 -54
- data/spec/extensions/input_transformer_spec.rb +10 -10
- data/spec/extensions/insert_returning_select_spec.rb +8 -8
- data/spec/extensions/instance_filters_spec.rb +26 -26
- data/spec/extensions/instance_hooks_spec.rb +85 -85
- data/spec/extensions/json_serializer_spec.rb +68 -68
- data/spec/extensions/lazy_attributes_spec.rb +49 -49
- data/spec/extensions/list_spec.rb +77 -75
- data/spec/extensions/looser_typecasting_spec.rb +16 -16
- data/spec/extensions/many_through_many_spec.rb +627 -627
- data/spec/extensions/meta_def_spec.rb +7 -7
- data/spec/extensions/migration_spec.rb +217 -217
- data/spec/extensions/modification_detection_spec.rb +20 -20
- data/spec/extensions/mssql_optimistic_locking_spec.rb +21 -21
- data/spec/extensions/named_timezones_spec.rb +18 -18
- data/spec/extensions/nested_attributes_spec.rb +107 -107
- data/spec/extensions/null_dataset_spec.rb +24 -24
- data/spec/extensions/optimistic_locking_spec.rb +21 -21
- data/spec/extensions/pagination_spec.rb +52 -52
- data/spec/extensions/pg_array_associations_spec.rb +273 -273
- data/spec/extensions/pg_array_ops_spec.rb +52 -52
- data/spec/extensions/pg_array_spec.rb +152 -152
- data/spec/extensions/pg_enum_spec.rb +13 -13
- data/spec/extensions/pg_hstore_ops_spec.rb +63 -63
- data/spec/extensions/pg_hstore_spec.rb +84 -84
- data/spec/extensions/pg_inet_spec.rb +15 -15
- data/spec/extensions/pg_interval_spec.rb +29 -29
- data/spec/extensions/pg_json_ops_spec.rb +86 -84
- data/spec/extensions/pg_json_spec.rb +104 -104
- data/spec/extensions/pg_loose_count_spec.rb +6 -6
- data/spec/extensions/pg_range_ops_spec.rb +24 -24
- data/spec/extensions/pg_range_spec.rb +143 -143
- data/spec/extensions/pg_row_ops_spec.rb +14 -14
- data/spec/extensions/pg_row_plugin_spec.rb +12 -12
- data/spec/extensions/pg_row_spec.rb +118 -118
- data/spec/extensions/pg_static_cache_updater_spec.rb +28 -28
- data/spec/extensions/pg_typecast_on_load_spec.rb +21 -21
- data/spec/extensions/prepared_statements_associations_spec.rb +42 -42
- data/spec/extensions/prepared_statements_safe_spec.rb +18 -18
- data/spec/extensions/prepared_statements_spec.rb +28 -28
- data/spec/extensions/prepared_statements_with_pk_spec.rb +11 -11
- data/spec/extensions/pretty_table_spec.rb +16 -16
- data/spec/extensions/query_literals_spec.rb +37 -37
- data/spec/extensions/query_spec.rb +32 -32
- data/spec/extensions/rcte_tree_spec.rb +141 -141
- data/spec/extensions/round_timestamps_spec.rb +21 -21
- data/spec/extensions/schema_caching_spec.rb +8 -8
- data/spec/extensions/schema_dumper_spec.rb +78 -78
- data/spec/extensions/schema_spec.rb +31 -27
- data/spec/extensions/scissors_spec.rb +3 -3
- data/spec/extensions/select_remove_spec.rb +14 -14
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +28 -28
- data/spec/extensions/serialization_modification_detection_spec.rb +33 -33
- data/spec/extensions/serialization_spec.rb +79 -78
- data/spec/extensions/server_block_spec.rb +17 -17
- data/spec/extensions/set_overrides_spec.rb +30 -30
- data/spec/extensions/sharding_spec.rb +65 -65
- data/spec/extensions/shared_caching_spec.rb +29 -29
- data/spec/extensions/single_table_inheritance_spec.rb +79 -79
- data/spec/extensions/skip_create_refresh_spec.rb +3 -3
- data/spec/extensions/spec_helper.rb +4 -29
- data/spec/extensions/split_array_nil_spec.rb +9 -9
- data/spec/extensions/split_values_spec.rb +7 -7
- data/spec/extensions/sql_expr_spec.rb +32 -32
- data/spec/extensions/static_cache_spec.rb +123 -123
- data/spec/extensions/string_date_time_spec.rb +34 -34
- data/spec/extensions/string_stripper_spec.rb +15 -15
- data/spec/extensions/subclasses_spec.rb +31 -31
- data/spec/extensions/table_select_spec.rb +15 -15
- data/spec/extensions/tactical_eager_loading_spec.rb +23 -23
- data/spec/extensions/thread_local_timezones_spec.rb +13 -13
- data/spec/extensions/timestamps_spec.rb +40 -40
- data/spec/extensions/to_dot_spec.rb +34 -34
- data/spec/extensions/touch_spec.rb +52 -52
- data/spec/extensions/tree_spec.rb +72 -72
- data/spec/extensions/typecast_on_load_spec.rb +25 -25
- data/spec/extensions/unlimited_update_spec.rb +2 -2
- data/spec/extensions/update_or_create_spec.rb +36 -36
- data/spec/extensions/update_primary_key_spec.rb +35 -35
- data/spec/extensions/update_refresh_spec.rb +41 -0
- data/spec/extensions/validate_associated_spec.rb +52 -0
- data/spec/extensions/validation_class_methods_spec.rb +314 -317
- data/spec/extensions/validation_helpers_spec.rb +195 -195
- data/spec/extensions/xml_serializer_spec.rb +48 -48
- data/spec/guards_helper.rb +55 -0
- data/spec/integration/associations_test.rb +1089 -1088
- data/spec/integration/database_test.rb +29 -29
- data/spec/integration/dataset_test.rb +661 -661
- data/spec/integration/eager_loader_test.rb +147 -147
- data/spec/integration/migrator_test.rb +122 -122
- data/spec/integration/model_test.rb +70 -70
- data/spec/integration/plugin_test.rb +682 -640
- data/spec/integration/prepared_statement_test.rb +172 -172
- data/spec/integration/schema_test.rb +245 -245
- data/spec/integration/spec_helper.rb +1 -64
- data/spec/integration/timezone_test.rb +17 -17
- data/spec/integration/transaction_test.rb +87 -87
- data/spec/integration/type_test.rb +33 -33
- data/spec/model/association_reflection_spec.rb +130 -121
- data/spec/model/associations_spec.rb +1112 -1113
- data/spec/model/base_spec.rb +197 -196
- data/spec/model/class_dataset_methods_spec.rb +118 -118
- data/spec/model/dataset_methods_spec.rb +49 -49
- data/spec/model/eager_loading_spec.rb +705 -702
- data/spec/model/hooks_spec.rb +169 -168
- data/spec/model/inflector_spec.rb +5 -5
- data/spec/model/model_spec.rb +287 -297
- data/spec/model/plugins_spec.rb +47 -47
- data/spec/model/record_spec.rb +534 -535
- data/spec/model/spec_helper.rb +3 -21
- data/spec/model/validations_spec.rb +72 -70
- data/spec/spec_config.rb +8 -0
- metadata +41 -9
- data/lib/sequel/adapters/fdbsql.rb +0 -286
- data/lib/sequel/adapters/jdbc/fdbsql.rb +0 -66
- data/lib/sequel/adapters/openbase.rb +0 -54
- data/lib/sequel/adapters/shared/fdbsql.rb +0 -550
- data/spec/adapters/fdbsql_spec.rb +0 -429
- data/spec/rspec_helper.rb +0 -22
data/lib/sequel/adapters/jdbc.rb
CHANGED
data/lib/sequel/adapters/mock.rb
CHANGED
@@ -189,6 +189,7 @@ module Sequel
|
|
189
189
|
INFINITE_TIMESTAMP_STRINGS = ['infinity'.freeze, '-infinity'.freeze].freeze
|
190
190
|
INFINITE_DATETIME_VALUES = ([PLUS_INFINITY, MINUS_INFINITY] + INFINITE_TIMESTAMP_STRINGS).freeze
|
191
191
|
|
192
|
+
set_adapter_scheme :postgresql
|
192
193
|
set_adapter_scheme :postgres
|
193
194
|
|
194
195
|
# Whether infinite timestamps/dates should be converted on retrieval. By default, no
|
@@ -0,0 +1 @@
|
|
1
|
+
Sequel.require 'adapters/postgres'
|
@@ -706,7 +706,7 @@ module Sequel
|
|
706
706
|
# Convert the hash of named conversion procs into a hash a oid conversion procs.
|
707
707
|
def convert_named_procs_to_procs(named_procs)
|
708
708
|
h = {}
|
709
|
-
from(:pg_type).where(:typtype=>'b', :typname=>named_procs.keys.map(&:to_s)).select_map([:oid, :typname]).each do |oid, name|
|
709
|
+
from(:pg_type).where(:typtype=>['b', 'e'], :typname=>named_procs.keys.map(&:to_s)).select_map([:oid, :typname]).each do |oid, name|
|
710
710
|
h[oid.to_i] = named_procs[name.untaint.to_sym]
|
711
711
|
end
|
712
712
|
h
|
@@ -1294,9 +1294,9 @@ module Sequel
|
|
1294
1294
|
# returned rows also include the exact phrase used.
|
1295
1295
|
# :rank :: Set to true to order by the rank, so that closer matches are returned first.
|
1296
1296
|
# :tsquery :: Specifies the terms argument is already a valid SQL expression returning a
|
1297
|
-
#
|
1297
|
+
# tsquery, and can be used directly in the query.
|
1298
1298
|
# :tsvector :: Specifies the cols argument is already a valid SQL expression returning a
|
1299
|
-
#
|
1299
|
+
# tsvector, and can be used directly in the query.
|
1300
1300
|
def full_text_search(cols, terms, opts = OPTS)
|
1301
1301
|
lang = Sequel.cast(opts[:language] || 'simple', :regconfig)
|
1302
1302
|
|
@@ -192,8 +192,13 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
192
192
|
deadline ||= time + @timeout
|
193
193
|
current_time = Time.now
|
194
194
|
raise(::Sequel::PoolTimeout, "timeout: #{@timeout}, elapsed: #{current_time - time}") if current_time > deadline
|
195
|
+
# :nocov:
|
196
|
+
# It's difficult to get to this point, it can only happen if there is a race condition
|
197
|
+
# where a connection cannot be acquired even after the thread is signalled by the condition
|
198
|
+
# variable that a connection is ready.
|
195
199
|
@waiters[server].wait(@mutex, deadline - current_time)
|
196
200
|
Thread.pass
|
201
|
+
# :nocov:
|
197
202
|
end
|
198
203
|
|
199
204
|
conn
|
@@ -4,7 +4,9 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
4
4
|
# Whether or not a ConditionVariable should be used to wait for connections.
|
5
5
|
# True except on ruby 1.8, where ConditionVariable#wait does not support a
|
6
6
|
# timeout.
|
7
|
-
USE_WAITER
|
7
|
+
unless defined?(USE_WAITER)
|
8
|
+
USE_WAITER = RUBY_VERSION >= '1.9'
|
9
|
+
end
|
8
10
|
|
9
11
|
# The maximum number of connections this pool will create (per shard/server
|
10
12
|
# if sharding).
|
@@ -40,7 +42,9 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
40
42
|
if USE_WAITER
|
41
43
|
@waiter = ConditionVariable.new
|
42
44
|
else
|
45
|
+
# :nocov:
|
43
46
|
@sleep_time = Float(opts[:pool_sleep_time] || 0.001)
|
47
|
+
# :nocov:
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
@@ -155,8 +159,12 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
155
159
|
deadline ||= time + @timeout
|
156
160
|
current_time = Time.now
|
157
161
|
raise(::Sequel::PoolTimeout, "timeout: #{@timeout}, elapsed: #{current_time - time}") if current_time > deadline
|
162
|
+
# :nocov:
|
163
|
+
# It's difficult to get to this point, it can only happen if there is a race condition
|
164
|
+
# where a connection cannot be acquired even after the thread is signalled by the condition
|
158
165
|
@waiter.wait(@mutex, deadline - current_time)
|
159
166
|
Thread.pass
|
167
|
+
# :nocov:
|
160
168
|
end
|
161
169
|
|
162
170
|
conn
|
@@ -6,7 +6,7 @@ module Sequel
|
|
6
6
|
# ---------------------
|
7
7
|
|
8
8
|
# Array of supported database adapters
|
9
|
-
ADAPTERS = %w'ado amalgalite cubrid db2 dbi do
|
9
|
+
ADAPTERS = %w'ado amalgalite cubrid db2 dbi do firebird ibmdb informix jdbc mock mysql mysql2 odbc oracle postgres sqlanywhere sqlite swift tinytds'.collect(&:to_sym)
|
10
10
|
|
11
11
|
@single_threaded = false
|
12
12
|
|
@@ -124,7 +124,7 @@ module Sequel
|
|
124
124
|
begin_transaction(conn, opts)
|
125
125
|
if rollback == :always
|
126
126
|
begin
|
127
|
-
yield(conn)
|
127
|
+
ret = yield(conn)
|
128
128
|
rescue Exception => e1
|
129
129
|
raise e1
|
130
130
|
ensure
|
@@ -139,6 +139,7 @@ module Sequel
|
|
139
139
|
rescue Exception
|
140
140
|
end
|
141
141
|
transaction_error(e, :conn=>conn, :rollback=>rollback)
|
142
|
+
ret
|
142
143
|
ensure
|
143
144
|
begin
|
144
145
|
committed = commit_or_rollback_transaction(e, conn, opts)
|
@@ -224,6 +224,16 @@ module Sequel
|
|
224
224
|
end
|
225
225
|
end
|
226
226
|
|
227
|
+
# Modify the default create_table generator to include
|
228
|
+
# the constraint validation methods.
|
229
|
+
def create_table_generator(&block)
|
230
|
+
super do
|
231
|
+
extend CreateTableGeneratorMethods
|
232
|
+
@validations = []
|
233
|
+
instance_eval(&block) if block
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
227
237
|
# Drop the constraint validations table.
|
228
238
|
def drop_constraint_validations_table
|
229
239
|
drop_table(constraint_validations_table)
|
@@ -262,8 +272,6 @@ module Sequel
|
|
262
272
|
ds.delete
|
263
273
|
end
|
264
274
|
|
265
|
-
private
|
266
|
-
|
267
275
|
# Modify the default alter_table generator to include
|
268
276
|
# the constraint validation methods.
|
269
277
|
def alter_table_generator(&block)
|
@@ -274,6 +282,8 @@ module Sequel
|
|
274
282
|
end
|
275
283
|
end
|
276
284
|
|
285
|
+
private
|
286
|
+
|
277
287
|
# After running all of the table alteration statements,
|
278
288
|
# if there were any constraint validations, run table alteration
|
279
289
|
# statements to create related constraints. This is purposely
|
@@ -317,16 +327,6 @@ module Sequel
|
|
317
327
|
super
|
318
328
|
end
|
319
329
|
|
320
|
-
# Modify the default create_table generator to include
|
321
|
-
# the constraint validation methods.
|
322
|
-
def create_table_generator(&block)
|
323
|
-
super do
|
324
|
-
extend CreateTableGeneratorMethods
|
325
|
-
@validations = []
|
326
|
-
instance_eval(&block) if block
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
330
|
# For the given table, generator, and validations, add constraints
|
331
331
|
# to the generator for each of the validations, as well as adding
|
332
332
|
# validation metadata to the constraint validations table.
|
@@ -123,10 +123,6 @@ module Sequel
|
|
123
123
|
expr = Sequel.+(expr, Sequel.lit(["", " "], value, sql_unit))
|
124
124
|
end
|
125
125
|
false
|
126
|
-
when :fdbsql
|
127
|
-
each_valid_interval_unit(h, FDBSQL_DURATION_UNITS) do |value, sql_unit|
|
128
|
-
expr = Sequel.+(expr, Sequel.lit(["INTERVAL ", " "], value, sql_unit))
|
129
|
-
end
|
130
126
|
else
|
131
127
|
raise Error, "date arithmetic is not implemented on #{db.database_type}"
|
132
128
|
end
|
@@ -1,6 +1,18 @@
|
|
1
1
|
# The pagination extension adds the Sequel::Dataset#paginate and #each_page methods,
|
2
|
-
# which return paginated (limited and offset) datasets with
|
3
|
-
# that make creating a paginated display easier
|
2
|
+
# which return paginated (limited and offset) datasets with the following methods
|
3
|
+
# added that make creating a paginated display easier:
|
4
|
+
#
|
5
|
+
# * +page_size+
|
6
|
+
# * +page_count+
|
7
|
+
# * +page_range+
|
8
|
+
# * +current_page+
|
9
|
+
# * +next_page+
|
10
|
+
# * +prev_page+
|
11
|
+
# * +first_page?+
|
12
|
+
# * +last_page?+
|
13
|
+
# * +pagination_record_count+
|
14
|
+
# * +current_page_record_count+
|
15
|
+
# * +current_page_record_range+
|
4
16
|
#
|
5
17
|
# This extension uses Object#extend at runtime, which can hurt performance.
|
6
18
|
#
|
@@ -18,7 +18,7 @@
|
|
18
18
|
# Just like any user-created type, after creating the type, you
|
19
19
|
# can create tables that have a column of that type:
|
20
20
|
#
|
21
|
-
# DB.create_table(:table_name)
|
21
|
+
# DB.create_table(:table_name) do
|
22
22
|
# enum_type_name :column_name
|
23
23
|
# end
|
24
24
|
#
|
@@ -31,7 +31,7 @@
|
|
31
31
|
# If the pg_array extension is used, arrays of enums are returned as a
|
32
32
|
# PGArray:
|
33
33
|
#
|
34
|
-
# DB.create_table(:table_name)
|
34
|
+
# DB.create_table(:table_name) do
|
35
35
|
# column :column_name, 'enum_type_name[]'
|
36
36
|
# end
|
37
37
|
# DB[:table_name].get(:column_name)
|
@@ -8,7 +8,7 @@
|
|
8
8
|
# as instances of Sequel::Postgres::HStore. HStore is
|
9
9
|
# a DelegateClass of Hash, so it mostly acts like a hash, but not
|
10
10
|
# completely (is_a?(Hash) is false). If you want the actual hash,
|
11
|
-
# you can call
|
11
|
+
# you can call HStore#to_hash. This is done so that Sequel does not
|
12
12
|
# treat a HStore like a Hash by default, which would cause issues.
|
13
13
|
#
|
14
14
|
# In addition to the parsers, this extension comes with literalizers
|
@@ -210,9 +210,9 @@ module Sequel
|
|
210
210
|
private
|
211
211
|
|
212
212
|
# Return a placeholder literal with the given str and args, wrapped
|
213
|
-
# in an JSONOp, used by operators that return json.
|
213
|
+
# in an JSONOp or JSONBOp, used by operators that return json or jsonb.
|
214
214
|
def json_op(str, args)
|
215
|
-
|
215
|
+
self.class.new(Sequel::SQL::PlaceholderLiteralString.new(str, [self, args]))
|
216
216
|
end
|
217
217
|
|
218
218
|
# Return a function with the given name, and the receiver as the first
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Sequel
|
2
|
+
module Plugins
|
3
|
+
# The delay_add_association plugin delays the adding of
|
4
|
+
# associated objects to a new (unsaved) object until after the new
|
5
|
+
# object is saved. By default, if you attempt to add
|
6
|
+
# associated objects to a new object, Sequel will raise
|
7
|
+
# an error, because you need to have a primary key before
|
8
|
+
# saving the objects.
|
9
|
+
#
|
10
|
+
# When delaying the add of an associated object, the object
|
11
|
+
# will be immediately added to the cached association array.
|
12
|
+
# When saving the current object, it will also attempt to
|
13
|
+
# validate any associated objects, and if the associated objects
|
14
|
+
# are not valid, the current object will also be considered
|
15
|
+
# not valid.
|
16
|
+
#
|
17
|
+
# Usage:
|
18
|
+
#
|
19
|
+
# # Make all model subclass delay add_association for new objects
|
20
|
+
# Sequel::Model.plugin :delay_add_association
|
21
|
+
#
|
22
|
+
# # Make the Album class delay add_association for new objects
|
23
|
+
# Album.plugin :delay_add_association
|
24
|
+
module DelayAddAssociation
|
25
|
+
# Depend on the validate_associated plugin.
|
26
|
+
def self.apply(mod)
|
27
|
+
mod.plugin :validate_associated
|
28
|
+
end
|
29
|
+
|
30
|
+
module InstanceMethods
|
31
|
+
private
|
32
|
+
|
33
|
+
# Delay the addition of the associated object till after
|
34
|
+
# saving the current object, if the current object is new
|
35
|
+
# and the associated dataset requires a primary key on the
|
36
|
+
# current object.
|
37
|
+
def add_associated_object(opts, o, *args)
|
38
|
+
if opts.dataset_need_primary_key? && new?
|
39
|
+
delay_validate_associated_object(opts, o)
|
40
|
+
send(opts[:name]) << o
|
41
|
+
after_create_hook{super(opts, o, *args)}
|
42
|
+
o
|
43
|
+
else
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/sequel/plugins/list.rb
CHANGED
@@ -129,11 +129,11 @@ module Sequel
|
|
129
129
|
checked_transaction do
|
130
130
|
ds = list_dataset
|
131
131
|
op, ds = if target < current
|
132
|
-
|
132
|
+
target = 1 if target < 1
|
133
133
|
[:+, ds.filter(position_field=>target...current)]
|
134
134
|
else
|
135
135
|
lp ||= last_position
|
136
|
-
|
136
|
+
target = lp if target > lp
|
137
137
|
[:-, ds.filter(position_field=>(current + 1)..target)]
|
138
138
|
end
|
139
139
|
ds.update(position_field => Sequel::SQL::NumericExpression.new(op, position_field, 1))
|
@@ -37,14 +37,16 @@ module Sequel
|
|
37
37
|
# of creating a new album.
|
38
38
|
#
|
39
39
|
# If you would like to delete the associated object instead of updating it, you add a _delete
|
40
|
-
# entry to the hash:
|
40
|
+
# entry to the hash, and also pass the :destroy option when calling +nested_attributes+:
|
41
41
|
#
|
42
|
+
# Artist.nested_attributes :albums, :destroy=>true
|
42
43
|
# a.update(:albums_attributes => [{:id=>1, :_delete=>true}])
|
43
44
|
#
|
44
45
|
# This will delete the related associated object from the database. If you want to leave the
|
45
46
|
# associated object in the database, but just remove it from the association, add a _remove
|
46
|
-
# entry in the hash:
|
47
|
+
# entry in the hash, and also pass the :remove option when calling +nested_attributes+:
|
47
48
|
#
|
49
|
+
# Artist.nested_attributes :albums, :remove=>true
|
48
50
|
# a.update(:albums_attributes => [{:id=>1, :_remove=>true}])
|
49
51
|
#
|
50
52
|
# The above example was for a one_to_many association, but the plugin also works similarly
|
@@ -71,9 +73,9 @@ module Sequel
|
|
71
73
|
# To save changes to the artist, create the first album and associate it to the artist,
|
72
74
|
# and update the other existing associated album.
|
73
75
|
module NestedAttributes
|
74
|
-
# Depend on the
|
76
|
+
# Depend on the validate_associated plugin.
|
75
77
|
def self.apply(model)
|
76
|
-
model.plugin(:
|
78
|
+
model.plugin(:validate_associated)
|
77
79
|
end
|
78
80
|
|
79
81
|
module ClassMethods
|
@@ -166,7 +168,7 @@ module Sequel
|
|
166
168
|
reflection = meta[:reflection]
|
167
169
|
obj = reflection.associated_class.new
|
168
170
|
nested_attributes_set_attributes(meta, obj, attributes)
|
169
|
-
|
171
|
+
delay_validate_associated_object(reflection, obj)
|
170
172
|
if reflection.returns_array?
|
171
173
|
send(reflection[:name]) << obj
|
172
174
|
after_save_hook{send(reflection.add_method, obj)}
|
@@ -282,7 +284,7 @@ module Sequel
|
|
282
284
|
# Returns the object updated.
|
283
285
|
def nested_attributes_update(meta, obj, attributes)
|
284
286
|
nested_attributes_update_attributes(meta, obj, attributes)
|
285
|
-
|
287
|
+
delay_validate_associated_object(meta[:reflection], obj)
|
286
288
|
# Don't need to validate the object twice if :validate association option is not false
|
287
289
|
# and don't want to validate it at all if it is false.
|
288
290
|
after_save_hook{obj.save_changes(:validate=>false)}
|
@@ -295,28 +297,6 @@ module Sequel
|
|
295
297
|
nested_attributes_set_attributes(meta, obj, attributes)
|
296
298
|
end
|
297
299
|
end
|
298
|
-
|
299
|
-
# Validate the given associated object, adding any validation error messages from the
|
300
|
-
# given object to the parent object.
|
301
|
-
def validate_associated_object(meta, obj)
|
302
|
-
reflection = meta[:reflection]
|
303
|
-
return if reflection[:validate] == false
|
304
|
-
association = reflection[:name]
|
305
|
-
if (reflection[:type] == :one_to_many || reflection[:type] == :one_to_one) && (key = reflection[:key]).is_a?(Symbol) && !(pk_val = obj.values[key])
|
306
|
-
# There could be a presence validation on the foreign key in the associated model,
|
307
|
-
# which will fail if we validate before saving the current object. If there is
|
308
|
-
# no value for the foreign key, set it to the current primary key value, or a dummy
|
309
|
-
# value of 0 if we haven't saved the current object.
|
310
|
-
p_key = pk unless pk.is_a?(Array)
|
311
|
-
obj.values[key] = p_key || 0
|
312
|
-
key = nil if p_key
|
313
|
-
end
|
314
|
-
obj.errors.full_messages.each{|m| errors.add(association, m)} unless obj.valid?
|
315
|
-
if key && !pk_val
|
316
|
-
# If we used a dummy value of 0, remove it so it doesn't accidently remain.
|
317
|
-
obj.values.delete(key)
|
318
|
-
end
|
319
|
-
end
|
320
300
|
end
|
321
301
|
end
|
322
302
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Sequel
|
2
|
+
module Plugins
|
3
|
+
# The update_refresh plugin makes the model class refresh
|
4
|
+
# the object after updating. By default, Sequel only
|
5
|
+
# refreshes automatically after inserting new rows, not
|
6
|
+
# after updating. However, if you are using triggers
|
7
|
+
# to modify the contents of updated rows, it can be
|
8
|
+
# helpful to immediately get the current data after
|
9
|
+
# updating.
|
10
|
+
#
|
11
|
+
# If the dataset supports UPDATE RETURNING, this
|
12
|
+
# plugin will use it so that it can retrieve the current
|
13
|
+
# data in the same query it uses for the update.
|
14
|
+
#
|
15
|
+
# Usage:
|
16
|
+
#
|
17
|
+
# # Make all model subclasses refresh after update
|
18
|
+
# Sequel::Model.plugin :update_refresh
|
19
|
+
#
|
20
|
+
# # Make the Album class refresh after update
|
21
|
+
# Album.plugin :update_refresh
|
22
|
+
module UpdateRefresh
|
23
|
+
module InstanceMethods
|
24
|
+
def after_update
|
25
|
+
super
|
26
|
+
unless this.supports_returning?(:update)
|
27
|
+
refresh
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def _update_without_checking(columns)
|
34
|
+
ds = _update_dataset
|
35
|
+
if ds.supports_returning?(:update)
|
36
|
+
ds = ds.opts[:returning] ? ds : ds.returning
|
37
|
+
rows = ds.update(columns)
|
38
|
+
n = rows.length
|
39
|
+
if n == 1
|
40
|
+
@values.merge!(rows.first)
|
41
|
+
end
|
42
|
+
n
|
43
|
+
else
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|