torque-postgresql 1.1.0 → 1.1.5
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/attributes.rb +0 -16
- data/lib/torque/postgresql/attributes/builder.rb +2 -2
- data/lib/torque/postgresql/attributes/builder/enum.rb +103 -66
- data/lib/torque/postgresql/attributes/builder/period.rb +1 -1
- data/lib/torque/postgresql/attributes/enum.rb +6 -1
- data/lib/torque/postgresql/attributes/enum_set.rb +6 -3
- data/lib/torque/postgresql/auxiliary_statement.rb +20 -6
- data/lib/torque/postgresql/config.rb +10 -0
- data/lib/torque/postgresql/reflection/abstract_reflection.rb +27 -4
- data/lib/torque/postgresql/relation/auxiliary_statement.rb +7 -7
- data/lib/torque/postgresql/schema_cache.rb +19 -11
- data/lib/torque/postgresql/schema_dumper.rb +16 -16
- data/lib/torque/postgresql/version.rb +1 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 91a42a9a04ba195e57f4b87af2931a6ecf82e9d58a4acec84b95350404ee4977
|
4
|
+
data.tar.gz: e4fce1b312a40bf6e98a1f8bee8351795a45a5afddf25ce0f7765cd6c01d89ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56a370889f5ffbb09a2c414bd1a9c4311d4d415675fd8ac7f00a09ffb4b2aa4b70998b475f6ab494ad06f0e0b9783ddea599268f04d0c5d3184b9e1d0d644d44
|
7
|
+
data.tar.gz: 7341f28b3805af398868be6a4095c9dcf4b9e7d6be28a0ce4e2af0340004490e2e75b9eb6e7e63f9d6ac0bba1caf5fdb7154cd5b8d7928c6c093f748cda96d71
|
data/Rakefile
CHANGED
@@ -14,13 +14,16 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|
14
14
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
15
|
end
|
16
16
|
|
17
|
-
desc '
|
18
|
-
task :
|
17
|
+
desc 'Initialize the local environment'
|
18
|
+
task :environment do |t|
|
19
19
|
lib = File.expand_path('../lib', __FILE__)
|
20
20
|
spec = File.expand_path('../spec', __FILE__)
|
21
21
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
22
22
|
$LOAD_PATH.unshift(spec) unless $LOAD_PATH.include?(spec)
|
23
|
+
end
|
23
24
|
|
25
|
+
desc 'Prints a schema dump of the test database'
|
26
|
+
task dump: :environment do |t|
|
24
27
|
require 'byebug'
|
25
28
|
require 'spec_helper'
|
26
29
|
ActiveRecord::SchemaDumper.dump
|
@@ -4,19 +4,3 @@ require_relative 'attributes/builder'
|
|
4
4
|
require_relative 'attributes/enum'
|
5
5
|
require_relative 'attributes/enum_set'
|
6
6
|
require_relative 'attributes/period'
|
7
|
-
|
8
|
-
module Torque
|
9
|
-
module PostgreSQL
|
10
|
-
module Attributes
|
11
|
-
extend ActiveSupport::Concern
|
12
|
-
|
13
|
-
# Configure enum_save_on_bang behavior
|
14
|
-
included do
|
15
|
-
class_attribute :enum_save_on_bang, instance_accessor: true
|
16
|
-
self.enum_save_on_bang = Torque::PostgreSQL.config.enum.save_on_bang
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
ActiveRecord::Base.include Attributes
|
21
|
-
end
|
22
|
-
end
|
@@ -5,14 +5,14 @@ module Torque
|
|
5
5
|
module PostgreSQL
|
6
6
|
module Attributes
|
7
7
|
module Builder
|
8
|
-
def self.include_on(klass, method_name, builder_klass, &block)
|
8
|
+
def self.include_on(klass, method_name, builder_klass, **extra, &block)
|
9
9
|
klass.define_singleton_method(method_name) do |*args, **options|
|
10
10
|
return unless connection.table_exists?(table_name)
|
11
11
|
|
12
12
|
args.each do |attribute|
|
13
13
|
begin
|
14
14
|
# Generate methods on self class
|
15
|
-
builder = builder_klass.new(self, attribute, options)
|
15
|
+
builder = builder_klass.new(self, attribute, extra.merge(options))
|
16
16
|
builder.conflicting?
|
17
17
|
builder.build
|
18
18
|
|
@@ -5,7 +5,8 @@ module Torque
|
|
5
5
|
class Enum
|
6
6
|
VALID_TYPES = %i[enum enum_set].freeze
|
7
7
|
|
8
|
-
attr_accessor :klass, :attribute, :subtype, :options, :values,
|
8
|
+
attr_accessor :klass, :attribute, :subtype, :options, :values,
|
9
|
+
:klass_module, :instance_module
|
9
10
|
|
10
11
|
# Start a new builder of methods for enum values on ActiveRecord::Base
|
11
12
|
def initialize(klass, attribute, options)
|
@@ -40,15 +41,20 @@ module Torque
|
|
40
41
|
|
41
42
|
@values_methods = begin
|
42
43
|
values.map do |val|
|
43
|
-
|
44
|
-
scope = base %
|
44
|
+
key = val.downcase.tr('- ', '__')
|
45
|
+
scope = base % key
|
45
46
|
ask = scope + '?'
|
46
47
|
bang = scope + '!'
|
47
|
-
[
|
48
|
+
[key, [scope, ask, bang, val]]
|
48
49
|
end.to_h
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
53
|
+
# Check if it's building the methods for sets
|
54
|
+
def set_features?
|
55
|
+
options[:set_features].present?
|
56
|
+
end
|
57
|
+
|
52
58
|
# Check if any of the methods that will be created get in conflict
|
53
59
|
# with the base class methods
|
54
60
|
def conflicting?
|
@@ -56,12 +62,20 @@ module Torque
|
|
56
62
|
attributes = attribute.pluralize
|
57
63
|
|
58
64
|
dangerous?(attributes, true)
|
59
|
-
dangerous?("#{attributes}
|
65
|
+
dangerous?("#{attributes}_keys", true)
|
60
66
|
dangerous?("#{attributes}_texts", true)
|
67
|
+
dangerous?("#{attributes}_options", true)
|
61
68
|
dangerous?("#{attribute}_text")
|
62
69
|
|
63
|
-
|
64
|
-
|
70
|
+
if set_features?
|
71
|
+
dangerous?("has_#{attributes}", true)
|
72
|
+
dangerous?("has_any_#{attributes}", true)
|
73
|
+
end
|
74
|
+
|
75
|
+
values_methods.each do |attr, (scope, ask, bang, *)|
|
76
|
+
dangerous?(scope, true)
|
77
|
+
dangerous?(bang)
|
78
|
+
dangerous?(ask)
|
65
79
|
end
|
66
80
|
rescue Interrupt => err
|
67
81
|
raise ArgumentError, <<-MSG.squish
|
@@ -73,14 +87,16 @@ module Torque
|
|
73
87
|
|
74
88
|
# Create all methods needed
|
75
89
|
def build
|
76
|
-
@
|
90
|
+
@klass_module = Module.new
|
91
|
+
@instance_module = Module.new
|
77
92
|
|
78
93
|
plural
|
79
94
|
stringify
|
80
95
|
all_values
|
96
|
+
set_scopes if set_features?
|
81
97
|
|
82
|
-
klass.
|
83
|
-
klass.
|
98
|
+
klass.extend klass_module
|
99
|
+
klass.include instance_module
|
84
100
|
end
|
85
101
|
|
86
102
|
private
|
@@ -96,78 +112,99 @@ module Torque
|
|
96
112
|
raise Interrupt, method_name.to_s
|
97
113
|
end
|
98
114
|
end
|
115
|
+
rescue Interrupt => e
|
116
|
+
raise e if Torque::PostgreSQL.config.enum.raise_conflicting
|
117
|
+
type = class_method ? 'class method' : 'instance method'
|
118
|
+
indicator = class_method ? '.' : '#'
|
119
|
+
|
120
|
+
Torque::PostgreSQL.logger.info(<<~MSG.squish)
|
121
|
+
Creating #{class_method} :#{method_name} for enum.
|
122
|
+
Overwriting existing method #{klass.name}#{indicator}#{method_name}.
|
123
|
+
MSG
|
99
124
|
end
|
100
125
|
|
101
126
|
# Create the method that allow access to the list of values
|
102
127
|
def plural
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
128
|
+
enum_klass = subtype.klass.name
|
129
|
+
klass_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
130
|
+
def #{attribute.pluralize} # def roles
|
131
|
+
::#{enum_klass}.values # Enum::Roles.values
|
132
|
+
end # end
|
133
|
+
|
134
|
+
def #{attribute.pluralize}_keys # def roles_keys
|
135
|
+
::#{enum_klass}.keys # Enum::Roles.keys
|
136
|
+
end # end
|
137
|
+
|
138
|
+
def #{attribute.pluralize}_texts # def roles_texts
|
139
|
+
::#{enum_klass}.members.map do |member| # Enum::Roles.members do |member|
|
140
|
+
member.text('#{attribute}', self) # member.text('role', self)
|
141
|
+
end # end
|
142
|
+
end # end
|
143
|
+
|
144
|
+
def #{attribute.pluralize}_options # def roles_options
|
145
|
+
#{attribute.pluralize}_texts.zip(::#{enum_klass}.values) # roles_texts.zip(Enum::Roles.values)
|
146
|
+
end # end
|
147
|
+
RUBY
|
148
|
+
end
|
120
149
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
150
|
+
# Create additional methods when the enum is a set, which needs
|
151
|
+
# better ways to check if values are present or not
|
152
|
+
def set_scopes
|
153
|
+
cast_type = subtype.name.chomp('[]')
|
154
|
+
klass_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
155
|
+
def has_#{attribute.pluralize}(*values) # def has_roles(*values)
|
156
|
+
attr = arel_attribute('#{attribute}') # attr = arel_attribute('role')
|
157
|
+
where(attr.contains(::Arel.array(values, cast: '#{cast_type}'))) # where(attr.contains(::Arel.array(values, cast: 'roles')))
|
158
|
+
end # end
|
159
|
+
|
160
|
+
def has_any_#{attribute.pluralize}(*values) # def has_roles(*values)
|
161
|
+
attr = arel_attribute('#{attribute}') # attr = arel_attribute('role')
|
162
|
+
where(attr.overlaps(::Arel.array(values, cast: '#{cast_type}'))) # where(attr.overlaps(::Arel.array(values, cast: 'roles')))
|
163
|
+
end # end
|
164
|
+
RUBY
|
126
165
|
end
|
127
166
|
|
128
167
|
# Create the method that turn the attribute value into text using
|
129
168
|
# the model scope
|
130
169
|
def stringify
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
define_method("#{attr}_text") { send(attr)&.text(attr, self) }
|
137
|
-
end
|
170
|
+
instance_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
171
|
+
def #{attribute}_text # def role_text
|
172
|
+
#{attribute}.text('#{attribute}', self) # role.text('role', self)
|
173
|
+
end # end
|
174
|
+
RUBY
|
138
175
|
end
|
139
176
|
|
140
177
|
# Create all the methods that represent actions related to the
|
141
178
|
# attribute value
|
142
179
|
def all_values
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
#
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
#
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
true
|
168
|
-
end
|
169
|
-
end
|
180
|
+
klass_content = ''
|
181
|
+
instance_content = ''
|
182
|
+
enum_klass = subtype.klass.name
|
183
|
+
|
184
|
+
values_methods.each do |key, (scope, ask, bang, val)|
|
185
|
+
klass_content += <<-RUBY
|
186
|
+
def #{scope} # def admin
|
187
|
+
attr = arel_attribute('#{attribute}') # attr = arel_attribute('role')
|
188
|
+
where(::#{enum_klass}.scope(attr, '#{val}')) # where(Enum::Roles.scope(attr, 'admin'))
|
189
|
+
end # end
|
190
|
+
RUBY
|
191
|
+
|
192
|
+
instance_content += <<-RUBY
|
193
|
+
def #{ask} # def admin?
|
194
|
+
#{attribute}.#{key}? # role.admin?
|
195
|
+
end # end
|
196
|
+
|
197
|
+
def #{bang} # admin!
|
198
|
+
self.#{attribute} = '#{val}' # self.role = 'admin'
|
199
|
+
return unless #{attribute}_changed? # return unless role_changed?
|
200
|
+
return save! if Torque::PostgreSQL.config.enum.save_on_bang
|
201
|
+
true # true
|
202
|
+
end # end
|
203
|
+
RUBY
|
170
204
|
end
|
205
|
+
|
206
|
+
klass_module.module_eval(klass_content)
|
207
|
+
instance_module.module_eval(instance_content)
|
171
208
|
end
|
172
209
|
end
|
173
210
|
end
|
@@ -164,7 +164,7 @@ module Torque
|
|
164
164
|
method_content = define_string_method(method_name, method_content, args)
|
165
165
|
|
166
166
|
source_module = send("#{type}_module")
|
167
|
-
source_module.
|
167
|
+
source_module.module_eval(method_content)
|
168
168
|
end
|
169
169
|
|
170
170
|
private
|
@@ -51,9 +51,14 @@ module Torque
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
# List of valus as symbols
|
55
|
+
def keys
|
56
|
+
values.map(&:to_sym)
|
57
|
+
end
|
58
|
+
|
54
59
|
# Different from values, it returns the list of items already casted
|
55
60
|
def members
|
56
|
-
values.
|
61
|
+
values.map(&method(:new))
|
57
62
|
end
|
58
63
|
|
59
64
|
# Get the list of the values translated by I18n
|
@@ -10,7 +10,7 @@ module Torque
|
|
10
10
|
include Enumerable
|
11
11
|
|
12
12
|
delegate :each, to: :members
|
13
|
-
delegate :values, :members, :texts, :to_options, :valid?, :size,
|
13
|
+
delegate :values, :keys, :members, :texts, :to_options, :valid?, :size,
|
14
14
|
:length, :connection_specification_name, to: :enum_source
|
15
15
|
|
16
16
|
# Find or create the class that will handle the value
|
@@ -28,7 +28,10 @@ module Torque
|
|
28
28
|
# Provide a method on the given class to setup which enum sets will be
|
29
29
|
# manually initialized
|
30
30
|
def include_on(klass, method_name = nil)
|
31
|
-
|
31
|
+
method_name ||= Torque::PostgreSQL.config.enum.set_method
|
32
|
+
Builder.include_on(klass, method_name, Builder::Enum, set_features: true) do |builder|
|
33
|
+
defined_enums[builder.attribute.to_sym] = builder.subtype
|
34
|
+
end
|
32
35
|
end
|
33
36
|
|
34
37
|
# The original Enum implementation, for individual values
|
@@ -73,7 +76,7 @@ module Torque
|
|
73
76
|
|
74
77
|
# Build an active record scope for a given atribute agains a value
|
75
78
|
def scope(attribute, value)
|
76
|
-
attribute.contains(
|
79
|
+
attribute.contains(::Arel.array(value, cast: enum_source.type_name))
|
77
80
|
end
|
78
81
|
|
79
82
|
private
|
@@ -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))]
|
@@ -205,9 +212,16 @@ module Torque
|
|
205
212
|
end
|
206
213
|
|
207
214
|
# Add the scopes defined by the reflection
|
215
|
+
# Possibilities:
|
216
|
+
# table
|
217
|
+
# table, foreign_klass
|
218
|
+
# table, foreign_table, foreign_klass
|
208
219
|
if association.respond_to?(:join_scope)
|
209
|
-
|
210
|
-
args
|
220
|
+
arity = association.method(:join_scope).arity
|
221
|
+
args = [@query.arel_table, foreign_table, base]
|
222
|
+
args.delete_at(1) if arity <= 2 # Delete foreign_table
|
223
|
+
args.delete_at(1) if arity <= 1 # Delete base (foreign_klass)
|
224
|
+
|
211
225
|
@query.merge(association.join_scope(*args))
|
212
226
|
end
|
213
227
|
|
@@ -281,7 +295,7 @@ module Torque
|
|
281
295
|
cte.is_a?(dependent_klass)
|
282
296
|
end
|
283
297
|
|
284
|
-
AuxiliaryStatement.build(dependent, base, options, bound_attributes)
|
298
|
+
AuxiliaryStatement.build(dependent, base, options, bound_attributes, join_sources)
|
285
299
|
end
|
286
300
|
end
|
287
301
|
|
@@ -4,6 +4,12 @@ module Torque
|
|
4
4
|
|
5
5
|
# Stores a version check for compatibility purposes
|
6
6
|
AR521 = (ActiveRecord.gem_version >= Gem::Version.new('5.2.1'))
|
7
|
+
AR523 = (ActiveRecord.gem_version >= Gem::Version.new('5.2.3'))
|
8
|
+
|
9
|
+
# Use the same logger as the Active Record one
|
10
|
+
def self.logger
|
11
|
+
ActiveRecord::Base.logger
|
12
|
+
end
|
7
13
|
|
8
14
|
# Allow nested configurations
|
9
15
|
# :TODO: Rely on +inheritable_copy+ to make nested configurations
|
@@ -63,6 +69,10 @@ module Torque
|
|
63
69
|
# database or not
|
64
70
|
enum.save_on_bang = true
|
65
71
|
|
72
|
+
# Indicates if it should raise errors when a generated method would
|
73
|
+
# conflict with an existing one
|
74
|
+
enum.raise_conflicting = false
|
75
|
+
|
66
76
|
# Specify the namespace of each enum type of value
|
67
77
|
enum.namespace = ::Object.const_set('Enum', Module.new)
|
68
78
|
|
@@ -17,12 +17,28 @@ module Torque
|
|
17
17
|
method(:join_keys).arity.eql?(0) ? join_keys : join_keys(klass)
|
18
18
|
end
|
19
19
|
|
20
|
+
# Fix for rails 5.2.3 where the join_scope method is the one now
|
21
|
+
# responsible for building the join condition
|
22
|
+
if Torque::PostgreSQL::AR523
|
23
|
+
def join_scope(table, foreign_table, foreign_klass)
|
24
|
+
return super unless connected_through_array?
|
25
|
+
|
26
|
+
predicate_builder = predicate_builder(table)
|
27
|
+
scope_chain_items = join_scopes(table, predicate_builder)
|
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?
|
34
|
+
|
35
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
20
39
|
# Manually build the join constraint
|
21
40
|
def build_join_constraint(table, foreign_table)
|
22
|
-
|
23
|
-
source_attr = foreign_table[torque_join_keys.foreign_key.to_s]
|
24
|
-
|
25
|
-
result = build_id_constraint(klass_attr, source_attr)
|
41
|
+
result = build_id_constraint_between(table, foreign_table)
|
26
42
|
result = table.create_and([result, klass.send(:type_condition, table)]) \
|
27
43
|
if klass.finder_needs_type_condition?
|
28
44
|
|
@@ -61,6 +77,13 @@ module Torque
|
|
61
77
|
|
62
78
|
private
|
63
79
|
|
80
|
+
def build_id_constraint_between(table, foreign_table)
|
81
|
+
klass_attr = table[torque_join_keys.key.to_s]
|
82
|
+
source_attr = foreign_table[torque_join_keys.foreign_key.to_s]
|
83
|
+
|
84
|
+
build_id_constraint(klass_attr, source_attr)
|
85
|
+
end
|
86
|
+
|
64
87
|
# Prepare a value for an array constraint overlap condition
|
65
88
|
def cast_constraint_to_array(type, value, should_cast)
|
66
89
|
base_ready = type.try(:array) && value.is_a?(AREL_ATTR)
|
@@ -47,16 +47,16 @@ module Torque
|
|
47
47
|
|
48
48
|
# Hook arel build to add the distinct on clause
|
49
49
|
def build_arel(*)
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
arel = super
|
51
|
+
subqueries = build_auxiliary_statements(arel)
|
52
|
+
subqueries.nil? ? arel : arel.with(subqueries)
|
53
53
|
end
|
54
54
|
|
55
55
|
# Build all necessary data for auxiliary statements
|
56
|
-
def build_auxiliary_statements
|
57
|
-
return unless
|
58
|
-
|
59
|
-
klass.build(self)
|
56
|
+
def build_auxiliary_statements(arel)
|
57
|
+
return unless auxiliary_statements_values.present?
|
58
|
+
auxiliary_statements_values.map do |klass|
|
59
|
+
klass.build(self).tap { arel.join_sources.concat(klass.join_sources) }
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -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
|
|
@@ -31,21 +31,21 @@ module Torque
|
|
31
31
|
if inherited_tables.present?
|
32
32
|
stream.puts " # These are tables that has inheritance"
|
33
33
|
inherited_tables.each do |table_name, inherits|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
34
|
+
next if ignored?(table_name)
|
35
|
+
|
36
|
+
sub_stream = StringIO.new
|
37
|
+
table(table_name, sub_stream)
|
38
|
+
|
39
|
+
# Add the inherits setting
|
40
|
+
sub_stream.rewind
|
41
|
+
inherits.map!(&:to_sym)
|
42
|
+
inherits = inherits.first if inherits.size === 1
|
43
|
+
inherits = ", inherits: #{inherits.inspect} do |t|"
|
44
|
+
table_dump = sub_stream.read.gsub(/ do \|t\|$/, inherits)
|
45
|
+
|
46
|
+
# Ensure bodyless definitions
|
47
|
+
table_dump.gsub!(/do \|t\|\n end/, '')
|
48
|
+
stream.print table_dump
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -63,7 +63,7 @@ module Torque
|
|
63
63
|
return unless types.any?
|
64
64
|
|
65
65
|
stream.puts " # These are user-defined types used on this database"
|
66
|
-
types.each { |name, type| send(type.to_sym, name, stream) }
|
66
|
+
types.sort_by(&:first).each { |name, type| send(type.to_sym, name, stream) }
|
67
67
|
stream.puts
|
68
68
|
rescue => e
|
69
69
|
stream.puts "# Could not dump user-defined types because of following #{e.class}"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: torque-postgresql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos Silva
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -260,8 +260,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
260
260
|
- !ruby/object:Gem::Version
|
261
261
|
version: 1.8.11
|
262
262
|
requirements: []
|
263
|
-
|
264
|
-
rubygems_version: 2.6.14
|
263
|
+
rubygems_version: 3.1.4
|
265
264
|
signing_key:
|
266
265
|
specification_version: 4
|
267
266
|
summary: ActiveRecord extension to access PostgreSQL advanced resources
|