activerecord-virtual_attributes 7.1.0 → 7.1.2
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.md +11 -1
- data/activerecord-virtual_attributes.gemspec +3 -4
- data/lib/active_record/virtual_attributes/version.rb +1 -1
- data/lib/active_record/virtual_attributes/virtual_arel.rb +1 -44
- data/lib/active_record/virtual_attributes/virtual_delegates.rb +30 -22
- data/lib/active_record/virtual_attributes/virtual_fields.rb +11 -6
- data/lib/active_record/virtual_attributes/virtual_includes.rb +1 -1
- data/lib/active_record/virtual_attributes/virtual_reflections.rb +8 -11
- data/lib/active_record/virtual_attributes.rb +8 -7
- metadata +8 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f9b4d5589eb768e0f866cd4d4cdf54e937284a98aea2ff1644e8dddb56413f9
|
4
|
+
data.tar.gz: 981261df2b4e1092f1206eb633b064d7605ada874ac1c56946524b89461f7779
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5bf6835a1bc40e8fd619b1f5b00a84d2f39f86ce51de170941d71e9880a1ae9c6c061b523c43f801664c8ec5789363f55d016207acde9e66655207c22fa923bf
|
7
|
+
data.tar.gz: 52a5dff2126f009791c7f9dad66647b0d589d9f0c659a184c79307fb087505b37bb23e8ad3c95c82c4939531d86ed8f11cc874f0b141c34cd5836cc122897dc6
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,14 @@ The versioning of this gem follows ActiveRecord versioning, and does not follow
|
|
4
4
|
|
5
5
|
## [Unreleased]
|
6
6
|
|
7
|
+
## [7.1.2] - 2025-06-20
|
8
|
+
|
9
|
+
* Introduce virtual_has_many :through [#191](https://github.com/ManageIQ/activerecord-virtual_attributes/pull/191)
|
10
|
+
|
11
|
+
## [7.1.1] - 2025-06-18
|
12
|
+
|
13
|
+
* Deprecate virtual_delegate without a type [#188](https://github.com/ManageIQ/activerecord-virtual_attributes/pull/188)
|
14
|
+
|
7
15
|
## [7.1.0] - 2025-02-19
|
8
16
|
|
9
17
|
* Use TableAlias for table aliasing [#168](https://github.com/ManageIQ/activerecord-virtual_attributes/pull/168)
|
@@ -111,7 +119,9 @@ The versioning of this gem follows ActiveRecord versioning, and does not follow
|
|
111
119
|
* Initial Release
|
112
120
|
* Extracted from ManageIQ/manageiq
|
113
121
|
|
114
|
-
[Unreleased]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.1.
|
122
|
+
[Unreleased]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.1.2...HEAD
|
123
|
+
[7.1.2]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.1.1...v7.1.2
|
124
|
+
[7.1.1]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.1.0...v7.1.1
|
115
125
|
[7.1.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.0.0...v7.1.0
|
116
126
|
[7.0.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v6.1.2...v7.0.0
|
117
127
|
[6.1.2]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v6.1.1...v6.1.2
|
@@ -28,14 +28,13 @@ Gem::Specification.new do |spec|
|
|
28
28
|
|
29
29
|
spec.require_paths = ["lib"]
|
30
30
|
|
31
|
-
spec.
|
32
|
-
# plan to ship a new 7.0 to fix it. See https://github.com/rails/rails/pull/54264
|
33
|
-
spec.add_runtime_dependency "activerecord", "~> 7.0", ">=7.0.8.7"
|
31
|
+
spec.add_runtime_dependency "activerecord", "~> 7.1", ">=7.1.5.1"
|
34
32
|
|
35
33
|
spec.add_development_dependency "byebug"
|
36
34
|
spec.add_development_dependency "database_cleaner-active_record", "~> 2.1"
|
37
35
|
spec.add_development_dependency "db-query-matchers"
|
38
|
-
spec.add_development_dependency "manageiq-style", ">= 1.5.
|
36
|
+
spec.add_development_dependency "manageiq-style", ">= 1.5.4"
|
37
|
+
|
39
38
|
spec.add_development_dependency "mysql2"
|
40
39
|
spec.add_development_dependency "pg"
|
41
40
|
spec.add_development_dependency "rake", "~> 13.0"
|
@@ -111,52 +111,9 @@ module ActiveRecord
|
|
111
111
|
private
|
112
112
|
|
113
113
|
def define_virtual_arel(name, arel) # :nodoc:
|
114
|
-
self._virtual_arel = _virtual_arel.merge(name => arel)
|
114
|
+
self._virtual_arel = _virtual_arel.merge(name.to_s => arel)
|
115
115
|
end
|
116
116
|
end
|
117
117
|
end
|
118
118
|
end
|
119
119
|
end
|
120
|
-
|
121
|
-
# fixed in https://github.com/rails/rails/pull/45642
|
122
|
-
if ActiveRecord.version < Gem::Version.new(7.1)
|
123
|
-
module Arel # :nodoc: all
|
124
|
-
# rubocop:disable Naming/MethodName
|
125
|
-
# rubocop:disable Naming/MethodParameterName
|
126
|
-
# rubocop:disable Style/ConditionalAssignment
|
127
|
-
module Visitors
|
128
|
-
# rails 6.1...
|
129
|
-
class ToSql
|
130
|
-
private
|
131
|
-
|
132
|
-
def visit_Arel_Nodes_HomogeneousIn(o, collector)
|
133
|
-
collector.preparable = false
|
134
|
-
|
135
|
-
# change:
|
136
|
-
# See https://github.com/rails/rails/pull/45642
|
137
|
-
visit(o.left, collector)
|
138
|
-
# /change
|
139
|
-
|
140
|
-
if o.type == :in
|
141
|
-
collector << " IN ("
|
142
|
-
else
|
143
|
-
collector << " NOT IN ("
|
144
|
-
end
|
145
|
-
|
146
|
-
values = o.casted_values
|
147
|
-
|
148
|
-
if values.empty?
|
149
|
-
collector << @connection.quote(nil)
|
150
|
-
else
|
151
|
-
collector.add_binds(values, o.proc_for_binds, &bind_block)
|
152
|
-
end
|
153
|
-
|
154
|
-
collector << ")"
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
# rubocop:enable Naming/MethodName
|
159
|
-
# rubocop:enable Naming/MethodParameterName
|
160
|
-
# rubocop:enable Style/ConditionalAssignment
|
161
|
-
end
|
162
|
-
end
|
@@ -10,8 +10,7 @@ module ActiveRecord
|
|
10
10
|
extend ActiveSupport::Concern
|
11
11
|
|
12
12
|
included do
|
13
|
-
class_attribute :virtual_delegates_to_define, :instance_accessor => false
|
14
|
-
self.virtual_delegates_to_define = {}
|
13
|
+
class_attribute :virtual_delegates_to_define, :instance_accessor => false, :default => {}
|
15
14
|
end
|
16
15
|
|
17
16
|
module ClassMethods
|
@@ -19,38 +18,28 @@ module ActiveRecord
|
|
19
18
|
# Definition
|
20
19
|
#
|
21
20
|
|
22
|
-
def virtual_delegate(*methods)
|
23
|
-
|
24
|
-
|
25
|
-
raise ArgumentError, 'Delegation needs an association. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
|
21
|
+
def virtual_delegate(*methods, to:, type: nil, prefix: nil, allow_nil: nil, default: nil, **options) # rubocop:disable Naming/MethodParameterName
|
22
|
+
unless type
|
23
|
+
ActiveRecord::VirtualAttributes.deprecator.warn("Calling virtual_delegate without :type is now deprecated", caller)
|
26
24
|
end
|
27
25
|
|
28
26
|
to = to.to_s
|
29
|
-
if to.include?(".") && methods.size > 1
|
30
|
-
raise ArgumentError, 'Delegation only supports specifying a method name when defining a single virtual method'
|
27
|
+
if to.include?(".") && (methods.size > 1 || prefix)
|
28
|
+
raise ArgumentError, 'Delegation only supports specifying a target method name when defining a single virtual method with no prefix'
|
31
29
|
end
|
32
30
|
|
33
31
|
if to.count(".") > 1
|
34
|
-
raise ArgumentError, 'Delegation needs a single association. Supply
|
32
|
+
raise ArgumentError, 'Delegation needs a single association. Supply keyword :to with only 1 period (e.g. delegate :hello, to: "greeter.greeting")'
|
35
33
|
end
|
36
34
|
|
37
|
-
allow_nil = options[:allow_nil]
|
38
|
-
default = options[:default]
|
39
|
-
|
40
35
|
# put method entry per method name.
|
41
36
|
# This better supports reloading of the class and changing the definitions
|
42
37
|
methods.each do |method|
|
43
|
-
|
44
|
-
method_name = "#{method_prefix}#{method}"
|
45
|
-
if to.include?(".") # to => "target.method"
|
46
|
-
to, method = to.split(".").map(&:to_sym)
|
47
|
-
options[:to] = to
|
48
|
-
end
|
49
|
-
|
38
|
+
method_name, to, method = determine_method_names(method, to, prefix)
|
50
39
|
define_delegate(method_name, method, :to => to, :allow_nil => allow_nil, :default => default)
|
51
40
|
|
52
41
|
self.virtual_delegates_to_define =
|
53
|
-
virtual_delegates_to_define.merge(method_name => [method, options])
|
42
|
+
virtual_delegates_to_define.merge(method_name.to_s => [method, options.merge(:to => to, :type => type)])
|
54
43
|
end
|
55
44
|
end
|
56
45
|
|
@@ -80,6 +69,7 @@ module ActiveRecord
|
|
80
69
|
end
|
81
70
|
|
82
71
|
# see activesupport module/delegation.rb
|
72
|
+
# rubocop:disable Style/TernaryParentheses
|
83
73
|
def define_delegate(method_name, method, to: nil, allow_nil: nil, default: nil) # rubocop:disable Naming/MethodParameterName
|
84
74
|
location = caller_locations(2, 1).first
|
85
75
|
file, line = location.path, location.lineno
|
@@ -125,9 +115,27 @@ module ActiveRecord
|
|
125
115
|
method_def = method_def.split("\n").map(&:strip).join(';')
|
126
116
|
module_eval(method_def, file, line)
|
127
117
|
end
|
118
|
+
# rubocop:enable Style/TernaryParentheses
|
119
|
+
|
120
|
+
# Sometimes the `to` contains the column name target.column, split it up to the source method_name and target column
|
121
|
+
# If `to` does specify the column name, `to` becomes the target (i.e.: association)
|
122
|
+
#
|
123
|
+
# @param column [Symbol|String] the name of the column
|
124
|
+
# @param to [Symbol|String]
|
125
|
+
# @param prefix [Boolean|Nil|Symbol]
|
126
|
+
# @return [Symbol, Symbol, Symbol] method_name, relation, relation's column name
|
127
|
+
def determine_method_names(column, to, prefix) # rubocop:disable Naming/MethodParameterName
|
128
|
+
method_name = column = column.to_sym
|
129
|
+
|
130
|
+
tos = to.to_s
|
131
|
+
if tos.include?(".") # to => "target.method"
|
132
|
+
to, column = tos.split(".").map(&:to_sym)
|
133
|
+
end
|
134
|
+
|
135
|
+
method_prefix = "#{prefix == true ? to : prefix}_" if prefix
|
136
|
+
method_name = "#{method_prefix}#{method_name}".to_sym
|
128
137
|
|
129
|
-
|
130
|
-
"#{prefix == true ? to : prefix}_" if prefix
|
138
|
+
[method_name, to.to_sym, column]
|
131
139
|
end
|
132
140
|
|
133
141
|
# @param col [String] attribute name
|
@@ -143,7 +143,7 @@ module ActiveRecord
|
|
143
143
|
|
144
144
|
module Associations
|
145
145
|
class Preloader
|
146
|
-
prepend(Module.new
|
146
|
+
prepend(Module.new do
|
147
147
|
# preloader is called with virtual attributes - need to resolve
|
148
148
|
def call
|
149
149
|
# Possibly overkill since all records probably have the same class and associations
|
@@ -165,11 +165,14 @@ module ActiveRecord
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
end
|
168
|
-
|
168
|
+
end)
|
169
169
|
|
170
170
|
class Branch
|
171
|
-
prepend(Module.new
|
171
|
+
prepend(Module.new do
|
172
172
|
# from branched.rb 7.0
|
173
|
+
# not going to modify rails code for rubocops
|
174
|
+
# rubocop:disable Lint/AmbiguousOperatorPrecedence
|
175
|
+
# rubocop:disable Layout/EmptyLineAfterGuardClause
|
173
176
|
def grouped_records
|
174
177
|
h = {}
|
175
178
|
polymorphic_parent = !root? && parent.polymorphic?
|
@@ -184,6 +187,8 @@ module ActiveRecord
|
|
184
187
|
end
|
185
188
|
h
|
186
189
|
end
|
190
|
+
# rubocop:enable Layout/EmptyLineAfterGuardClause
|
191
|
+
# rubocop:enable Lint/AmbiguousOperatorPrecedence
|
187
192
|
|
188
193
|
# branched.rb 7.0
|
189
194
|
def preloaders_for_reflection(reflection, reflection_records)
|
@@ -206,13 +211,13 @@ module ActiveRecord
|
|
206
211
|
preloader_for(reflection).new(rhs_klass, rs, reflection, scope, reflection_scope, associate_by_default)
|
207
212
|
end
|
208
213
|
end
|
209
|
-
|
214
|
+
end)
|
210
215
|
end
|
211
216
|
end
|
212
217
|
end
|
213
218
|
|
214
219
|
class Relation
|
215
|
-
include(Module.new
|
220
|
+
include(Module.new do
|
216
221
|
# From ActiveRecord::QueryMethods (rails 5.2 - 6.1)
|
217
222
|
def build_select(arel)
|
218
223
|
if select_values.any?
|
@@ -243,6 +248,6 @@ module ActiveRecord
|
|
243
248
|
associations = klass.replace_virtual_fields(associations) || {}
|
244
249
|
super
|
245
250
|
end
|
246
|
-
|
251
|
+
end)
|
247
252
|
end
|
248
253
|
end
|
@@ -5,31 +5,28 @@ module ActiveRecord
|
|
5
5
|
include ActiveRecord::VirtualAttributes::VirtualIncludes
|
6
6
|
|
7
7
|
module ClassMethods
|
8
|
-
|
9
8
|
#
|
10
9
|
# Definition
|
11
10
|
#
|
12
11
|
|
13
|
-
def virtual_has_one(name,
|
14
|
-
uses = options.delete(:uses)
|
12
|
+
def virtual_has_one(name, uses: nil, **options)
|
15
13
|
reflection = ActiveRecord::Associations::Builder::HasOne.build(self, name, nil, options)
|
16
|
-
add_virtual_reflection(reflection, name, uses
|
14
|
+
add_virtual_reflection(reflection, name, uses)
|
17
15
|
end
|
18
16
|
|
19
|
-
def virtual_has_many(name,
|
17
|
+
def virtual_has_many(name, uses: nil, source: nil, through: nil, **options)
|
20
18
|
define_method(:"#{name.to_s.singularize}_ids") do
|
21
19
|
records = send(name)
|
22
20
|
records.respond_to?(:ids) ? records.ids : records.collect(&:id)
|
23
21
|
end
|
24
|
-
|
22
|
+
define_delegate(name, source || name, :to => through, :allow_nil => true, :default => []) if through
|
25
23
|
reflection = ActiveRecord::Associations::Builder::HasMany.build(self, name, nil, options)
|
26
|
-
add_virtual_reflection(reflection, name, uses
|
24
|
+
add_virtual_reflection(reflection, name, uses)
|
27
25
|
end
|
28
26
|
|
29
|
-
def virtual_belongs_to(name,
|
30
|
-
uses = options.delete(:uses)
|
27
|
+
def virtual_belongs_to(name, uses: nil, **options)
|
31
28
|
reflection = ActiveRecord::Associations::Builder::BelongsTo.build(self, name, nil, options)
|
32
|
-
add_virtual_reflection(reflection, name, uses
|
29
|
+
add_virtual_reflection(reflection, name, uses)
|
33
30
|
end
|
34
31
|
|
35
32
|
def virtual_reflection?(name)
|
@@ -95,7 +92,7 @@ module ActiveRecord
|
|
95
92
|
|
96
93
|
private
|
97
94
|
|
98
|
-
def add_virtual_reflection(reflection, name, uses
|
95
|
+
def add_virtual_reflection(reflection, name, uses)
|
99
96
|
raise ArgumentError, "macro must be specified" unless reflection
|
100
97
|
|
101
98
|
reset_virtual_reflection_information
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "active_support/concern"
|
2
2
|
require "active_record"
|
3
3
|
|
4
|
+
require "active_record/virtual_attributes/version"
|
4
5
|
require "active_record/virtual_attributes/virtual_includes"
|
5
6
|
require "active_record/virtual_attributes/virtual_arel"
|
6
7
|
require "active_record/virtual_attributes/virtual_delegates"
|
@@ -37,9 +38,12 @@ module ActiveRecord
|
|
37
38
|
ActiveRecord::Type.register(:string_set, Type::StringSet)
|
38
39
|
ActiveRecord::Type.register(:symbol, Type::Symbol)
|
39
40
|
|
41
|
+
def self.deprecator
|
42
|
+
@deprecator ||= ActiveSupport::Deprecation.new(ActiveRecord::VirtualAttributes::VERSION, "virtual_attributes")
|
43
|
+
end
|
44
|
+
|
40
45
|
included do
|
41
|
-
class_attribute :virtual_attributes_to_define, :instance_accessor => false
|
42
|
-
self.virtual_attributes_to_define = {}
|
46
|
+
class_attribute :virtual_attributes_to_define, :instance_accessor => false, :default => {}
|
43
47
|
end
|
44
48
|
|
45
49
|
module ClassMethods
|
@@ -48,10 +52,7 @@ module ActiveRecord
|
|
48
52
|
#
|
49
53
|
|
50
54
|
# Compatibility method: `virtual_attribute` is a more accurate name
|
51
|
-
def virtual_column(name, **options)
|
52
|
-
type = options.delete(:type)
|
53
|
-
raise ArgumentError, "missing :type attribute" unless type
|
54
|
-
|
55
|
+
def virtual_column(name, type:, **options)
|
55
56
|
virtual_attribute(name, type, **options)
|
56
57
|
end
|
57
58
|
|
@@ -101,7 +102,7 @@ module ActiveRecord
|
|
101
102
|
end
|
102
103
|
|
103
104
|
def define_virtual_attribute(name, cast_type, uses: nil, arel: nil)
|
104
|
-
attribute_types[name] = cast_type
|
105
|
+
attribute_types[name.to_s] = cast_type
|
105
106
|
define_virtual_include(name, uses) if uses
|
106
107
|
define_virtual_arel(name, arel) if arel
|
107
108
|
end
|
metadata
CHANGED
@@ -1,49 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-virtual_attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.1.
|
4
|
+
version: 7.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keenan Brock
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: concurrent-ruby
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "<"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 1.3.5
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "<"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 1.3.5
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: activerecord
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
17
|
- - "~>"
|
32
18
|
- !ruby/object:Gem::Version
|
33
|
-
version: '7.
|
19
|
+
version: '7.1'
|
34
20
|
- - ">="
|
35
21
|
- !ruby/object:Gem::Version
|
36
|
-
version: 7.
|
22
|
+
version: 7.1.5.1
|
37
23
|
type: :runtime
|
38
24
|
prerelease: false
|
39
25
|
version_requirements: !ruby/object:Gem::Requirement
|
40
26
|
requirements:
|
41
27
|
- - "~>"
|
42
28
|
- !ruby/object:Gem::Version
|
43
|
-
version: '7.
|
29
|
+
version: '7.1'
|
44
30
|
- - ">="
|
45
31
|
- !ruby/object:Gem::Version
|
46
|
-
version: 7.
|
32
|
+
version: 7.1.5.1
|
47
33
|
- !ruby/object:Gem::Dependency
|
48
34
|
name: byebug
|
49
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,14 +78,14 @@ dependencies:
|
|
92
78
|
requirements:
|
93
79
|
- - ">="
|
94
80
|
- !ruby/object:Gem::Version
|
95
|
-
version: 1.5.
|
81
|
+
version: 1.5.4
|
96
82
|
type: :development
|
97
83
|
prerelease: false
|
98
84
|
version_requirements: !ruby/object:Gem::Requirement
|
99
85
|
requirements:
|
100
86
|
- - ">="
|
101
87
|
- !ruby/object:Gem::Version
|
102
|
-
version: 1.5.
|
88
|
+
version: 1.5.4
|
103
89
|
- !ruby/object:Gem::Dependency
|
104
90
|
name: mysql2
|
105
91
|
requirement: !ruby/object:Gem::Requirement
|