sequel 5.33.0 → 5.58.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 +318 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +40 -9
- data/doc/association_basics.rdoc +77 -13
- data/doc/cheat_sheet.rdoc +13 -5
- data/doc/code_order.rdoc +0 -12
- data/doc/dataset_filtering.rdoc +2 -2
- data/doc/fork_safety.rdoc +84 -0
- data/doc/migration.rdoc +12 -6
- data/doc/model_plugins.rdoc +1 -1
- data/doc/opening_databases.rdoc +15 -3
- data/doc/postgresql.rdoc +9 -1
- data/doc/querying.rdoc +7 -5
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/doc/release_notes/5.36.0.txt +60 -0
- data/doc/release_notes/5.37.0.txt +30 -0
- data/doc/release_notes/5.38.0.txt +28 -0
- data/doc/release_notes/5.39.0.txt +19 -0
- data/doc/release_notes/5.40.0.txt +40 -0
- data/doc/release_notes/5.41.0.txt +25 -0
- data/doc/release_notes/5.42.0.txt +136 -0
- data/doc/release_notes/5.43.0.txt +98 -0
- data/doc/release_notes/5.44.0.txt +32 -0
- data/doc/release_notes/5.45.0.txt +34 -0
- data/doc/release_notes/5.46.0.txt +87 -0
- data/doc/release_notes/5.47.0.txt +59 -0
- data/doc/release_notes/5.48.0.txt +14 -0
- data/doc/release_notes/5.49.0.txt +59 -0
- data/doc/release_notes/5.50.0.txt +78 -0
- data/doc/release_notes/5.51.0.txt +47 -0
- data/doc/release_notes/5.52.0.txt +87 -0
- data/doc/release_notes/5.53.0.txt +23 -0
- data/doc/release_notes/5.54.0.txt +27 -0
- data/doc/release_notes/5.55.0.txt +21 -0
- data/doc/release_notes/5.56.0.txt +51 -0
- data/doc/release_notes/5.57.0.txt +23 -0
- data/doc/release_notes/5.58.0.txt +31 -0
- data/doc/sql.rdoc +14 -2
- data/doc/testing.rdoc +10 -1
- data/doc/transactions.rdoc +0 -8
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/ado/access.rb +1 -1
- data/lib/sequel/adapters/ado.rb +17 -17
- data/lib/sequel/adapters/amalgalite.rb +3 -5
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc/derby.rb +8 -0
- data/lib/sequel/adapters/jdbc/h2.rb +60 -10
- data/lib/sequel/adapters/jdbc/hsqldb.rb +6 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +4 -4
- data/lib/sequel/adapters/jdbc/postgresql.rb +4 -4
- data/lib/sequel/adapters/jdbc.rb +29 -19
- data/lib/sequel/adapters/mysql.rb +80 -67
- data/lib/sequel/adapters/mysql2.rb +54 -49
- data/lib/sequel/adapters/odbc.rb +8 -6
- data/lib/sequel/adapters/oracle.rb +5 -4
- data/lib/sequel/adapters/postgres.rb +27 -29
- data/lib/sequel/adapters/shared/access.rb +2 -0
- data/lib/sequel/adapters/shared/db2.rb +30 -0
- data/lib/sequel/adapters/shared/mssql.rb +84 -7
- data/lib/sequel/adapters/shared/mysql.rb +33 -2
- data/lib/sequel/adapters/shared/oracle.rb +82 -7
- data/lib/sequel/adapters/shared/postgres.rb +158 -20
- data/lib/sequel/adapters/shared/sqlanywhere.rb +3 -0
- data/lib/sequel/adapters/shared/sqlite.rb +102 -10
- data/lib/sequel/adapters/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +60 -18
- data/lib/sequel/adapters/tinytds.rb +2 -1
- data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -1
- data/lib/sequel/ast_transformer.rb +6 -0
- data/lib/sequel/connection_pool/sharded_single.rb +9 -8
- data/lib/sequel/connection_pool/sharded_threaded.rb +10 -10
- data/lib/sequel/connection_pool/single.rb +7 -9
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/core.rb +33 -24
- data/lib/sequel/database/connecting.rb +3 -4
- data/lib/sequel/database/misc.rb +37 -12
- data/lib/sequel/database/query.rb +3 -1
- data/lib/sequel/database/schema_generator.rb +50 -53
- data/lib/sequel/database/schema_methods.rb +45 -23
- data/lib/sequel/database/transactions.rb +9 -6
- data/lib/sequel/dataset/actions.rb +61 -8
- data/lib/sequel/dataset/features.rb +15 -0
- data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
- data/lib/sequel/dataset/prepared_statements.rb +2 -0
- data/lib/sequel/dataset/query.rb +114 -11
- data/lib/sequel/dataset/sql.rb +172 -46
- data/lib/sequel/deprecated.rb +3 -1
- data/lib/sequel/exceptions.rb +2 -0
- data/lib/sequel/extensions/_pretty_table.rb +1 -2
- data/lib/sequel/extensions/any_not_empty.rb +1 -1
- data/lib/sequel/extensions/async_thread_pool.rb +438 -0
- data/lib/sequel/extensions/blank.rb +8 -0
- data/lib/sequel/extensions/columns_introspection.rb +1 -2
- data/lib/sequel/extensions/core_refinements.rb +38 -11
- data/lib/sequel/extensions/date_arithmetic.rb +36 -24
- data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
- data/lib/sequel/extensions/datetime_parse_to_time.rb +5 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -1
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/inflector.rb +9 -1
- data/lib/sequel/extensions/is_distinct_from.rb +139 -0
- data/lib/sequel/extensions/migration.rb +13 -2
- data/lib/sequel/extensions/named_timezones.rb +5 -1
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +1 -0
- data/lib/sequel/extensions/pg_array_ops.rb +6 -2
- data/lib/sequel/extensions/pg_enum.rb +3 -1
- data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +55 -3
- data/lib/sequel/extensions/pg_inet.rb +2 -0
- data/lib/sequel/extensions/pg_inet_ops.rb +1 -1
- data/lib/sequel/extensions/pg_interval.rb +35 -8
- data/lib/sequel/extensions/pg_json.rb +3 -5
- data/lib/sequel/extensions/pg_json_ops.rb +119 -4
- data/lib/sequel/extensions/pg_loose_count.rb +3 -1
- data/lib/sequel/extensions/pg_multirange.rb +372 -0
- data/lib/sequel/extensions/pg_range.rb +7 -19
- data/lib/sequel/extensions/pg_range_ops.rb +39 -9
- data/lib/sequel/extensions/pg_row.rb +1 -1
- data/lib/sequel/extensions/pg_row_ops.rb +25 -1
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/run_transaction_hooks.rb +1 -1
- data/lib/sequel/extensions/s.rb +4 -1
- data/lib/sequel/extensions/schema_dumper.rb +16 -5
- data/lib/sequel/extensions/server_block.rb +8 -12
- data/lib/sequel/extensions/sql_comments.rb +110 -3
- data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
- data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
- data/lib/sequel/extensions/string_agg.rb +1 -1
- data/lib/sequel/extensions/string_date_time.rb +19 -23
- data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +9 -3
- data/lib/sequel/model/associations.rb +342 -114
- data/lib/sequel/model/base.rb +45 -24
- data/lib/sequel/model/errors.rb +10 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model/plugins.rb +8 -3
- data/lib/sequel/model.rb +3 -1
- data/lib/sequel/plugins/association_pks.rb +60 -18
- data/lib/sequel/plugins/association_proxies.rb +3 -0
- data/lib/sequel/plugins/async_thread_pool.rb +39 -0
- data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
- data/lib/sequel/plugins/auto_validations.rb +39 -5
- data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +3 -8
- data/lib/sequel/plugins/column_encryption.rb +728 -0
- data/lib/sequel/plugins/composition.rb +8 -2
- data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
- data/lib/sequel/plugins/constraint_validations.rb +2 -1
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/dataset_associations.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +44 -0
- data/lib/sequel/plugins/enum.rb +124 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +2 -0
- data/lib/sequel/plugins/insert_conflict.rb +4 -0
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/json_serializer.rb +39 -24
- data/lib/sequel/plugins/lazy_attributes.rb +4 -1
- data/lib/sequel/plugins/many_through_many.rb +108 -9
- data/lib/sequel/plugins/nested_attributes.rb +8 -3
- data/lib/sequel/plugins/pg_array_associations.rb +58 -41
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +2 -0
- data/lib/sequel/plugins/prepared_statements.rb +15 -12
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
- data/lib/sequel/plugins/rcte_tree.rb +37 -35
- data/lib/sequel/plugins/serialization.rb +9 -3
- data/lib/sequel/plugins/serialization_modification_detection.rb +2 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +7 -0
- data/lib/sequel/plugins/sql_comments.rb +189 -0
- data/lib/sequel/plugins/static_cache.rb +1 -1
- data/lib/sequel/plugins/string_stripper.rb +1 -1
- data/lib/sequel/plugins/subclasses.rb +28 -11
- data/lib/sequel/plugins/tactical_eager_loading.rb +8 -2
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/tree.rb +9 -4
- data/lib/sequel/plugins/unused_associations.rb +521 -0
- data/lib/sequel/plugins/update_or_create.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -1
- data/lib/sequel/plugins/validation_helpers.rb +18 -11
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/timezones.rb +20 -17
- data/lib/sequel/version.rb +1 -1
- metadata +93 -39
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module Plugins
|
|
5
|
+
# The sql_comments plugin will automatically use SQL comments on
|
|
6
|
+
# queries for the model it is loaded into. These comments will
|
|
7
|
+
# show the related model, what type of method was called, and
|
|
8
|
+
# the method name (or association name for queries to load
|
|
9
|
+
# associations):
|
|
10
|
+
#
|
|
11
|
+
# album = Album[1]
|
|
12
|
+
# # SELECT * FROM albums WHERE (id = 1) LIMIT 1
|
|
13
|
+
# # -- model:Album,method_type:class,method:[]
|
|
14
|
+
#
|
|
15
|
+
# album.update(:name=>'A')
|
|
16
|
+
# # UPDATE albums SET name = 'baz' WHERE (id = 1)
|
|
17
|
+
# # -- model:Album,method_type:instance,method:update
|
|
18
|
+
#
|
|
19
|
+
# album.artist
|
|
20
|
+
# # SELECT * FROM artists WHERE (artists.id = 1)
|
|
21
|
+
# # -- model:Album,method_type:association_load,association:artist
|
|
22
|
+
#
|
|
23
|
+
# Album.eager(:artists).all
|
|
24
|
+
# # SELECT * FROM albums
|
|
25
|
+
# # SELECT * FROM artists WHERE (artists.id IN (1))
|
|
26
|
+
# # -- model:Album,method_type:association_eager_load,association:artist
|
|
27
|
+
#
|
|
28
|
+
# Album.where(id: 1).delete
|
|
29
|
+
# # DELETE FROM albums WHERE (id = 1)
|
|
30
|
+
# # -- model:Album,method_type:dataset,method:delete
|
|
31
|
+
#
|
|
32
|
+
# This plugin automatically supports the class, instance, and dataset
|
|
33
|
+
# methods are are supported by default in Sequel::Model. To support
|
|
34
|
+
# custom class, instance, and dataset methods, such as those added by
|
|
35
|
+
# other plugins, you can use the appropriate <tt>sql_comments_*_methods</tt>
|
|
36
|
+
# class method:
|
|
37
|
+
#
|
|
38
|
+
# Album.sql_comments_class_methods :first_by_name # example from finder plugin, with :mod option
|
|
39
|
+
# Album.sql_comments_instance_methods :lazy_attribute_lookup # lazy_attributes plugin
|
|
40
|
+
# Album.sql_comments_dataset_methods :to_csv # csv_serializer plugin
|
|
41
|
+
#
|
|
42
|
+
# In order for the sql_comments plugin to work, the sql_comments
|
|
43
|
+
# Database extension must be loaded into the model's database.
|
|
44
|
+
#
|
|
45
|
+
# Note that in order to make sure SQL comments are included, some
|
|
46
|
+
# optimizations are disabled if this plugin is loaded.
|
|
47
|
+
#
|
|
48
|
+
# Usage:
|
|
49
|
+
#
|
|
50
|
+
# # Make all model subclasses support automatic SQL comments
|
|
51
|
+
# # (called before loading subclasses)
|
|
52
|
+
# Sequel::Model.plugin :sql_comments
|
|
53
|
+
#
|
|
54
|
+
# # Make the Album class support automatic SQL comments
|
|
55
|
+
# Album.plugin :sql_comments
|
|
56
|
+
module SqlComments
|
|
57
|
+
# Define a method +meth+ on the given module +mod+ that will use automatic
|
|
58
|
+
# SQL comments with the given model, method_type, and method.
|
|
59
|
+
def self.def_sql_commend_method(mod, model, method_type, meth)
|
|
60
|
+
mod.send(:define_method, meth) do |*a, &block|
|
|
61
|
+
model.db.with_comments(:model=>model, :method_type=>method_type, :method=>meth) do
|
|
62
|
+
super(*a, &block)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
# :nocov:
|
|
66
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
|
|
67
|
+
# :nocov:
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.configure(model)
|
|
71
|
+
model.send(:reset_fast_pk_lookup_sql)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
module ClassMethods
|
|
75
|
+
# Use automatic SQL comments for the given class methods.
|
|
76
|
+
def sql_comments_class_methods(*meths)
|
|
77
|
+
_sql_comments_methods(singleton_class, :class, meths)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Use automatic SQL comments for the given instance methods.
|
|
81
|
+
def sql_comments_instance_methods(*meths)
|
|
82
|
+
_sql_comments_methods(self, :instance, meths)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Use automatic SQL comments for the given dataset methods.
|
|
86
|
+
def sql_comments_dataset_methods(*meths)
|
|
87
|
+
unless @_sql_comments_dataset_module
|
|
88
|
+
dataset_module(@_sql_comments_dataset_module = Module.new)
|
|
89
|
+
end
|
|
90
|
+
_sql_comments_methods(@_sql_comments_dataset_module, :dataset, meths)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
[:[], :create, :find, :find_or_create, :with_pk, :with_pk!].each do |meth|
|
|
94
|
+
define_method(meth) do |*a, &block|
|
|
95
|
+
db.with_comments(:model=>self, :method_type=>:class, :method=>meth) do
|
|
96
|
+
super(*a, &block)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
# :nocov:
|
|
100
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
|
|
101
|
+
# :nocov:
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
# Don't optimize the fast PK lookups, as it uses static SQL that
|
|
107
|
+
# won't support the SQL comments.
|
|
108
|
+
def reset_fast_pk_lookup_sql
|
|
109
|
+
@fast_pk_lookup_sql = @fast_instance_delete_sql = nil
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Define automatic SQL comment methods in +mod+ for each method in +meths+,
|
|
113
|
+
# with the given +method_type+.
|
|
114
|
+
def _sql_comments_methods(mod, method_type, meths)
|
|
115
|
+
meths.each do |meth|
|
|
116
|
+
SqlComments.def_sql_commend_method(mod, self, method_type, meth)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
module InstanceMethods
|
|
122
|
+
[:delete, :destroy, :lock!, :refresh, :save, :save_changes, :update, :update_fields].each do |meth|
|
|
123
|
+
define_method(meth) do |*a, &block|
|
|
124
|
+
t = Sequel.current
|
|
125
|
+
return super(*a, &block) if (hash = Sequel.synchronize{db.comment_hashes[t]}) && hash[:model]
|
|
126
|
+
|
|
127
|
+
db.with_comments(:model=>model, :method_type=>:instance, :method=>meth) do
|
|
128
|
+
super(*a, &block)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
# :nocov:
|
|
132
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
|
|
133
|
+
# :nocov:
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
# Do not use a placeholder loader for associations.
|
|
139
|
+
def _associated_object_loader(opts, dynamic_opts)
|
|
140
|
+
nil
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Use SQL comments on normal association load queries, showing they are association loads.
|
|
144
|
+
def _load_associated_objects(opts, dynamic_opts=OPTS)
|
|
145
|
+
db.with_comments(:model=>model, :method_type=>:association_load, :association=>opts[:name]) do
|
|
146
|
+
super
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
module DatasetMethods
|
|
152
|
+
Dataset::ACTION_METHODS.each do |meth|
|
|
153
|
+
define_method(meth) do |*a, &block|
|
|
154
|
+
t = Sequel.current
|
|
155
|
+
return super(*a, &block) if (hash = Sequel.synchronize{db.comment_hashes[t]}) && hash[:model]
|
|
156
|
+
|
|
157
|
+
db.with_comments(:model=>model, :method_type=>:dataset, :method=>meth) do
|
|
158
|
+
super(*a, &block)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
# :nocov:
|
|
162
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, false)
|
|
163
|
+
# :nocov:
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
private
|
|
167
|
+
|
|
168
|
+
# Add the association name as part of the eager load data, so
|
|
169
|
+
# perform_eager_load has access to it.
|
|
170
|
+
def prepare_eager_load(a, reflections, eager_assoc)
|
|
171
|
+
res = super
|
|
172
|
+
|
|
173
|
+
reflections.each do |r|
|
|
174
|
+
res[r[:eager_loader]][:association] = r[:name]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
res
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Use SQL comments on eager load queries, showing they are eager loads.
|
|
181
|
+
def perform_eager_load(loader, eo)
|
|
182
|
+
db.with_comments(:model=>model, :method_type=>:association_eager_load, :method=>nil, :association=>eo[:association]) do
|
|
183
|
+
super
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
@@ -87,7 +87,7 @@ module Sequel
|
|
|
87
87
|
# array containing the number of instances specified (single integer
|
|
88
88
|
# argument).
|
|
89
89
|
def first(*args)
|
|
90
|
-
if
|
|
90
|
+
if defined?(yield) || args.length > 1 || (args.length == 1 && !args[0].is_a?(Integer))
|
|
91
91
|
super
|
|
92
92
|
else
|
|
93
93
|
@all.first(*args)
|
|
@@ -28,7 +28,7 @@ module Sequel
|
|
|
28
28
|
model.plugin(:input_transformer, :string_stripper){|v| (v.is_a?(String) && !v.is_a?(SQL::Blob)) ? v.strip : v}
|
|
29
29
|
end
|
|
30
30
|
def self.configure(model)
|
|
31
|
-
model.
|
|
31
|
+
model.send(:set_skipped_string_stripping_columns)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
module ClassMethods
|
|
@@ -5,7 +5,7 @@ module Sequel
|
|
|
5
5
|
# The subclasses plugin keeps track of all subclasses of the
|
|
6
6
|
# current model class. Direct subclasses are available via the
|
|
7
7
|
# subclasses method, and all descendent classes are available via the
|
|
8
|
-
#
|
|
8
|
+
# descendants method:
|
|
9
9
|
#
|
|
10
10
|
# c = Class.new(Sequel::Model)
|
|
11
11
|
# c.plugin :subclasses
|
|
@@ -16,7 +16,7 @@ module Sequel
|
|
|
16
16
|
# sc1.subclasses # [ssc1]
|
|
17
17
|
# sc2.subclasses # []
|
|
18
18
|
# ssc1.subclasses # []
|
|
19
|
-
# c.
|
|
19
|
+
# c.descendants # [sc1, ssc1, sc2]
|
|
20
20
|
#
|
|
21
21
|
# You can also finalize the associations and then freeze the classes
|
|
22
22
|
# in all descendent classes. Doing so is a recommended practice after
|
|
@@ -35,9 +35,14 @@ module Sequel
|
|
|
35
35
|
# class B < Sequel::Model; end
|
|
36
36
|
# a # => [A, B]
|
|
37
37
|
module Subclasses
|
|
38
|
+
NEED_SUBCLASSES = !Object.respond_to?(:subclasses) || Object.method(:subclasses).source_location
|
|
39
|
+
private_constant :NEED_SUBCLASSES
|
|
40
|
+
|
|
38
41
|
# Initialize the subclasses instance variable for the model.
|
|
39
42
|
def self.apply(model, &block)
|
|
40
|
-
|
|
43
|
+
# :nocov:
|
|
44
|
+
model.instance_variable_set(:@subclasses, []) if NEED_SUBCLASSES
|
|
45
|
+
# :nocov:
|
|
41
46
|
model.instance_variable_set(:@on_subclass, block)
|
|
42
47
|
end
|
|
43
48
|
|
|
@@ -46,21 +51,31 @@ module Sequel
|
|
|
46
51
|
# class created.
|
|
47
52
|
attr_reader :on_subclass
|
|
48
53
|
|
|
49
|
-
#
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
# :nocov:
|
|
55
|
+
if NEED_SUBCLASSES
|
|
56
|
+
# All subclasses for the current model. Does not
|
|
57
|
+
# include the model itself.
|
|
58
|
+
attr_reader :subclasses
|
|
59
|
+
end
|
|
60
|
+
# :nocov:
|
|
52
61
|
|
|
53
62
|
# All descendent classes of this model.
|
|
54
|
-
def
|
|
55
|
-
Sequel.synchronize{subclasses.dup}.map{|x| [x] + x.send(:
|
|
63
|
+
def descendants
|
|
64
|
+
Sequel.synchronize{subclasses.dup}.map{|x| [x] + x.send(:descendants)}.flatten
|
|
56
65
|
end
|
|
57
66
|
|
|
67
|
+
# SEQUEL6: Remove
|
|
68
|
+
alias descendents descendants
|
|
69
|
+
|
|
58
70
|
# Freeze all descendent classes. This also finalizes the associations for those
|
|
59
71
|
# classes before freezing.
|
|
60
|
-
def
|
|
61
|
-
|
|
72
|
+
def freeze_descendants
|
|
73
|
+
descendants.each(&:finalize_associations).each(&:freeze)
|
|
62
74
|
end
|
|
63
75
|
|
|
76
|
+
# SEQUEL6: Remove
|
|
77
|
+
alias freeze_descendents freeze_descendants
|
|
78
|
+
|
|
64
79
|
Plugins.inherited_instance_variables(self, :@subclasses=>lambda{|v| []}, :@on_subclass=>nil)
|
|
65
80
|
|
|
66
81
|
private
|
|
@@ -70,7 +85,9 @@ module Sequel
|
|
|
70
85
|
# in the subclass.
|
|
71
86
|
def inherited(subclass)
|
|
72
87
|
super
|
|
73
|
-
|
|
88
|
+
# :nocov:
|
|
89
|
+
Sequel.synchronize{subclasses << subclass} if NEED_SUBCLASSES
|
|
90
|
+
# :nocov:
|
|
74
91
|
on_subclass.call(subclass) if on_subclass
|
|
75
92
|
end
|
|
76
93
|
end
|
|
@@ -143,9 +143,15 @@ module Sequel
|
|
|
143
143
|
def load_associated_objects(opts, dynamic_opts=OPTS, &block)
|
|
144
144
|
dynamic_opts = load_association_objects_options(dynamic_opts, &block)
|
|
145
145
|
name = opts[:name]
|
|
146
|
-
|
|
146
|
+
eager_reload = dynamic_opts[:eager_reload]
|
|
147
|
+
if (!associations.include?(name) || eager_reload) && opts[:allow_eager] != false && retrieved_by && !frozen? && !dynamic_opts[:callback] && !dynamic_opts[:reload]
|
|
147
148
|
begin
|
|
148
|
-
|
|
149
|
+
objects = if eager_reload
|
|
150
|
+
retrieved_with.reject(&:frozen?)
|
|
151
|
+
else
|
|
152
|
+
retrieved_with.reject{|x| x.frozen? || x.associations.include?(name)}
|
|
153
|
+
end
|
|
154
|
+
retrieved_by.send(:eager_load, objects, name=>dynamic_opts[:eager] || OPTS)
|
|
149
155
|
rescue Sequel::UndefinedAssociation
|
|
150
156
|
# This can happen if class table inheritance is used and the association
|
|
151
157
|
# is only defined in a subclass. This particular instance can use the
|
|
@@ -19,7 +19,7 @@ module Sequel
|
|
|
19
19
|
#
|
|
20
20
|
# # Timestamp Artist instances, forcing an overwrite of the create
|
|
21
21
|
# # timestamp, and setting the update timestamp when creating
|
|
22
|
-
#
|
|
22
|
+
# Artist.plugin :timestamps, force: true, update_on_create: true
|
|
23
23
|
module Timestamps
|
|
24
24
|
# Configure the plugin by setting the available options. Note that
|
|
25
25
|
# if this method is run more than once, previous settings are ignored,
|
data/lib/sequel/plugins/tree.rb
CHANGED
|
@@ -45,6 +45,7 @@ module Sequel
|
|
|
45
45
|
|
|
46
46
|
model.instance_exec do
|
|
47
47
|
@parent_column = opts[:key]
|
|
48
|
+
@qualified_parent_column = Sequel.deep_qualify(table_name, opts[:key])
|
|
48
49
|
@tree_order = opts[:order]
|
|
49
50
|
@parent_association_name = parent
|
|
50
51
|
@children_association_name = children
|
|
@@ -59,17 +60,21 @@ module Sequel
|
|
|
59
60
|
# The column symbol or array of column symbols on which to order the tree.
|
|
60
61
|
attr_accessor :tree_order
|
|
61
62
|
|
|
62
|
-
# The symbol for the column containing the value pointing to the
|
|
63
|
-
# parent of the
|
|
63
|
+
# The symbol or array of symbols for the column containing the value pointing to the
|
|
64
|
+
# parent of the node.
|
|
64
65
|
attr_accessor :parent_column
|
|
65
66
|
|
|
67
|
+
# The qualified identifier or array of qualified identifiers for the column
|
|
68
|
+
# containing the value pointing to the parent of the node.
|
|
69
|
+
attr_accessor :qualified_parent_column
|
|
70
|
+
|
|
66
71
|
# The association name for the parent association
|
|
67
72
|
attr_reader :parent_association_name
|
|
68
73
|
|
|
69
74
|
# The association name for the children association
|
|
70
75
|
attr_reader :children_association_name
|
|
71
76
|
|
|
72
|
-
Plugins.inherited_instance_variables(self, :@parent_column=>nil, :@tree_order=>nil, :@parent_association_name=>nil, :@children_association_name=>nil)
|
|
77
|
+
Plugins.inherited_instance_variables(self, :@parent_column=>nil, :@qualified_parent_column=>nil, :@tree_order=>nil, :@parent_association_name=>nil, :@children_association_name=>nil)
|
|
73
78
|
Plugins.def_dataset_methods(self, [:roots, :roots_dataset])
|
|
74
79
|
|
|
75
80
|
# Should freeze tree order if it is an array when freezing the model class.
|
|
@@ -151,7 +156,7 @@ module Sequel
|
|
|
151
156
|
#
|
|
152
157
|
# TreeClass.roots_dataset # => Sequel::Dataset instance
|
|
153
158
|
def roots_dataset
|
|
154
|
-
ds = where(Sequel.or(Array(model.
|
|
159
|
+
ds = where(Sequel.or(Array(model.qualified_parent_column).zip([])))
|
|
155
160
|
ds = ds.order(*model.tree_order) if model.tree_order
|
|
156
161
|
ds
|
|
157
162
|
end
|