activerecord-virtual_attributes 7.1.2 → 7.2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f9b4d5589eb768e0f866cd4d4cdf54e937284a98aea2ff1644e8dddb56413f9
4
- data.tar.gz: 981261df2b4e1092f1206eb633b064d7605ada874ac1c56946524b89461f7779
3
+ metadata.gz: ef69f0683d1cf4b95da626b2407fe42fcd2e6564053bcb424ea8c867365e6c94
4
+ data.tar.gz: 28d0d1506872044eae2cb1d9e84cd0044e9dae43f849facabd44024c9f1ed676
5
5
  SHA512:
6
- metadata.gz: 5bf6835a1bc40e8fd619b1f5b00a84d2f39f86ce51de170941d71e9880a1ae9c6c061b523c43f801664c8ec5789363f55d016207acde9e66655207c22fa923bf
7
- data.tar.gz: 52a5dff2126f009791c7f9dad66647b0d589d9f0c659a184c79307fb087505b37bb23e8ad3c95c82c4939531d86ed8f11cc874f0b141c34cd5836cc122897dc6
6
+ metadata.gz: 2c26a6ea644c42aa0317bcf3848f31ae79d49a86f80fa2c0832642652c9195171f52fe23b52789544fd7045efbb51a398d911e39fc2f4645e2e88a2945fa1555
7
+ data.tar.gz: 3d59e61f9b22e9037237c1e1f8e8be91ee36dc165c54a101bf742f4a5b88cc9da6b0a13fef44dbe18dda4f0af299028179e5e37c001e7f3419f6cd988679e044
data/CHANGELOG.md CHANGED
@@ -4,9 +4,15 @@ The versioning of this gem follows ActiveRecord versioning, and does not follow
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [7.2.0.0] - 2025-06-25
8
+
9
+ * virtual_delegate requires type [#185](https://github.com/ManageIQ/activerecord-virtual_attributes/pull/185)
10
+ * Rails 7.2 support [#187](https://github.com/ManageIQ/activerecord-virtual_attributes/pull/187)
11
+
7
12
  ## [7.1.2] - 2025-06-20
8
13
 
9
14
  * Introduce virtual_has_many :through [#191](https://github.com/ManageIQ/activerecord-virtual_attributes/pull/191)
15
+ * Use kwargs for virtual_delegate and virtual_column [#190](https://github.com/ManageIQ/activerecord-virtual_attributes/pull/190)
10
16
 
11
17
  ## [7.1.1] - 2025-06-18
12
18
 
@@ -119,7 +125,8 @@ The versioning of this gem follows ActiveRecord versioning, and does not follow
119
125
  * Initial Release
120
126
  * Extracted from ManageIQ/manageiq
121
127
 
122
- [Unreleased]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.1.2...HEAD
128
+ [Unreleased]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.2.0.0...HEAD
129
+ [7.2.0.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.1.2...v7.2.0.0
123
130
  [7.1.2]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.1.1...v7.1.2
124
131
  [7.1.1]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.1.0...v7.1.1
125
132
  [7.1.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.0.0...v7.1.0
data/Gemfile CHANGED
@@ -2,9 +2,4 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "~>7.1.5"
6
- gem "mysql2"
7
- gem "pg"
8
- gem "sqlite3", "< 2"
9
-
10
5
  gemspec
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
 
29
29
  spec.require_paths = ["lib"]
30
30
 
31
- spec.add_runtime_dependency "activerecord", "~> 7.1", ">=7.1.5.1"
31
+ spec.add_runtime_dependency "activerecord", "~> 7.2.2", ">=7.2.2.1"
32
32
 
33
33
  spec.add_development_dependency "byebug"
34
34
  spec.add_development_dependency "database_cleaner-active_record", "~> 2.1"
@@ -40,5 +40,5 @@ Gem::Specification.new do |spec|
40
40
  spec.add_development_dependency "rake", "~> 13.0"
41
41
  spec.add_development_dependency "rspec", "~> 3.0"
42
42
  spec.add_development_dependency "simplecov", ">= 0.21.2"
43
- spec.add_development_dependency "sqlite3"
43
+ spec.add_development_dependency "sqlite3", "< 2"
44
44
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module VirtualAttributes
3
- VERSION = "7.1.2".freeze
3
+ VERSION = "7.2.0.0".freeze
4
4
  end
5
5
  end
@@ -111,7 +111,7 @@ module ActiveRecord
111
111
  private
112
112
 
113
113
  def define_virtual_arel(name, arel) # :nodoc:
114
- self._virtual_arel = _virtual_arel.merge(name.to_s => arel)
114
+ self._virtual_arel = _virtual_arel.merge(name.to_s => arel) unless arel.nil?
115
115
  end
116
116
  end
117
117
  end
@@ -9,20 +9,12 @@ module ActiveRecord
9
9
  module VirtualDelegates
10
10
  extend ActiveSupport::Concern
11
11
 
12
- included do
13
- class_attribute :virtual_delegates_to_define, :instance_accessor => false, :default => {}
14
- end
15
-
16
12
  module ClassMethods
17
13
  #
18
14
  # Definition
19
15
  #
20
16
 
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)
24
- end
25
-
17
+ def virtual_delegate(*methods, to:, type:, prefix: nil, allow_nil: nil, default: nil, uses: nil, **options) # rubocop:disable Naming/MethodParameterName
26
18
  to = to.to_s
27
19
  if to.include?(".") && (methods.size > 1 || prefix)
28
20
  raise ArgumentError, 'Delegation only supports specifying a target method name when defining a single virtual method with no prefix'
@@ -36,38 +28,17 @@ module ActiveRecord
36
28
  # This better supports reloading of the class and changing the definitions
37
29
  methods.each do |method|
38
30
  method_name, to, method = determine_method_names(method, to, prefix)
39
- define_delegate(method_name, method, :to => to, :allow_nil => allow_nil, :default => default)
31
+ unless (to_ref = reflection_with_virtual(to))
32
+ raise ArgumentError, "Delegation needs an association. Association #{to} does not exist"
33
+ end
40
34
 
41
- self.virtual_delegates_to_define =
42
- virtual_delegates_to_define.merge(method_name.to_s => [method, options.merge(:to => to, :type => type)])
35
+ define_delegate(method_name, method, :to => to, :allow_nil => allow_nil, :default => default)
36
+ virtual_attribute(method_name, type, :uses => (uses || to), :arel => virtual_delegate_arel(method, to_ref), **options)
43
37
  end
44
38
  end
45
39
 
46
40
  private
47
41
 
48
- # define virtual_attribute for delegates
49
- #
50
- # this is called at schema load time (and not at class definition time)
51
- #
52
- # @param method_name [Symbol] name of the attribute on the source class to be defined
53
- # @param col [Symbol] name of the attribute on the associated class to be referenced
54
- # @option options :to [Symbol] name of the association from the source class to be referenced
55
- # @option options :arel [Proc] (optional and not common)
56
- # @option options :uses [Array|Symbol|Hash] sql includes hash. (default: to)
57
- def define_virtual_delegate(method_name, col, options)
58
- unless (to = options[:to]) && (to_ref = reflection_with_virtual(to.to_s))
59
- raise ArgumentError, 'Delegation needs an association. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
60
- end
61
-
62
- col = col.to_s
63
- type = options[:type] || to_ref.klass.type_for_attribute(col)
64
- type = ActiveRecord::Type.lookup(type) if type.kind_of?(Symbol)
65
- raise "unknown attribute #{to}##{col} referenced in #{name}" unless type
66
-
67
- arel = virtual_delegate_arel(col, to_ref)
68
- define_virtual_attribute(method_name, type, :uses => (options[:uses] || to), :arel => arel)
69
- end
70
-
71
42
  # see activesupport module/delegation.rb
72
43
  # rubocop:disable Style/TernaryParentheses
73
44
  def define_delegate(method_name, method, to: nil, allow_nil: nil, default: nil) # rubocop:disable Naming/MethodParameterName
@@ -85,6 +56,7 @@ module ActiveRecord
85
56
  # On the other hand it could be that the target has side-effects,
86
57
  # whereas conceptually, from the user point of view, the delegator should
87
58
  # be doing one call.
59
+ # NOTE: This is based upon ActiveSupport 6.0 delegate.rb, but we added has_attribute? and default
88
60
  if allow_nil
89
61
  method_def = <<-METHOD
90
62
  def #{method_name}(#{definition})
@@ -152,8 +152,12 @@ module ActiveRecord
152
152
 
153
153
  # convert the includes with virtual attributes to includes with proper associations
154
154
  records_by_assoc = records.group_by { |rec| assoc_cache[rec.class] }
155
- # if these are the same includes, then do the preloader work
156
- return super if records_by_assoc.size == 1 && records_by_assoc.keys.first == associations
155
+ # If the association were already translated, then short circuit / do the standard preloader work.
156
+ # When replace_virtual_fields removes the outer array, match that too.
157
+ if records_by_assoc.size == 1 &&
158
+ (associations == records_by_assoc.keys.first || associations == [records_by_assoc.keys.first])
159
+ return super
160
+ end
157
161
 
158
162
  # for each of the associations, run a preloader
159
163
  records_by_assoc.each do |klass_associations, klass_records|
@@ -191,6 +195,7 @@ module ActiveRecord
191
195
  # rubocop:enable Lint/AmbiguousOperatorPrecedence
192
196
 
193
197
  # branched.rb 7.0
198
+ # rubocop:disable Style/MultilineBlockChain
194
199
  def preloaders_for_reflection(reflection, reflection_records)
195
200
  reflection_records.group_by do |record|
196
201
  # begin virtual_attributes changes
@@ -212,6 +217,7 @@ module ActiveRecord
212
217
  end
213
218
  end
214
219
  end)
220
+ # rubocop:enable Style/MultilineBlockChain
215
221
  end
216
222
  end
217
223
  end
@@ -25,7 +25,7 @@ module ActiveRecord
25
25
  private
26
26
 
27
27
  def define_virtual_include(name, uses)
28
- self._virtual_includes = _virtual_includes.merge(name.to_s => uses)
28
+ self._virtual_includes = _virtual_includes.merge(name.to_s => uses) unless uses.nil?
29
29
  end
30
30
  end
31
31
  end
@@ -14,12 +14,12 @@ module ActiveRecord
14
14
  add_virtual_reflection(reflection, name, uses)
15
15
  end
16
16
 
17
- def virtual_has_many(name, uses: nil, source: nil, through: nil, **options)
17
+ def virtual_has_many(name, uses: nil, source: name, through: nil, **options)
18
18
  define_method(:"#{name.to_s.singularize}_ids") do
19
19
  records = send(name)
20
20
  records.respond_to?(:ids) ? records.ids : records.collect(&:id)
21
21
  end
22
- define_delegate(name, source || name, :to => through, :allow_nil => true, :default => []) if through
22
+ define_delegate(name, source, :to => through, :allow_nil => true, :default => []) if through
23
23
  reflection = ActiveRecord::Associations::Builder::HasMany.build(self, name, nil, options)
24
24
  add_virtual_reflection(reflection, name, uses)
25
25
  end
@@ -56,12 +56,15 @@ module ActiveRecord
56
56
  virtual_attribute(name, type, **options)
57
57
  end
58
58
 
59
- def virtual_attribute(name, type, **options)
59
+ def virtual_attribute(name, type, uses: nil, arel: nil, **options)
60
60
  name = name.to_s
61
61
  reload_schema_from_cache
62
62
 
63
63
  self.virtual_attributes_to_define =
64
64
  virtual_attributes_to_define.merge(name => [type, options])
65
+
66
+ define_virtual_include(name, uses)
67
+ define_virtual_arel(name, arel)
65
68
  end
66
69
 
67
70
  #
@@ -84,27 +87,18 @@ module ActiveRecord
84
87
  end
85
88
  end
86
89
 
87
- private
88
-
89
- def load_schema!
90
- super
91
-
92
- virtual_attributes_to_define.each do |name, (type, options)|
93
- type = type.call if type.respond_to?(:call)
94
- type = ActiveRecord::Type.lookup(type, **options.except(:uses, :arel)) if type.kind_of?(Symbol)
95
-
96
- define_virtual_attribute(name, type, **options.slice(:uses, :arel))
97
- end
98
-
99
- virtual_delegates_to_define.each do |method_name, (method, options)|
100
- define_virtual_delegate(method_name, method, options)
90
+ def attribute_types
91
+ @attribute_types || super.tap do |hash|
92
+ virtual_attributes_to_define.each do |name, (type, options)|
93
+ type = type.call if type.respond_to?(:call)
94
+ type = ActiveRecord::Type.lookup(type, **options) if type.kind_of?(Symbol)
95
+ hash[name] = type
96
+ end
101
97
  end
102
98
  end
103
99
 
104
- def define_virtual_attribute(name, cast_type, uses: nil, arel: nil)
100
+ def define_virtual_attribute(name, cast_type)
105
101
  attribute_types[name.to_s] = cast_type
106
- define_virtual_include(name, uses) if uses
107
- define_virtual_arel(name, arel) if arel
108
102
  end
109
103
  end
110
104
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-virtual_attributes
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.2
4
+ version: 7.2.0.0
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-06-20 00:00:00.000000000 Z
11
+ date: 2025-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '7.1'
19
+ version: 7.2.2
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 7.1.5.1
22
+ version: 7.2.2.1
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '7.1'
29
+ version: 7.2.2
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 7.1.5.1
32
+ version: 7.2.2.1
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: byebug
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -160,16 +160,16 @@ dependencies:
160
160
  name: sqlite3
161
161
  requirement: !ruby/object:Gem::Requirement
162
162
  requirements:
163
- - - ">="
163
+ - - "<"
164
164
  - !ruby/object:Gem::Version
165
- version: '0'
165
+ version: '2'
166
166
  type: :development
167
167
  prerelease: false
168
168
  version_requirements: !ruby/object:Gem::Requirement
169
169
  requirements:
170
- - - ">="
170
+ - - "<"
171
171
  - !ruby/object:Gem::Version
172
- version: '0'
172
+ version: '2'
173
173
  description: Define attributes in arel
174
174
  email:
175
175
  - keenan@thebrocks.net