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