activerecord-virtual_attributes 7.1.1 → 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 +4 -4
- data/CHANGELOG.md +13 -1
- data/Gemfile +0 -5
- data/activerecord-virtual_attributes.gemspec +2 -2
- data/lib/active_record/virtual_attributes/version.rb +1 -1
- data/lib/active_record/virtual_attributes/virtual_arel.rb +1 -2
- data/lib/active_record/virtual_attributes/virtual_delegates.rb +30 -53
- data/lib/active_record/virtual_attributes/virtual_fields.rb +16 -8
- 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 +14 -23
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef69f0683d1cf4b95da626b2407fe42fcd2e6564053bcb424ea8c867365e6c94
|
4
|
+
data.tar.gz: 28d0d1506872044eae2cb1d9e84cd0044e9dae43f849facabd44024c9f1ed676
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c26a6ea644c42aa0317bcf3848f31ae79d49a86f80fa2c0832642652c9195171f52fe23b52789544fd7045efbb51a398d911e39fc2f4645e2e88a2945fa1555
|
7
|
+
data.tar.gz: 3d59e61f9b22e9037237c1e1f8e8be91ee36dc165c54a101bf742f4a5b88cc9da6b0a13fef44dbe18dda4f0af299028179e5e37c001e7f3419f6cd988679e044
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,16 @@ 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
|
+
|
12
|
+
## [7.1.2] - 2025-06-20
|
13
|
+
|
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)
|
16
|
+
|
7
17
|
## [7.1.1] - 2025-06-18
|
8
18
|
|
9
19
|
* Deprecate virtual_delegate without a type [#188](https://github.com/ManageIQ/activerecord-virtual_attributes/pull/188)
|
@@ -115,7 +125,9 @@ The versioning of this gem follows ActiveRecord versioning, and does not follow
|
|
115
125
|
* Initial Release
|
116
126
|
* Extracted from ManageIQ/manageiq
|
117
127
|
|
118
|
-
[Unreleased]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.
|
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
|
130
|
+
[7.1.2]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.1.1...v7.1.2
|
119
131
|
[7.1.1]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.1.0...v7.1.1
|
120
132
|
[7.1.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v7.0.0...v7.1.0
|
121
133
|
[7.0.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v6.1.2...v7.0.0
|
data/Gemfile
CHANGED
@@ -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.
|
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
|
@@ -111,10 +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) unless arel.nil?
|
115
115
|
end
|
116
116
|
end
|
117
117
|
end
|
118
118
|
end
|
119
119
|
end
|
120
|
-
|
@@ -9,80 +9,38 @@ 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)
|
22
|
-
options = methods.extract_options!
|
23
|
-
unless (to = options[:to])
|
24
|
-
raise ArgumentError, 'Delegation needs an association. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
|
25
|
-
end
|
26
|
-
|
27
|
-
unless options[:type]
|
28
|
-
ActiveRecord::VirtualAttributes.deprecator.warn("Calling virtual_delegate without :type is now deprecated", caller)
|
29
|
-
end
|
30
|
-
|
17
|
+
def virtual_delegate(*methods, to:, type:, prefix: nil, allow_nil: nil, default: nil, uses: nil, **options) # rubocop:disable Naming/MethodParameterName
|
31
18
|
to = to.to_s
|
32
|
-
if to.include?(".") && methods.size > 1
|
33
|
-
raise ArgumentError, 'Delegation only supports specifying a method name when defining a single virtual method'
|
19
|
+
if to.include?(".") && (methods.size > 1 || prefix)
|
20
|
+
raise ArgumentError, 'Delegation only supports specifying a target method name when defining a single virtual method with no prefix'
|
34
21
|
end
|
35
22
|
|
36
23
|
if to.count(".") > 1
|
37
|
-
raise ArgumentError, 'Delegation needs a single association. Supply
|
24
|
+
raise ArgumentError, 'Delegation needs a single association. Supply keyword :to with only 1 period (e.g. delegate :hello, to: "greeter.greeting")'
|
38
25
|
end
|
39
26
|
|
40
|
-
allow_nil = options[:allow_nil]
|
41
|
-
default = options[:default]
|
42
|
-
|
43
27
|
# put method entry per method name.
|
44
28
|
# This better supports reloading of the class and changing the definitions
|
45
29
|
methods.each do |method|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
to, method = to.split(".").map(&:to_sym)
|
50
|
-
options[:to] = to
|
30
|
+
method_name, to, method = determine_method_names(method, to, prefix)
|
31
|
+
unless (to_ref = reflection_with_virtual(to))
|
32
|
+
raise ArgumentError, "Delegation needs an association. Association #{to} does not exist"
|
51
33
|
end
|
52
34
|
|
53
35
|
define_delegate(method_name, method, :to => to, :allow_nil => allow_nil, :default => default)
|
54
|
-
|
55
|
-
self.virtual_delegates_to_define =
|
56
|
-
virtual_delegates_to_define.merge(method_name => [method, options])
|
36
|
+
virtual_attribute(method_name, type, :uses => (uses || to), :arel => virtual_delegate_arel(method, to_ref), **options)
|
57
37
|
end
|
58
38
|
end
|
59
39
|
|
60
40
|
private
|
61
41
|
|
62
|
-
# define virtual_attribute for delegates
|
63
|
-
#
|
64
|
-
# this is called at schema load time (and not at class definition time)
|
65
|
-
#
|
66
|
-
# @param method_name [Symbol] name of the attribute on the source class to be defined
|
67
|
-
# @param col [Symbol] name of the attribute on the associated class to be referenced
|
68
|
-
# @option options :to [Symbol] name of the association from the source class to be referenced
|
69
|
-
# @option options :arel [Proc] (optional and not common)
|
70
|
-
# @option options :uses [Array|Symbol|Hash] sql includes hash. (default: to)
|
71
|
-
def define_virtual_delegate(method_name, col, options)
|
72
|
-
unless (to = options[:to]) && (to_ref = reflection_with_virtual(to.to_s))
|
73
|
-
raise ArgumentError, 'Delegation needs an association. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
|
74
|
-
end
|
75
|
-
|
76
|
-
col = col.to_s
|
77
|
-
type = options[:type] || to_ref.klass.type_for_attribute(col)
|
78
|
-
type = ActiveRecord::Type.lookup(type) if type.kind_of?(Symbol)
|
79
|
-
raise "unknown attribute #{to}##{col} referenced in #{name}" unless type
|
80
|
-
|
81
|
-
arel = virtual_delegate_arel(col, to_ref)
|
82
|
-
define_virtual_attribute(method_name, type, :uses => (options[:uses] || to), :arel => arel)
|
83
|
-
end
|
84
|
-
|
85
42
|
# see activesupport module/delegation.rb
|
43
|
+
# rubocop:disable Style/TernaryParentheses
|
86
44
|
def define_delegate(method_name, method, to: nil, allow_nil: nil, default: nil) # rubocop:disable Naming/MethodParameterName
|
87
45
|
location = caller_locations(2, 1).first
|
88
46
|
file, line = location.path, location.lineno
|
@@ -98,6 +56,7 @@ module ActiveRecord
|
|
98
56
|
# On the other hand it could be that the target has side-effects,
|
99
57
|
# whereas conceptually, from the user point of view, the delegator should
|
100
58
|
# be doing one call.
|
59
|
+
# NOTE: This is based upon ActiveSupport 6.0 delegate.rb, but we added has_attribute? and default
|
101
60
|
if allow_nil
|
102
61
|
method_def = <<-METHOD
|
103
62
|
def #{method_name}(#{definition})
|
@@ -128,9 +87,27 @@ module ActiveRecord
|
|
128
87
|
method_def = method_def.split("\n").map(&:strip).join(';')
|
129
88
|
module_eval(method_def, file, line)
|
130
89
|
end
|
90
|
+
# rubocop:enable Style/TernaryParentheses
|
91
|
+
|
92
|
+
# Sometimes the `to` contains the column name target.column, split it up to the source method_name and target column
|
93
|
+
# If `to` does specify the column name, `to` becomes the target (i.e.: association)
|
94
|
+
#
|
95
|
+
# @param column [Symbol|String] the name of the column
|
96
|
+
# @param to [Symbol|String]
|
97
|
+
# @param prefix [Boolean|Nil|Symbol]
|
98
|
+
# @return [Symbol, Symbol, Symbol] method_name, relation, relation's column name
|
99
|
+
def determine_method_names(column, to, prefix) # rubocop:disable Naming/MethodParameterName
|
100
|
+
method_name = column = column.to_sym
|
101
|
+
|
102
|
+
tos = to.to_s
|
103
|
+
if tos.include?(".") # to => "target.method"
|
104
|
+
to, column = tos.split(".").map(&:to_sym)
|
105
|
+
end
|
106
|
+
|
107
|
+
method_prefix = "#{prefix == true ? to : prefix}_" if prefix
|
108
|
+
method_name = "#{method_prefix}#{method_name}".to_sym
|
131
109
|
|
132
|
-
|
133
|
-
"#{prefix == true ? to : prefix}_" if prefix
|
110
|
+
[method_name, to.to_sym, column]
|
134
111
|
end
|
135
112
|
|
136
113
|
# @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
|
@@ -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
|
-
#
|
156
|
-
|
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|
|
@@ -165,13 +169,14 @@ module ActiveRecord
|
|
165
169
|
end
|
166
170
|
end
|
167
171
|
end
|
168
|
-
|
172
|
+
end)
|
169
173
|
|
170
174
|
class Branch
|
171
|
-
prepend(Module.new
|
175
|
+
prepend(Module.new do
|
172
176
|
# from branched.rb 7.0
|
173
177
|
# not going to modify rails code for rubocops
|
174
178
|
# rubocop:disable Lint/AmbiguousOperatorPrecedence
|
179
|
+
# rubocop:disable Layout/EmptyLineAfterGuardClause
|
175
180
|
def grouped_records
|
176
181
|
h = {}
|
177
182
|
polymorphic_parent = !root? && parent.polymorphic?
|
@@ -186,9 +191,11 @@ module ActiveRecord
|
|
186
191
|
end
|
187
192
|
h
|
188
193
|
end
|
194
|
+
# rubocop:enable Layout/EmptyLineAfterGuardClause
|
189
195
|
# rubocop:enable Lint/AmbiguousOperatorPrecedence
|
190
196
|
|
191
197
|
# branched.rb 7.0
|
198
|
+
# rubocop:disable Style/MultilineBlockChain
|
192
199
|
def preloaders_for_reflection(reflection, reflection_records)
|
193
200
|
reflection_records.group_by do |record|
|
194
201
|
# begin virtual_attributes changes
|
@@ -209,13 +216,14 @@ module ActiveRecord
|
|
209
216
|
preloader_for(reflection).new(rhs_klass, rs, reflection, scope, reflection_scope, associate_by_default)
|
210
217
|
end
|
211
218
|
end
|
212
|
-
|
219
|
+
end)
|
220
|
+
# rubocop:enable Style/MultilineBlockChain
|
213
221
|
end
|
214
222
|
end
|
215
223
|
end
|
216
224
|
|
217
225
|
class Relation
|
218
|
-
include(Module.new
|
226
|
+
include(Module.new do
|
219
227
|
# From ActiveRecord::QueryMethods (rails 5.2 - 6.1)
|
220
228
|
def build_select(arel)
|
221
229
|
if select_values.any?
|
@@ -246,6 +254,6 @@ module ActiveRecord
|
|
246
254
|
associations = klass.replace_virtual_fields(associations) || {}
|
247
255
|
super
|
248
256
|
end
|
249
|
-
|
257
|
+
end)
|
250
258
|
end
|
251
259
|
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: name, 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, :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
|
@@ -52,19 +52,19 @@ module ActiveRecord
|
|
52
52
|
#
|
53
53
|
|
54
54
|
# Compatibility method: `virtual_attribute` is a more accurate name
|
55
|
-
def virtual_column(name, **options)
|
56
|
-
type = options.delete(:type)
|
57
|
-
raise ArgumentError, "missing :type attribute" unless type
|
58
|
-
|
55
|
+
def virtual_column(name, type:, **options)
|
59
56
|
virtual_attribute(name, type, **options)
|
60
57
|
end
|
61
58
|
|
62
|
-
def virtual_attribute(name, type, **options)
|
59
|
+
def virtual_attribute(name, type, uses: nil, arel: nil, **options)
|
63
60
|
name = name.to_s
|
64
61
|
reload_schema_from_cache
|
65
62
|
|
66
63
|
self.virtual_attributes_to_define =
|
67
64
|
virtual_attributes_to_define.merge(name => [type, options])
|
65
|
+
|
66
|
+
define_virtual_include(name, uses)
|
67
|
+
define_virtual_arel(name, arel)
|
68
68
|
end
|
69
69
|
|
70
70
|
#
|
@@ -87,27 +87,18 @@ module ActiveRecord
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
type = ActiveRecord::Type.lookup(type, **options.except(:uses, :arel)) if type.kind_of?(Symbol)
|
98
|
-
|
99
|
-
define_virtual_attribute(name, type, **options.slice(:uses, :arel))
|
100
|
-
end
|
101
|
-
|
102
|
-
virtual_delegates_to_define.each do |method_name, (method, options)|
|
103
|
-
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
|
104
97
|
end
|
105
98
|
end
|
106
99
|
|
107
|
-
def define_virtual_attribute(name, cast_type
|
108
|
-
attribute_types[name] = cast_type
|
109
|
-
define_virtual_include(name, uses) if uses
|
110
|
-
define_virtual_arel(name, arel) if arel
|
100
|
+
def define_virtual_attribute(name, cast_type)
|
101
|
+
attribute_types[name.to_s] = cast_type
|
111
102
|
end
|
112
103
|
end
|
113
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.
|
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-
|
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:
|
19
|
+
version: 7.2.2
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 7.
|
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:
|
29
|
+
version: 7.2.2
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 7.
|
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: '
|
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: '
|
172
|
+
version: '2'
|
173
173
|
description: Define attributes in arel
|
174
174
|
email:
|
175
175
|
- keenan@thebrocks.net
|