torque-postgresql 1.1.1 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Rakefile +5 -2
- data/lib/torque/postgresql.rb +0 -2
- data/lib/torque/postgresql/adapter.rb +0 -1
- data/lib/torque/postgresql/adapter/database_statements.rb +4 -15
- data/lib/torque/postgresql/adapter/schema_creation.rb +13 -23
- data/lib/torque/postgresql/adapter/schema_definitions.rb +7 -21
- data/lib/torque/postgresql/adapter/schema_dumper.rb +71 -11
- data/lib/torque/postgresql/adapter/schema_statements.rb +2 -12
- data/lib/torque/postgresql/associations.rb +0 -3
- data/lib/torque/postgresql/associations/association_scope.rb +18 -61
- data/lib/torque/postgresql/associations/belongs_to_many_association.rb +2 -1
- data/lib/torque/postgresql/associations/preloader.rb +0 -24
- data/lib/torque/postgresql/associations/preloader/association.rb +13 -9
- data/lib/torque/postgresql/auxiliary_statement.rb +12 -17
- data/lib/torque/postgresql/coder.rb +1 -2
- data/lib/torque/postgresql/config.rb +0 -4
- data/lib/torque/postgresql/inheritance.rb +13 -17
- data/lib/torque/postgresql/reflection/abstract_reflection.rb +19 -25
- data/lib/torque/postgresql/relation.rb +11 -16
- data/lib/torque/postgresql/relation/auxiliary_statement.rb +9 -15
- data/lib/torque/postgresql/relation/distinct_on.rb +1 -1
- data/lib/torque/postgresql/schema_cache.rb +19 -11
- data/lib/torque/postgresql/version.rb +1 -1
- data/spec/en.yml +19 -0
- data/spec/factories/authors.rb +6 -0
- data/spec/factories/comments.rb +13 -0
- data/spec/factories/posts.rb +6 -0
- data/spec/factories/tags.rb +5 -0
- data/spec/factories/texts.rb +5 -0
- data/spec/factories/users.rb +6 -0
- data/spec/factories/videos.rb +5 -0
- data/spec/mocks/cache_query.rb +16 -0
- data/spec/mocks/create_table.rb +35 -0
- data/spec/models/activity.rb +3 -0
- data/spec/models/activity_book.rb +4 -0
- data/spec/models/activity_post.rb +7 -0
- data/spec/models/activity_post/sample.rb +4 -0
- data/spec/models/author.rb +4 -0
- data/spec/models/author_journalist.rb +4 -0
- data/spec/models/comment.rb +3 -0
- data/spec/models/course.rb +2 -0
- data/spec/models/geometry.rb +2 -0
- data/spec/models/guest_comment.rb +4 -0
- data/spec/models/post.rb +6 -0
- data/spec/models/tag.rb +2 -0
- data/spec/models/text.rb +2 -0
- data/spec/models/time_keeper.rb +2 -0
- data/spec/models/user.rb +8 -0
- data/spec/models/video.rb +2 -0
- data/spec/schema.rb +141 -0
- data/spec/spec_helper.rb +59 -0
- data/spec/tests/arel_spec.rb +72 -0
- data/spec/tests/auxiliary_statement_spec.rb +593 -0
- data/spec/tests/belongs_to_many_spec.rb +240 -0
- data/spec/tests/coder_spec.rb +367 -0
- data/spec/tests/collector_spec.rb +59 -0
- data/spec/tests/distinct_on_spec.rb +65 -0
- data/spec/tests/enum_set_spec.rb +306 -0
- data/spec/tests/enum_spec.rb +628 -0
- data/spec/tests/geometric_builder_spec.rb +221 -0
- data/spec/tests/has_many_spec.rb +390 -0
- data/spec/tests/interval_spec.rb +167 -0
- data/spec/tests/lazy_spec.rb +24 -0
- data/spec/tests/period_spec.rb +954 -0
- data/spec/tests/quoting_spec.rb +24 -0
- data/spec/tests/range_spec.rb +36 -0
- data/spec/tests/relation_spec.rb +57 -0
- data/spec/tests/table_inheritance_spec.rb +416 -0
- metadata +103 -16
- data/lib/torque/postgresql/associations/join_dependency/join_association.rb +0 -15
- data/lib/torque/postgresql/schema_dumper.rb +0 -88
@@ -33,7 +33,8 @@ module Torque
|
|
33
33
|
|
34
34
|
def ids_writer(new_ids)
|
35
35
|
column = reflection.active_record_primary_key
|
36
|
-
owner.update_column
|
36
|
+
command = owner.persisted? ? :update_column : :write_attribute
|
37
|
+
owner.public_send(command, column, new_ids.presence)
|
37
38
|
@association_scope = nil
|
38
39
|
end
|
39
40
|
|
@@ -1,25 +1 @@
|
|
1
1
|
require_relative 'preloader/association'
|
2
|
-
|
3
|
-
unless Torque::PostgreSQL::AR521
|
4
|
-
module Torque
|
5
|
-
module PostgreSQL
|
6
|
-
module Associations
|
7
|
-
module Preloader
|
8
|
-
BelongsToMany = Class.new(::ActiveRecord::Associations::Preloader::HasMany)
|
9
|
-
|
10
|
-
def preloader_for(reflection, owners, *)
|
11
|
-
return AlreadyLoaded \
|
12
|
-
if owners.first.association(reflection.name).loaded?
|
13
|
-
|
14
|
-
return BelongsToMany \
|
15
|
-
if reflection.macro.eql?(:belongs_to_many)
|
16
|
-
|
17
|
-
super
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
::ActiveRecord::Associations::Preloader.prepend(Preloader)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -8,7 +8,7 @@ module Torque
|
|
8
8
|
|
9
9
|
# For reflections connected through an array, make sure to properly
|
10
10
|
# decuple the list of ids and set them as associated with the owner
|
11
|
-
def run
|
11
|
+
def run
|
12
12
|
return super unless connected_through_array?
|
13
13
|
send("run_array_for_#{@reflection.macro}")
|
14
14
|
end
|
@@ -18,7 +18,7 @@ module Torque
|
|
18
18
|
# Specific run for belongs_many association
|
19
19
|
def run_array_for_belongs_to_many
|
20
20
|
# Add reverse to has_many
|
21
|
-
records =
|
21
|
+
records = groupped_records
|
22
22
|
owners.each do |owner|
|
23
23
|
items = records.values_at(*Array.wrap(owner[owner_key_name]))
|
24
24
|
associate_records_to_owner(owner, items.flatten)
|
@@ -29,7 +29,7 @@ module Torque
|
|
29
29
|
def run_array_for_has_many
|
30
30
|
# Add reverse to belongs_to_many
|
31
31
|
records = Hash.new { |h, k| h[k] = [] }
|
32
|
-
|
32
|
+
groupped_records.each do |ids, record|
|
33
33
|
ids.each { |id| records[id].concat(Array.wrap(record)) }
|
34
34
|
end
|
35
35
|
|
@@ -47,14 +47,18 @@ module Torque
|
|
47
47
|
scope.where(condition).load(&block)
|
48
48
|
end
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
50
|
+
def associate_records_to_owner(owner, records)
|
51
|
+
return super unless connected_through_array?
|
52
|
+
association = owner.association(reflection.name)
|
53
|
+
association.loaded!
|
54
|
+
association.target.concat(records)
|
56
55
|
end
|
57
56
|
|
57
|
+
def groupped_records
|
58
|
+
preloaded_records.group_by do |record|
|
59
|
+
convert_key(record[association_key_name])
|
60
|
+
end
|
61
|
+
end
|
58
62
|
end
|
59
63
|
|
60
64
|
::ActiveRecord::Associations::Preloader::Association.prepend(Association)
|
@@ -31,11 +31,12 @@ module Torque
|
|
31
31
|
end
|
32
32
|
|
33
33
|
# Fast access to statement build
|
34
|
-
def build(statement, base, options = nil, bound_attributes = [])
|
34
|
+
def build(statement, base, options = nil, bound_attributes = [], join_sources = [])
|
35
35
|
klass = instantiate(statement, base, options)
|
36
36
|
result = klass.build(base)
|
37
37
|
|
38
38
|
bound_attributes.concat(klass.bound_attributes)
|
39
|
+
join_sources.concat(klass.join_sources)
|
39
40
|
result
|
40
41
|
end
|
41
42
|
|
@@ -105,7 +106,7 @@ module Torque
|
|
105
106
|
delegate :config, :table, :table_name, :relation, :configure, :relation_query?,
|
106
107
|
to: :class
|
107
108
|
|
108
|
-
attr_reader :bound_attributes
|
109
|
+
attr_reader :bound_attributes, :join_sources
|
109
110
|
|
110
111
|
# Start a new auxiliary statement giving extra options
|
111
112
|
def initialize(*args)
|
@@ -117,15 +118,21 @@ module Torque
|
|
117
118
|
@where = options.fetch(:where, {})
|
118
119
|
@select = options.fetch(:select, {})
|
119
120
|
@join_type = options.fetch(:join_type, nil)
|
121
|
+
|
120
122
|
@bound_attributes = []
|
123
|
+
@join_sources = []
|
121
124
|
end
|
122
125
|
|
123
126
|
# Build the statement on the given arel and return the WITH statement
|
124
127
|
def build(base)
|
128
|
+
@bound_attributes.clear
|
129
|
+
@join_sources.clear
|
130
|
+
|
131
|
+
# Prepare all the data for the statement
|
125
132
|
prepare(base)
|
126
133
|
|
127
134
|
# Add the join condition to the list
|
128
|
-
|
135
|
+
@join_sources << build_join(base)
|
129
136
|
|
130
137
|
# Return the statement with its dependencies
|
131
138
|
[@dependencies, ::Arel::Nodes::As.new(table, build_query(base))]
|
@@ -204,19 +211,7 @@ module Torque
|
|
204
211
|
foreign_table = ::Arel::Table.new(association.plural_name)
|
205
212
|
end
|
206
213
|
|
207
|
-
|
208
|
-
# Possibilities:
|
209
|
-
# table
|
210
|
-
# table, foreign_klass
|
211
|
-
# table, foreign_table, foreign_klass
|
212
|
-
if association.respond_to?(:join_scope)
|
213
|
-
arity = association.method(:join_scope).arity
|
214
|
-
args = [@query.arel_table, foreign_table, base]
|
215
|
-
args.delete_at(1) if arity <= 2 # Delete foreign_table
|
216
|
-
args.delete_at(1) if arity <= 1 # Delete base (foreign_klass)
|
217
|
-
|
218
|
-
@query.merge(association.join_scope(*args))
|
219
|
-
end
|
214
|
+
@query.merge(association.join_scope(@query.arel_table, foreign_table, base))
|
220
215
|
|
221
216
|
# Add the join constraints
|
222
217
|
constraint = association.build_join_constraint(table, foreign_table)
|
@@ -288,7 +283,7 @@ module Torque
|
|
288
283
|
cte.is_a?(dependent_klass)
|
289
284
|
end
|
290
285
|
|
291
|
-
AuxiliaryStatement.build(dependent, base, options, bound_attributes)
|
286
|
+
AuxiliaryStatement.build(dependent, base, options, bound_attributes, join_sources)
|
292
287
|
end
|
293
288
|
end
|
294
289
|
|
@@ -2,10 +2,6 @@ module Torque
|
|
2
2
|
module PostgreSQL
|
3
3
|
include ActiveSupport::Configurable
|
4
4
|
|
5
|
-
# Stores a version check for compatibility purposes
|
6
|
-
AR521 = (ActiveRecord.gem_version >= Gem::Version.new('5.2.1'))
|
7
|
-
AR523 = (ActiveRecord.gem_version >= Gem::Version.new('5.2.3'))
|
8
|
-
|
9
5
|
# Use the same logger as the Active Record one
|
10
6
|
def self.logger
|
11
7
|
ActiveRecord::Base.logger
|
@@ -18,14 +18,7 @@ module Torque
|
|
18
18
|
klass.find(self.id)
|
19
19
|
end
|
20
20
|
|
21
|
-
private
|
22
|
-
|
23
|
-
def using_single_table_inheritance?(record) # :nodoc:
|
24
|
-
self.class.physically_inherited? || super
|
25
|
-
end
|
26
|
-
|
27
21
|
module ClassMethods
|
28
|
-
|
29
22
|
delegate :_auto_cast_attribute, :_record_class_attribute, to: ActiveRecord::Relation
|
30
23
|
|
31
24
|
# Get a full list of all attributes from a model and all its dependents
|
@@ -101,9 +94,10 @@ module Torque
|
|
101
94
|
|
102
95
|
# Get the final decorated table, regardless of any special condition
|
103
96
|
def decorated_table_name
|
104
|
-
|
105
|
-
|
106
|
-
contained =
|
97
|
+
parent_class = try(:module_parent) || try(:parent)
|
98
|
+
if parent_class < Base && !parent_class.abstract_class?
|
99
|
+
contained = parent_class.table_name
|
100
|
+
contained = contained.singularize if parent_class.pluralize_table_names
|
107
101
|
contained += "_"
|
108
102
|
end
|
109
103
|
|
@@ -144,17 +138,19 @@ module Torque
|
|
144
138
|
|
145
139
|
private
|
146
140
|
|
147
|
-
def
|
141
|
+
def instantiate_instance_of(klass, attributes, column_types = {}, &block)
|
142
|
+
return super unless klass.physically_inheritances?
|
143
|
+
|
148
144
|
auto_cast = _auto_cast_attribute.to_s
|
149
145
|
record_class = _record_class_attribute.to_s
|
146
|
+
return super unless attributes.key?(record_class) &&
|
147
|
+
attributes.delete(auto_cast) && attributes[record_class] != table_name
|
150
148
|
|
151
|
-
|
152
|
-
|
149
|
+
klass = casted_dependents[attributes[record_class]]
|
150
|
+
raise_unable_to_cast(attributes[record_class]) if klass.nil?
|
151
|
+
filter_attributes_for_cast(attributes, klass)
|
153
152
|
|
154
|
-
klass
|
155
|
-
raise_unable_to_cast(record[record_class]) if klass.nil?
|
156
|
-
filter_attributes_for_cast(record, klass)
|
157
|
-
klass
|
153
|
+
super(klass, attributes, column_types, &block)
|
158
154
|
end
|
159
155
|
|
160
156
|
# Filter the record attributes to be loaded to not included those from
|
@@ -12,28 +12,21 @@ module Torque
|
|
12
12
|
false
|
13
13
|
end
|
14
14
|
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
klass_scope = klass_join_scope(table, predicate_builder)
|
29
|
-
|
30
|
-
klass_scope.where!(build_id_constraint_between(table, foreign_table))
|
31
|
-
klass_scope.where!(type => foreign_klass.polymorphic_name) if type
|
32
|
-
klass_scope.where!(klass.send(:type_condition, table)) \
|
33
|
-
if klass.finder_needs_type_condition?
|
15
|
+
# Fix where the join_scope method is the one now responsible for
|
16
|
+
# building the join condition
|
17
|
+
def join_scope(table, foreign_table, foreign_klass)
|
18
|
+
return super unless connected_through_array?
|
19
|
+
|
20
|
+
predicate_builder = predicate_builder(table)
|
21
|
+
scope_chain_items = join_scopes(table, predicate_builder)
|
22
|
+
klass_scope = klass_join_scope(table, predicate_builder)
|
23
|
+
|
24
|
+
klass_scope.where!(build_id_constraint_between(table, foreign_table))
|
25
|
+
klass_scope.where!(type => foreign_klass.polymorphic_name) if type
|
26
|
+
klass_scope.where!(klass.send(:type_condition, table)) \
|
27
|
+
if klass.finder_needs_type_condition?
|
34
28
|
|
35
|
-
|
36
|
-
end
|
29
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
37
30
|
end
|
38
31
|
|
39
32
|
# Manually build the join constraint
|
@@ -50,9 +43,9 @@ module Torque
|
|
50
43
|
return klass_attr.eq(source_attr) unless connected_through_array?
|
51
44
|
|
52
45
|
# Klass and key are associated with the reflection Class
|
53
|
-
klass_type = klass.columns_hash[
|
46
|
+
klass_type = klass.columns_hash[join_keys.key.to_s]
|
54
47
|
# active_record and foreign_key are associated with the source Class
|
55
|
-
source_type = active_record.columns_hash[
|
48
|
+
source_type = active_record.columns_hash[join_keys.foreign_key.to_s]
|
56
49
|
|
57
50
|
# If both are attributes but the left side is not an array, and the
|
58
51
|
# right side is, use the ANY operation
|
@@ -78,8 +71,8 @@ module Torque
|
|
78
71
|
private
|
79
72
|
|
80
73
|
def build_id_constraint_between(table, foreign_table)
|
81
|
-
klass_attr = table[
|
82
|
-
source_attr = foreign_table[
|
74
|
+
klass_attr = table[join_keys.key.to_s]
|
75
|
+
source_attr = foreign_table[join_keys.foreign_key.to_s]
|
83
76
|
|
84
77
|
build_id_constraint(klass_attr, source_attr)
|
85
78
|
end
|
@@ -105,6 +98,7 @@ module Torque
|
|
105
98
|
# returns either +nil+ or the inverse association name that it finds.
|
106
99
|
def automatic_inverse_of
|
107
100
|
return super unless connected_through_array?
|
101
|
+
|
108
102
|
if can_find_inverse_of_automatically?(self)
|
109
103
|
inverse_name = options[:as] || active_record.name.demodulize
|
110
104
|
inverse_name = ActiveSupport::Inflector.underscore(inverse_name)
|
@@ -52,11 +52,8 @@ module Torque
|
|
52
52
|
when Array
|
53
53
|
resolve_column(item, base)
|
54
54
|
when Hash
|
55
|
-
raise ArgumentError,
|
56
|
-
item.map
|
57
|
-
other_list = [other_list] unless other_list.kind_of? Enumerable
|
58
|
-
resolve_column(other_list, key)
|
59
|
-
end
|
55
|
+
raise ArgumentError, 'Unsupported Hash for attributes on third level' if base
|
56
|
+
item.map { |key, other_list| resolve_column(Array.wrap(other_list), key) }
|
60
57
|
else
|
61
58
|
raise ArgumentError, "Unsupported argument type: #{value} (#{value.class})"
|
62
59
|
end
|
@@ -138,19 +135,17 @@ module Torque
|
|
138
135
|
ActiveRecord::Relation::SINGLE_VALUE_METHODS += Relation::SINGLE_VALUE_METHODS
|
139
136
|
ActiveRecord::Relation::MULTI_VALUE_METHODS += Relation::MULTI_VALUE_METHODS
|
140
137
|
ActiveRecord::Relation::VALUE_METHODS += Relation::VALUE_METHODS
|
141
|
-
ActiveRecord::QueryMethods::VALID_UNSCOPING_VALUES += [
|
142
|
-
|
138
|
+
ActiveRecord::QueryMethods::VALID_UNSCOPING_VALUES += %i[cast_records itself_only
|
139
|
+
distinct_on auxiliary_statements]
|
143
140
|
|
144
|
-
|
145
|
-
|
146
|
-
ActiveRecord::QueryMethods::DEFAULT_VALUES[value]
|
147
|
-
|
148
|
-
end
|
141
|
+
Relation::SINGLE_VALUE_METHODS.each do |value|
|
142
|
+
ActiveRecord::QueryMethods::DEFAULT_VALUES[value] = nil \
|
143
|
+
if ActiveRecord::QueryMethods::DEFAULT_VALUES[value].nil?
|
144
|
+
end
|
149
145
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
146
|
+
Relation::MULTI_VALUE_METHODS.each do |value|
|
147
|
+
ActiveRecord::QueryMethods::DEFAULT_VALUES[value] ||= \
|
148
|
+
ActiveRecord::QueryMethods::FROZEN_EMPTY_ARRAY
|
154
149
|
end
|
155
150
|
|
156
151
|
$VERBOSE = warn_level
|
@@ -33,30 +33,24 @@ module Torque
|
|
33
33
|
# Get all auxiliary statements bound attributes and the base bound
|
34
34
|
# attributes as well
|
35
35
|
def bound_attributes
|
36
|
-
|
37
|
-
|
38
|
-
visitor.accept(self.arel.ast, ::Arel::Collectors::Bind.new).value
|
39
|
-
else
|
40
|
-
return super unless self.auxiliary_statements_values.present?
|
41
|
-
bindings = self.auxiliary_statements_values.map(&:bound_attributes)
|
42
|
-
(bindings + super).flatten
|
43
|
-
end
|
36
|
+
visitor = ::Arel::Visitors::PostgreSQL.new(ActiveRecord::Base.connection)
|
37
|
+
visitor.accept(self.arel.ast, ::Arel::Collectors::Bind.new).value
|
44
38
|
end
|
45
39
|
|
46
40
|
private
|
47
41
|
|
48
42
|
# Hook arel build to add the distinct on clause
|
49
43
|
def build_arel(*)
|
50
|
-
|
51
|
-
|
52
|
-
|
44
|
+
arel = super
|
45
|
+
subqueries = build_auxiliary_statements(arel)
|
46
|
+
subqueries.nil? ? arel : arel.with(subqueries)
|
53
47
|
end
|
54
48
|
|
55
49
|
# Build all necessary data for auxiliary statements
|
56
|
-
def build_auxiliary_statements
|
57
|
-
return unless
|
58
|
-
|
59
|
-
klass.build(self)
|
50
|
+
def build_auxiliary_statements(arel)
|
51
|
+
return unless auxiliary_statements_values.present?
|
52
|
+
auxiliary_statements_values.map do |klass|
|
53
|
+
klass.build(self).tap { arel.join_sources.concat(klass.join_sources) }
|
60
54
|
end
|
61
55
|
end
|
62
56
|
|
@@ -33,7 +33,7 @@ module Torque
|
|
33
33
|
|
34
34
|
# Hook arel build to add the distinct on clause
|
35
35
|
def build_arel(*)
|
36
|
-
arel =
|
36
|
+
arel = super
|
37
37
|
value = self.distinct_on_values
|
38
38
|
arel.distinct_on(resolve_column(value)) if value.present?
|
39
39
|
arel
|
@@ -11,6 +11,7 @@ module Torque
|
|
11
11
|
@data_sources_model_names = {}
|
12
12
|
@inheritance_dependencies = {}
|
13
13
|
@inheritance_associations = {}
|
14
|
+
@inheritance_loaded = false
|
14
15
|
end
|
15
16
|
|
16
17
|
def initialize_dup(*) # :nodoc:
|
@@ -22,16 +23,16 @@ module Torque
|
|
22
23
|
|
23
24
|
def encode_with(coder) # :nodoc:
|
24
25
|
super
|
25
|
-
coder[
|
26
|
-
coder[
|
27
|
-
coder[
|
26
|
+
coder['data_sources_model_names'] = @data_sources_model_names
|
27
|
+
coder['inheritance_dependencies'] = @inheritance_dependencies
|
28
|
+
coder['inheritance_associations'] = @inheritance_associations
|
28
29
|
end
|
29
30
|
|
30
31
|
def init_with(coder) # :nodoc:
|
31
32
|
super
|
32
|
-
@data_sources_model_names = coder[
|
33
|
-
@inheritance_dependencies = coder[
|
34
|
-
@inheritance_associations = coder[
|
33
|
+
@data_sources_model_names = coder['data_sources_model_names']
|
34
|
+
@inheritance_dependencies = coder['inheritance_dependencies']
|
35
|
+
@inheritance_associations = coder['inheritance_associations']
|
35
36
|
end
|
36
37
|
|
37
38
|
def add(table_name, *) # :nodoc:
|
@@ -41,6 +42,7 @@ module Torque
|
|
41
42
|
if @data_sources.key?(table_name)
|
42
43
|
@inheritance_dependencies.clear
|
43
44
|
@inheritance_associations.clear
|
45
|
+
@inheritance_loaded = false
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
@@ -49,6 +51,7 @@ module Torque
|
|
49
51
|
@data_sources_model_names.clear
|
50
52
|
@inheritance_dependencies.clear
|
51
53
|
@inheritance_associations.clear
|
54
|
+
@inheritance_loaded = false
|
52
55
|
end
|
53
56
|
|
54
57
|
def size # :nodoc:
|
@@ -71,10 +74,12 @@ module Torque
|
|
71
74
|
@inheritance_dependencies,
|
72
75
|
@inheritance_associations,
|
73
76
|
@data_sources_model_names,
|
77
|
+
@inheritance_loaded,
|
74
78
|
]
|
75
79
|
end
|
76
80
|
|
77
81
|
def marshal_load(array) # :nodoc:
|
82
|
+
@inheritance_loaded = array.pop
|
78
83
|
@data_sources_model_names = array.pop
|
79
84
|
@inheritance_associations = array.pop
|
80
85
|
@inheritance_dependencies = array.pop
|
@@ -101,13 +106,13 @@ module Torque
|
|
101
106
|
end
|
102
107
|
|
103
108
|
# Try to find a model based on a given table
|
104
|
-
def lookup_model(table_name,
|
105
|
-
|
109
|
+
def lookup_model(table_name, scoped_class = '')
|
110
|
+
scoped_class = scoped_class.name if scoped_class.is_a?(Class)
|
106
111
|
return @data_sources_model_names[table_name] \
|
107
112
|
if @data_sources_model_names.key?(table_name)
|
108
113
|
|
109
114
|
# Get all the possible scopes
|
110
|
-
scopes =
|
115
|
+
scopes = scoped_class.scan(/(?:::)?[A-Z][a-z]+/)
|
111
116
|
scopes.unshift('Object::')
|
112
117
|
|
113
118
|
# Consider the maximum namespaced possible model name
|
@@ -164,14 +169,17 @@ module Torque
|
|
164
169
|
# Reload information about tables inheritance and dependencies, uses a
|
165
170
|
# cache to not perform additional checkes
|
166
171
|
def reload_inheritance_data!
|
167
|
-
return if @
|
172
|
+
return if @inheritance_loaded
|
168
173
|
@inheritance_dependencies = connection.inherited_tables
|
169
174
|
@inheritance_associations = generate_associations
|
175
|
+
@inheritance_loaded = true
|
170
176
|
end
|
171
177
|
|
172
178
|
# Calculates the inverted dependency (association), where even indirect
|
173
179
|
# inheritance comes up in the list
|
174
180
|
def generate_associations
|
181
|
+
return {} if @inheritance_dependencies.empty?
|
182
|
+
|
175
183
|
result = Hash.new{ |h, k| h[k] = [] }
|
176
184
|
masters = @inheritance_dependencies.values.flatten.uniq
|
177
185
|
|
@@ -200,7 +208,7 @@ module Torque
|
|
200
208
|
super
|
201
209
|
@data_sources_model_names = Torque::PostgreSQL.config
|
202
210
|
.irregular_models.slice(*@data_sources.keys).map do |table_name, model_name|
|
203
|
-
[table_name, model_name.constantize]
|
211
|
+
[table_name, (model_name.is_a?(Class) ? model_name : model_name.constantize)]
|
204
212
|
end.to_h
|
205
213
|
end
|
206
214
|
|