activerecord-virtual_attributes 3.0.0 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +8 -6
- data/.github/workflows/ci.yaml +74 -0
- data/.rubocop.yml +3 -2
- data/.rubocop_cc.yml +3 -3
- data/.whitesource +3 -0
- data/CHANGELOG.md +32 -17
- data/Gemfile +3 -3
- data/README.md +6 -10
- data/activerecord-virtual_attributes.gemspec +5 -5
- data/lib/active_record/virtual_attributes/version.rb +1 -1
- data/lib/active_record/virtual_attributes/virtual_arel.rb +56 -12
- data/lib/active_record/virtual_attributes/virtual_delegates.rb +12 -16
- data/lib/active_record/virtual_attributes/virtual_fields.rb +83 -298
- data/lib/active_record/virtual_attributes/virtual_total.rb +3 -7
- data/lib/active_record/virtual_attributes.rb +1 -23
- metadata +20 -26
- data/.travis.yml +0 -30
- data/Appraisals +0 -23
- data/gemfiles/gemfile_50.gemfile +0 -10
- data/gemfiles/gemfile_51.gemfile +0 -10
- data/gemfiles/gemfile_52.gemfile +0 -10
- data/gemfiles/gemfile_60.gemfile +0 -10
- data/lib/active_record/virtual_attributes/arel_groups.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb60079c2b76281f9ace2d7f4a25c9956d9c439c408b6d0df615cb8c4512a31f
|
4
|
+
data.tar.gz: 6eb95ac5ea930cd875c73e8fcfaca826e3f69370417489f9c074c2c90795e71e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0d8221e8ee5ce87f5082c7e3e7b821375e0da1c6109bd772c1ee01fb396de12169c3f6ac53cdddd267d7974785b81ca0047ccf4b0ed43278b79bdb84c2cd557
|
7
|
+
data.tar.gz: 0b980f5df648db206618fd304ac54fd69f84ed53e004226629ddcc389775686934291baaf106cf196b0fe5204107046bf437f6db12b41a632a62dba88c71b0a0
|
data/.codeclimate.yml
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
-
---
|
2
1
|
version: '2'
|
3
2
|
prepare:
|
4
3
|
fetch:
|
5
|
-
- url: https://raw.githubusercontent.com/ManageIQ/
|
4
|
+
- url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/.rubocop_base.yml
|
6
5
|
path: ".rubocop_base.yml"
|
7
|
-
- url: https://raw.githubusercontent.com/ManageIQ/
|
6
|
+
- url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/.rubocop_cc_base.yml
|
8
7
|
path: ".rubocop_cc_base.yml"
|
8
|
+
- url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/styles/base.yml
|
9
|
+
path: styles/base.yml
|
10
|
+
- url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/styles/cc_base.yml
|
11
|
+
path: styles/cc_base.yml
|
9
12
|
checks:
|
10
13
|
argument-count:
|
11
14
|
enabled: false
|
@@ -27,6 +30,5 @@ checks:
|
|
27
30
|
plugins:
|
28
31
|
rubocop:
|
29
32
|
enabled: true
|
30
|
-
|
31
|
-
|
32
|
-
file: ".rubocop_cc.yml"
|
33
|
+
config: ".rubocop_cc.yml"
|
34
|
+
channel: rubocop-0-82
|
@@ -0,0 +1,74 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
ci:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
strategy:
|
9
|
+
matrix:
|
10
|
+
ruby-version:
|
11
|
+
- '2.7'
|
12
|
+
services:
|
13
|
+
postgres:
|
14
|
+
image: postgres:13
|
15
|
+
env:
|
16
|
+
POSTGRES_PASSWORD: password
|
17
|
+
POSTGRES_DB: virtual_attributes
|
18
|
+
ports:
|
19
|
+
- 5432:5432
|
20
|
+
options: >-
|
21
|
+
--health-cmd pg_isready
|
22
|
+
--health-interval 2s
|
23
|
+
--health-timeout 5s
|
24
|
+
--health-retries 5
|
25
|
+
mysql:
|
26
|
+
image: mysql:8.0
|
27
|
+
env:
|
28
|
+
MYSQL_ROOT_PASSWORD: password
|
29
|
+
MYSQL_DATABASE: virtual_attributes
|
30
|
+
ports:
|
31
|
+
- 3306:3306
|
32
|
+
options: >-
|
33
|
+
--health-cmd="mysqladmin ping -h 127.0.0.1 -P 3306 --silent"
|
34
|
+
--health-interval 10s
|
35
|
+
--health-timeout 5s
|
36
|
+
--health-retries 3
|
37
|
+
env:
|
38
|
+
# for the pg cli (psql, pg_isready) and possibly rails
|
39
|
+
PGHOST: localhost
|
40
|
+
PGPORT: 5432
|
41
|
+
PGUSER: postgres
|
42
|
+
PGPASSWORD: password
|
43
|
+
# for the mysql cli (mysql, mysqladmin)
|
44
|
+
MYSQL_HOST: 127.0.0.1
|
45
|
+
MYSQL_PWD: password
|
46
|
+
steps:
|
47
|
+
- uses: actions/checkout@v2
|
48
|
+
- name: Set up Ruby
|
49
|
+
uses: ruby/setup-ruby@v1
|
50
|
+
with:
|
51
|
+
ruby-version: ${{ matrix.ruby-version }}
|
52
|
+
bundler-cache: true
|
53
|
+
- name: Run SQLite tests
|
54
|
+
env:
|
55
|
+
DB: sqlite3
|
56
|
+
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
57
|
+
run: bundle exec rake
|
58
|
+
- name: Run Postgres tests
|
59
|
+
env:
|
60
|
+
DB: pg
|
61
|
+
COLLATE_SYMBOLS: false
|
62
|
+
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
63
|
+
run: bundle exec rake
|
64
|
+
- name: Run MySQL tests
|
65
|
+
env:
|
66
|
+
DB: mysql2
|
67
|
+
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
68
|
+
run: bundle exec rake
|
69
|
+
- if: ${{ github.ref == 'refs/heads/master' && matrix.ruby-version == '2.7' }}
|
70
|
+
name: Report code coverage
|
71
|
+
continue-on-error: true
|
72
|
+
uses: paambaati/codeclimate-action@v3.0.0
|
73
|
+
env:
|
74
|
+
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
data/.rubocop.yml
CHANGED
data/.rubocop_cc.yml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
inherit_from:
|
2
|
-
- .rubocop_base.yml
|
3
|
-
- .rubocop_cc_base.yml
|
4
|
-
- .rubocop_local.yml
|
2
|
+
- ".rubocop_base.yml"
|
3
|
+
- ".rubocop_cc_base.yml"
|
4
|
+
- ".rubocop_local.yml"
|
data/.whitesource
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,29 +1,43 @@
|
|
1
|
-
#
|
1
|
+
# Change Log
|
2
2
|
|
3
|
-
|
4
|
-
a nice looking [Changelog](http://keepachangelog.com).
|
3
|
+
Versioning of this gem follows ActiveRecord versioning, and does not follow SemVer.
|
5
4
|
|
6
|
-
|
5
|
+
e.g.: virtual attributes 6.1.x supports all versions of rails 6.1.
|
7
6
|
|
8
|
-
|
7
|
+
Use the latest version of both this gem and rails where the first 2 digits match.
|
8
|
+
|
9
|
+
## [Unreleased]
|
10
|
+
|
11
|
+
## [6.1.0] - 2022-02-03
|
12
|
+
|
13
|
+
* **BREAKING** Dropped support for Rails 5.0, 5.1, 5.2, 6.0
|
14
|
+
* **BREAKING** This gem will now no longer follow Semantic Versioning,
|
15
|
+
but instead follow Rails' versioning numbers in order to simplify version
|
16
|
+
matches between them both.
|
17
|
+
* Added Rails 6.1 support
|
18
|
+
* Ruby 3.0 compatibility: kwargs, regular expression fixes
|
19
|
+
* changed extension mechanism from `arel_attribute()` to `arel_table[]`
|
20
|
+
* Auto add grouping to virtual attribute arel
|
21
|
+
|
22
|
+
## [3.0.0] - 2020-09-28
|
9
23
|
|
10
24
|
* fix virtual_aggregate to return a consistent 0 when calculating a sum of no records
|
11
25
|
* fix virtual delegate to include the type column when fetching associated models for polymorphism
|
12
26
|
* add virtual_average, virtual_minimum, and virtual_maximum
|
13
27
|
|
14
|
-
##
|
28
|
+
## [2.0.0] - 2020-05-22
|
15
29
|
|
16
30
|
* This is a trivial release, but because it modifies a public interface, the jump makes it look significant.
|
17
|
-
* removed legacy virtual_column parameter support. (it is not ruby 2.7 compatible)
|
31
|
+
* **BREAKING** removed legacy virtual_column parameter support. (it is not ruby 2.7 compatible)
|
18
32
|
* fixed warnings in ruby 2.7
|
19
33
|
|
20
|
-
##
|
34
|
+
## [1.6.0] - 2019-12-02
|
21
35
|
|
22
36
|
* rails 5.2 support
|
23
37
|
* fix Arel#name error
|
24
38
|
* Display deprecation notices for invalid associations (rather than throw an error)
|
25
39
|
|
26
|
-
##
|
40
|
+
## [1.5.0] - 2019-12-02
|
27
41
|
|
28
42
|
* `select()` no longer modifies `select_values`. It understands virtual attributes at a lower level.
|
29
43
|
* `includes()` can now handle all proper values presented.
|
@@ -32,22 +46,22 @@ a nice looking [Changelog](http://keepachangelog.com).
|
|
32
46
|
* rails 6.0 support, (rails 5.2 only fails `habtm` preloading)
|
33
47
|
* ruby 2.6.x support (no longer testing ruby 2.4)
|
34
48
|
|
35
|
-
##
|
49
|
+
## [1.4.0] - 2019-07-13
|
36
50
|
|
37
51
|
* fix includes to include all associations
|
38
52
|
* fix bin/console to now actually run
|
39
53
|
* select no longer munges field attribute
|
40
54
|
* support virtual attributes in left_outer_joins
|
41
55
|
|
42
|
-
##
|
56
|
+
## [1.3.1] - 2019-06-06
|
43
57
|
|
44
58
|
* quote column aliases
|
45
59
|
|
46
|
-
##
|
60
|
+
## [1.3.0] - 2019-05-24
|
47
61
|
|
48
62
|
* Rails 5.2 support
|
49
63
|
|
50
|
-
##
|
64
|
+
## [1.2.0] - 2019-04-23
|
51
65
|
|
52
66
|
* Virtual_delegate :type now specified to avoid rare race conditions with attribute discovery
|
53
67
|
* Delays interpreting delegate until column is used
|
@@ -55,24 +69,25 @@ a nice looking [Changelog](http://keepachangelog.com).
|
|
55
69
|
* More flexible includes. e.g.: Arrays of symbols now work
|
56
70
|
* Raises errors for invalid `includes()` and `:uses`
|
57
71
|
|
58
|
-
##
|
72
|
+
## [1.1.0] - 2019-04-23
|
59
73
|
|
60
74
|
* Add legacy types for `VirtualAttribute::Types`
|
61
75
|
* Fix rails 5.1 bug with `includes()`
|
62
76
|
* Remove reference to `MiqPreloader`
|
63
77
|
|
64
|
-
##
|
78
|
+
## [1.0.0] - 2019-03-05
|
65
79
|
|
66
80
|
* Renamed to activerecord-virtual_attributes
|
67
81
|
* Moved from ManageIQ to own repo
|
68
82
|
* Added support for Rails 5.1
|
69
83
|
|
70
|
-
##
|
84
|
+
## 0.1.0 - 2019-01-17
|
71
85
|
|
72
86
|
* Initial Release
|
73
87
|
* Extracted from ManageIQ/manageiq
|
74
88
|
|
75
|
-
[Unreleased]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/
|
89
|
+
[Unreleased]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v6.1.0...HEAD
|
90
|
+
[6.1.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v3.0.0...v6.1.0
|
76
91
|
[3.0.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v2.0.0...v3.0.0
|
77
92
|
[2.0.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v1.6.0...v2.0.0
|
78
93
|
[1.6.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v1.5.0...v1.6.0
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,20 +1,16 @@
|
|
1
1
|
# VirtualAttributes
|
2
2
|
|
3
|
-
[![
|
3
|
+
[![CI](https://github.com/ManageIQ/activerecord-virtual_attributes/actions/workflows/ci.yaml/badge.svg)](https://github.com/ManageIQ/activerecord-virtual_attributes/actions/workflows/ci.yaml)
|
4
4
|
[![Maintainability](https://api.codeclimate.com/v1/badges/e1a0c26941c00f4edb55/maintainability)](https://codeclimate.com/github/ManageIQ/activerecord-virtual_attributes/maintainability)
|
5
5
|
[![Test Coverage](https://api.codeclimate.com/v1/badges/e1a0c26941c00f4edb55/test_coverage)](https://codeclimate.com/github/ManageIQ/activerecord-virtual_attributes/test_coverage)
|
6
|
-
[![Security](https://hakiri.io/github/ManageIQ/activerecord-virtual_attributes/master.svg)](https://hakiri.io/github/ManageIQ/activerecord-virtual_attributes/master)
|
7
6
|
|
8
|
-
|
7
|
+
VirtualAttributes allows you to define a ruby method that acts like an attribute or relation.
|
9
8
|
|
10
|
-
Sometimes you have a model with an attribute defined in ruby
|
11
|
-
Well, to filter by that attribute, you need to fetch all the rows from the database and filter it in ruby.
|
12
|
-
For large tables, this is slow and takes up a lot of memory
|
9
|
+
Sometimes you have a model with an attribute defined in ruby but you want to sort or filter by it. Filtering by that attribute necessitates fetching all the rows from the database and filtering in ruby. For large tables, this is slow and takes up a lot of memory.
|
13
10
|
|
14
|
-
This gem allows you to represent these
|
11
|
+
This gem allows you to represent these attributes in sql so `ORDER BY` `WHERE` clauses will work.
|
15
12
|
|
16
|
-
This
|
17
|
-
to get rid of the N+1 problem of running a `count(*)` on a subcollection for each row.
|
13
|
+
This also allows you to calculate counts and treat those as a field accessible with `select(:child_count)` to get rid of the N+1 problem of running a `count(*)` on a subcollection for each row.
|
18
14
|
|
19
15
|
## Installation
|
20
16
|
|
@@ -45,7 +41,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
45
41
|
|
46
42
|
To test with different versions of ruby, use `wwtd` gem or
|
47
43
|
|
48
|
-
DB=pg BUNDLE_GEMFILE=gemfiles/gemfile_${version-52}.gemfile
|
44
|
+
DB=pg BUNDLE_GEMFILE=gemfiles/gemfile_${version-52}.gemfile bundle exec rake
|
49
45
|
|
50
46
|
## Contributing
|
51
47
|
|
@@ -25,12 +25,12 @@ Gem::Specification.new do |spec|
|
|
25
25
|
|
26
26
|
spec.require_paths = ["lib"]
|
27
27
|
|
28
|
-
spec.add_runtime_dependency "activerecord", "
|
28
|
+
spec.add_runtime_dependency "activerecord", "~> 6.1.0"
|
29
29
|
|
30
|
-
spec.add_development_dependency "appraisal"
|
31
30
|
spec.add_development_dependency "byebug"
|
32
|
-
spec.add_development_dependency "db-query-matchers"
|
33
|
-
spec.add_development_dependency "
|
31
|
+
spec.add_development_dependency "db-query-matchers"
|
32
|
+
spec.add_development_dependency "manageiq-style"
|
33
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
34
34
|
spec.add_development_dependency "rspec", "~> 3.0"
|
35
|
-
spec.add_development_dependency "simplecov"
|
35
|
+
spec.add_development_dependency "simplecov", ">= 0.21.2"
|
36
36
|
end
|
@@ -9,11 +9,39 @@ module ActiveRecord
|
|
9
9
|
#
|
10
10
|
# Model.select(Model.arel_table.grouping(Model.arel_table[:field2]).as(:field))
|
11
11
|
# Model.attribute_supported_by_sql?(:field) # => true
|
12
|
+
|
13
|
+
# in essence, this is our Arel::Nodes::VirtualAttribute
|
12
14
|
class Arel::Nodes::Grouping
|
13
15
|
attr_accessor :name
|
14
16
|
end
|
15
17
|
|
16
18
|
module VirtualArel
|
19
|
+
# This arel table proxy is our shim to get our functionality into rails
|
20
|
+
class ArelTableProxy < Arel::Table
|
21
|
+
attr_accessor :klass
|
22
|
+
|
23
|
+
# overrides Arel::Table#[]
|
24
|
+
# adds aliases and virtual attribute arel (aka sql)
|
25
|
+
#
|
26
|
+
# @returns Arel::Attributes::Attribute|Arel::Nodes::Grouping|Nil
|
27
|
+
# for regular database columns:
|
28
|
+
# returns an Arel::Attribute (just like Arel::Table#[])
|
29
|
+
# for virtual attributes:
|
30
|
+
# returns the arel for the value
|
31
|
+
# for non sql friendly virtual attributes:
|
32
|
+
# returns nil
|
33
|
+
def [](name, table = self)
|
34
|
+
if (col_alias = @klass.attribute_alias(name))
|
35
|
+
name = col_alias
|
36
|
+
end
|
37
|
+
if @klass.virtual_attribute?(name)
|
38
|
+
@klass.arel_for_virtual_attribute(name, table)
|
39
|
+
else
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
17
45
|
extend ActiveSupport::Concern
|
18
46
|
|
19
47
|
included do
|
@@ -22,20 +50,19 @@ module ActiveRecord
|
|
22
50
|
end
|
23
51
|
|
24
52
|
module ClassMethods
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
super
|
53
|
+
if ActiveRecord.version.to_s < "6.1"
|
54
|
+
# ActiveRecord::Core 6.0 (every version of active record seems to do this differently)
|
55
|
+
def arel_table
|
56
|
+
@arel_table ||= ArelTableProxy.new(table_name, :type_caster => type_caster).tap { |t| t.klass = self }
|
57
|
+
end
|
58
|
+
else
|
59
|
+
# ActiveRecord::Core 6.1
|
60
|
+
def arel_table
|
61
|
+
@arel_table ||= ArelTableProxy.new(table_name, :klass => self)
|
35
62
|
end
|
36
63
|
end
|
37
64
|
|
38
|
-
# supported by sql if
|
65
|
+
# supported by sql if any are true:
|
39
66
|
# - it is an attribute alias
|
40
67
|
# - it is an attribute that is non virtual
|
41
68
|
# - it is an attribute that is virtual and has arel defined
|
@@ -45,9 +72,26 @@ module ActiveRecord
|
|
45
72
|
(has_attribute?(name) && (!virtual_attribute?(name) || !!_virtual_arel[name.to_s]))
|
46
73
|
end
|
47
74
|
|
75
|
+
# private api
|
76
|
+
#
|
77
|
+
# @return [Nil|Arel::Nodes::Grouping]
|
78
|
+
# for virtual attributes:
|
79
|
+
# returns the arel for the column
|
80
|
+
# for non sql friendly virtual attributes:
|
81
|
+
# returns nil
|
82
|
+
def arel_for_virtual_attribute(column_name, table) # :nodoc:
|
83
|
+
arel_lambda = _virtual_arel[column_name.to_s]
|
84
|
+
return unless arel_lambda
|
85
|
+
|
86
|
+
arel = arel_lambda.call(table)
|
87
|
+
arel = Arel::Nodes::Grouping.new(arel) unless arel.kind_of?(Arel::Nodes::Grouping)
|
88
|
+
arel.name = column_name
|
89
|
+
arel
|
90
|
+
end
|
91
|
+
|
48
92
|
private
|
49
93
|
|
50
|
-
def define_virtual_arel(name, arel)
|
94
|
+
def define_virtual_arel(name, arel) # :nodoc:
|
51
95
|
self._virtual_arel = _virtual_arel.merge(name => arel)
|
52
96
|
end
|
53
97
|
end
|
@@ -151,14 +151,9 @@ module ActiveRecord
|
|
151
151
|
# There is currently no way to propagate sql over a virtual association
|
152
152
|
if reflect_on_association(to_ref.name) && (to_ref.macro == :has_one || to_ref.macro == :belongs_to)
|
153
153
|
lambda do |t|
|
154
|
-
|
155
|
-
to_ref.join_keys
|
156
|
-
else
|
157
|
-
to_ref.join_keys(to_ref.klass)
|
158
|
-
end
|
159
|
-
src_model_id = arel_attribute(join_keys.foreign_key, t)
|
154
|
+
src_model_id = arel_table[to_ref.join_foreign_key, t]
|
160
155
|
blk = ->(arel) { arel.limit = 1 } if to_ref.macro == :has_one
|
161
|
-
VirtualDelegates.select_from_alias(to_ref, col,
|
156
|
+
VirtualDelegates.select_from_alias(to_ref, col, to_ref.join_primary_key, src_model_id, &blk)
|
162
157
|
end
|
163
158
|
end
|
164
159
|
end
|
@@ -248,24 +243,25 @@ module ActiveRecord
|
|
248
243
|
to_ref.klass.all
|
249
244
|
end
|
250
245
|
|
251
|
-
src_model
|
252
|
-
to_table
|
253
|
-
to_model_id = to_ref.klass.
|
254
|
-
to_column = to_ref.klass.
|
255
|
-
arel
|
256
|
-
|
257
|
-
|
246
|
+
src_model = to_ref.active_record
|
247
|
+
to_table = select_from_alias_table(to_ref.klass, src_model_id.relation)
|
248
|
+
to_model_id = to_ref.klass.arel_table[to_model_col_name, to_table]
|
249
|
+
to_column = to_ref.klass.arel_table[col, to_table]
|
250
|
+
arel = query.except(:select).select(to_column).arel
|
251
|
+
.from(to_table)
|
252
|
+
.where(to_model_id.eq(src_model_id))
|
258
253
|
|
259
254
|
# :type is in the reflection definition (meaning it is polymorphic)
|
260
255
|
if to_ref.type
|
261
256
|
# get the class name (e.g. "Host")
|
262
257
|
polymorphic_type = src_model.base_class.name
|
263
|
-
arel = arel.where(to_ref.klass.
|
258
|
+
arel = arel.where(to_ref.klass.arel_table[to_ref.type].eq(polymorphic_type))
|
264
259
|
end
|
265
260
|
|
266
261
|
yield arel if block_given?
|
267
262
|
|
268
|
-
|
263
|
+
# convert arel to sql to populate with bind variables
|
264
|
+
::Arel::Nodes::Grouping.new(Arel.sql(arel.to_sql))
|
269
265
|
end
|
270
266
|
|
271
267
|
# determine table reference to use for a sub query
|
@@ -101,242 +101,76 @@ module ActiveRecord
|
|
101
101
|
module Associations
|
102
102
|
class Preloader
|
103
103
|
prepend(Module.new {
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
# preloader.rb active record 6.0
|
137
|
-
# since this deals with polymorphic_parent, it makes everything easier to just define it
|
138
|
-
def preloaders_on(association, records, scope, polymorphic_parent = false)
|
139
|
-
case association
|
140
|
-
when Hash
|
141
|
-
preloaders_for_hash(association, records, scope, polymorphic_parent)
|
142
|
-
when Symbol, String
|
143
|
-
preloaders_for_one(association.to_sym, records, scope, polymorphic_parent)
|
144
|
-
else
|
145
|
-
raise ArgumentError, "#{association.inspect} was not recognized for preload"
|
104
|
+
# preloader.rb active record 6.0
|
105
|
+
# changed:
|
106
|
+
# since grouped_records can return a hash/array, we need to handle those 2 new cases
|
107
|
+
def preloaders_for_reflection(reflection, records, scope, polymorphic_parent)
|
108
|
+
case reflection
|
109
|
+
when Array
|
110
|
+
reflection.flat_map { |ref| preloaders_on(ref, records, scope, polymorphic_parent) }
|
111
|
+
when Hash
|
112
|
+
preloaders_on(reflection, records, scope, polymorphic_parent)
|
113
|
+
else
|
114
|
+
super(reflection, records, scope)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# rubocop:disable Style/BlockDelimiters, Lint/AmbiguousBlockAssociation, Style/MethodCallWithArgsParentheses
|
119
|
+
# preloader.rb active record 6.0
|
120
|
+
# changed:
|
121
|
+
# passing polymorphic around (and makes 5.2 more similar to 6.0)
|
122
|
+
def preloaders_for_hash(association, records, scope, polymorphic_parent)
|
123
|
+
association.flat_map { |parent, child|
|
124
|
+
grouped_records(parent, records, polymorphic_parent).flat_map do |reflection, reflection_records|
|
125
|
+
loaders = preloaders_for_reflection(reflection, reflection_records, scope, polymorphic_parent)
|
126
|
+
recs = loaders.flat_map(&:preloaded_records).uniq
|
127
|
+
child_polymorphic_parent = reflection && reflection.respond_to?(:options) && reflection.options[:polymorphic]
|
128
|
+
loaders.concat Array.wrap(child).flat_map { |assoc|
|
129
|
+
preloaders_on assoc, recs, scope, child_polymorphic_parent
|
130
|
+
}
|
131
|
+
loaders
|
146
132
|
end
|
147
|
-
|
133
|
+
}
|
148
134
|
end
|
149
135
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
grouped_records(parent, records, polymorphic_parent).flat_map do |reflection, reflection_records|
|
158
|
-
loaders = preloaders_for_reflection(reflection, reflection_records, scope, polymorphic_parent)
|
159
|
-
recs = loaders.flat_map(&:preloaded_records).uniq
|
160
|
-
child_polymorphic_parent = reflection && reflection.respond_to?(:options) && reflection.options[:polymorphic]
|
161
|
-
loaders.concat Array.wrap(child).flat_map { |assoc|
|
162
|
-
preloaders_on assoc, recs, scope, child_polymorphic_parent
|
163
|
-
}
|
164
|
-
loaders
|
165
|
-
end
|
166
|
-
}
|
167
|
-
end
|
168
|
-
|
169
|
-
# preloader.rb active record 6.0
|
170
|
-
# changed:
|
171
|
-
# passing polymorphic_parent to preloaders_for_reflection
|
172
|
-
def preloaders_for_one(association, records, scope, polymorphic_parent)
|
173
|
-
grouped_records(association, records, polymorphic_parent)
|
174
|
-
.flat_map do |reflection, reflection_records|
|
175
|
-
preloaders_for_reflection(reflection, reflection_records, scope, polymorphic_parent)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
# preloader.rb active record 6.0
|
180
|
-
# changed:
|
181
|
-
# different from 5.2. But not called outside these redefined methods here, so it works fine
|
182
|
-
# did add compact to fix a 5.2 double preload nil bug
|
183
|
-
def grouped_records(orig_association, records, polymorphic_parent)
|
184
|
-
h = {}
|
185
|
-
records.compact.each do |record|
|
186
|
-
# each class can resolve virtual_{attributes,includes} differently
|
187
|
-
association = record.class.replace_virtual_fields(orig_association)
|
188
|
-
# 1 line optimization for single element array:
|
189
|
-
association = association.first if association.kind_of?(Array) && association.size == 1
|
190
|
-
|
191
|
-
case association
|
192
|
-
when Symbol, String
|
193
|
-
# 4/24/20 we want to revert #67 once we handle all these error cases in our codebase.
|
194
|
-
reflection = record.class._reflect_on_association(association)
|
195
|
-
display_virtual_attribute_deprecation("#{record.class.name}.#{association} does not exist") if !reflection && !polymorphic_parent
|
196
|
-
next if !reflection || !record.association(association).klass
|
197
|
-
when nil
|
198
|
-
next
|
199
|
-
else # need parent (preloaders_for_{hash,one}) to handle this Array/Hash
|
200
|
-
reflection = association
|
201
|
-
end
|
202
|
-
(h[reflection] ||= []) << record
|
203
|
-
end
|
204
|
-
h
|
205
|
-
end
|
206
|
-
# rubocop:enable Style/BlockDelimiters, Lint/AmbiguousBlockAssociation, Style/MethodCallWithArgsParentheses
|
207
|
-
|
208
|
-
def display_virtual_attribute_deprecation(str)
|
209
|
-
short_caller = caller
|
210
|
-
# if debugging is turned on, don't prune the backtrace.
|
211
|
-
# if debugging is off, prune down to the line where the sql is executed
|
212
|
-
# this defaults to false and only displays 1 line number.
|
213
|
-
unless ActiveSupport::Deprecation.debug
|
214
|
-
bc = ActiveSupport::BacktraceCleaner.new
|
215
|
-
bc.add_silencer { |line| line =~ /virtual_fields/ }
|
216
|
-
bc.add_silencer { |line| line =~ /active_record/ }
|
217
|
-
short_caller = bc.clean(caller)
|
136
|
+
# preloader.rb active record 6.0
|
137
|
+
# changed:
|
138
|
+
# passing polymorphic_parent to preloaders_for_reflection
|
139
|
+
def preloaders_for_one(association, records, scope, polymorphic_parent)
|
140
|
+
grouped_records(association, records, polymorphic_parent)
|
141
|
+
.flat_map do |reflection, reflection_records|
|
142
|
+
preloaders_for_reflection(reflection, reflection_records, scope, polymorphic_parent)
|
218
143
|
end
|
144
|
+
end
|
219
145
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
146
|
+
# preloader.rb active record 6.0, 6.1
|
147
|
+
def grouped_records(orig_association, records, polymorphic_parent)
|
148
|
+
h = {}
|
149
|
+
records.each do |record|
|
150
|
+
# The virtual_field lookup can return Symbol/Nil/Other (typically a Hash)
|
151
|
+
# so the case statement and the cases for Nil/Other are new
|
225
152
|
|
226
|
-
#
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
end
|
231
|
-
# /new logic
|
153
|
+
# each class can resolve virtual_{attributes,includes} differently
|
154
|
+
association = record.class.replace_virtual_fields(orig_association)
|
155
|
+
# 1 line optimization for single element array:
|
156
|
+
association = association.first if association.kind_of?(Array) && association.size == 1
|
232
157
|
|
233
|
-
|
234
|
-
|
235
|
-
|
158
|
+
case association
|
159
|
+
when Symbol, String
|
160
|
+
reflection = record.class._reflect_on_association(association)
|
161
|
+
next if polymorphic_parent && !reflection || !record.association(association).klass
|
162
|
+
when nil
|
163
|
+
next
|
164
|
+
else # need parent (preloaders_for_{hash,one}) to handle this Array/Hash
|
165
|
+
reflection = association
|
236
166
|
end
|
237
|
-
|
238
|
-
loaders
|
167
|
+
(h[reflection] ||= []) << record
|
239
168
|
end
|
169
|
+
h
|
240
170
|
end
|
171
|
+
# rubocop:enable Style/BlockDelimiters, Lint/AmbiguousBlockAssociation, Style/MethodCallWithArgsParentheses
|
241
172
|
})
|
242
173
|
end
|
243
|
-
|
244
|
-
# FIXME: Hopefully we can get this into Rails core so this is no longer
|
245
|
-
# required in our codebase, but the rule that are broken here are mostly
|
246
|
-
# due to the style of the Rails codebase conflicting with our own.
|
247
|
-
# Ignoring them to avoid noise in RuboCop, but allow us to keep the same
|
248
|
-
# syntax from the original codebase.
|
249
|
-
#
|
250
|
-
# rubocop:disable Style/BlockDelimiters, Layout/SpaceAfterComma, Style/HashSyntax
|
251
|
-
# rubocop:disable Layout/AlignHash
|
252
|
-
class JoinDependency
|
253
|
-
def instantiate(result_set, *_, &block)
|
254
|
-
primary_key = aliases.column_alias(join_root, join_root.primary_key)
|
255
|
-
|
256
|
-
seen = Hash.new { |i, object_id|
|
257
|
-
i[object_id] = Hash.new { |j, child_class|
|
258
|
-
j[child_class] = {}
|
259
|
-
}
|
260
|
-
}
|
261
|
-
|
262
|
-
model_cache = Hash.new { |h,klass| h[klass] = {} }
|
263
|
-
parents = model_cache[join_root]
|
264
|
-
column_aliases = aliases.column_aliases(join_root)
|
265
|
-
|
266
|
-
# New Code
|
267
|
-
column_aliases += select_values_from_references(column_aliases, result_set) if result_set.present?
|
268
|
-
# End of New Code
|
269
|
-
|
270
|
-
message_bus = ActiveSupport::Notifications.instrumenter
|
271
|
-
|
272
|
-
payload = {
|
273
|
-
record_count: result_set.length,
|
274
|
-
class_name: join_root.base_klass.name
|
275
|
-
}
|
276
|
-
|
277
|
-
message_bus.instrument('instantiation.active_record', payload) do
|
278
|
-
result_set.each { |row_hash|
|
279
|
-
parent_key = primary_key ? row_hash[primary_key] : row_hash
|
280
|
-
parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, &block)
|
281
|
-
if ActiveRecord.version.to_s < "6.0"
|
282
|
-
construct(parent, join_root, row_hash, result_set, seen, model_cache, aliases)
|
283
|
-
else
|
284
|
-
construct(parent, join_root, row_hash, seen, model_cache)
|
285
|
-
end
|
286
|
-
}
|
287
|
-
end
|
288
|
-
|
289
|
-
parents.values
|
290
|
-
end
|
291
|
-
# rubocop:enable Style/BlockDelimiters, Layout/SpaceAfterComma, Style/HashSyntax
|
292
|
-
# rubocop:enable Layout/AlignHash
|
293
|
-
|
294
|
-
#
|
295
|
-
# This monkey patches the ActiveRecord::Associations::JoinDependency to
|
296
|
-
# include columns into the main record that might have been added
|
297
|
-
# through a `select` clause.
|
298
|
-
#
|
299
|
-
# This can be seen with the following:
|
300
|
-
#
|
301
|
-
# Vm.select(Vm.arel_table[Arel.star]).select(:some_vm_virtual_col)
|
302
|
-
# .includes(:tags => {}).references(:tags)
|
303
|
-
#
|
304
|
-
# Which will produce a SQL SELECT statement kind of like this:
|
305
|
-
#
|
306
|
-
# SELECT "vms".*,
|
307
|
-
# (<virtual_attribute_arel>) AS some_vm_virtual_col,
|
308
|
-
# "vms"."id" AS t0_r0
|
309
|
-
# "vms"."vendor" AS t0_r1
|
310
|
-
# "vms"."format" AS t0_r1
|
311
|
-
# "vms"."version" AS t0_r1
|
312
|
-
# ...
|
313
|
-
# "tags"."id" AS t1_r0
|
314
|
-
# "tags"."name" AS t1_r1
|
315
|
-
#
|
316
|
-
# This is because rails is trying to reduce the number of queries
|
317
|
-
# needed to fetch all of the records in the include, so it grabs the
|
318
|
-
# columns for both of the tables together to do it. Unfortunately (or
|
319
|
-
# fortunately... depending on how you look at it), it does not remove
|
320
|
-
# any `.select` columns from the query that is run in the process, so
|
321
|
-
# that is brought along for the ride, but never used when this method
|
322
|
-
# instanciates the objects.
|
323
|
-
#
|
324
|
-
# The "New Code" here simply also instanciates any extra rows that
|
325
|
-
# might have been included in the select (virtual_columns) as well and
|
326
|
-
# brought back with the result set.
|
327
|
-
def select_values_from_references(column_aliases, result_set)
|
328
|
-
join_dep_keys = aliases.columns.map(&:right)
|
329
|
-
join_root_aliases = column_aliases.map(&:first)
|
330
|
-
additional_attributes = result_set.first.keys
|
331
|
-
.reject { |k| join_dep_keys.include?(k) }
|
332
|
-
.reject { |k| join_root_aliases.include?(k) }
|
333
|
-
if ActiveRecord.version.to_s >= "6.0"
|
334
|
-
additional_attributes.map { |k| Aliases::Column.new(k, k) }
|
335
|
-
else
|
336
|
-
additional_attributes.map { |k| [k, k] }
|
337
|
-
end
|
338
|
-
end
|
339
|
-
end
|
340
174
|
end
|
341
175
|
|
342
176
|
class Relation
|
@@ -351,99 +185,50 @@ module ActiveRecord
|
|
351
185
|
|
352
186
|
include(Module.new {
|
353
187
|
# From ActiveRecord::FinderMethods
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
real.apply_join_dependency(*args, &block)
|
361
|
-
end
|
362
|
-
end
|
363
|
-
else
|
364
|
-
def find_with_associations(&block)
|
365
|
-
real = without_virtual_includes
|
366
|
-
if real.equal?(self)
|
367
|
-
super
|
368
|
-
else
|
369
|
-
real.find_with_associations(&block)
|
370
|
-
end
|
188
|
+
def apply_join_dependency(*args, **kargs, &block)
|
189
|
+
real = without_virtual_includes
|
190
|
+
if real.equal?(self)
|
191
|
+
super
|
192
|
+
else
|
193
|
+
real.apply_join_dependency(*args, **kargs, &block)
|
371
194
|
end
|
372
195
|
end
|
373
196
|
|
374
|
-
# From ActiveRecord::QueryMethods (rails 5.2 - 6.
|
197
|
+
# From ActiveRecord::QueryMethods (rails 5.2 - 6.1)
|
375
198
|
def build_select(arel)
|
376
199
|
if select_values.any?
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
end
|
384
|
-
|
385
|
-
# from ActiveRecord::QueryMethods (rails 5.2 - 6.0)
|
386
|
-
def arel_columns(columns, allow_alias = false)
|
387
|
-
columns.flat_map do |field|
|
388
|
-
case field
|
389
|
-
when Symbol
|
390
|
-
arel_column(field.to_s, allow_alias) do |attr_name|
|
391
|
-
connection.quote_table_name(attr_name)
|
200
|
+
cols = arel_columns(select_values.uniq).map do |col|
|
201
|
+
# if it is a virtual attribute, then add aliases to those columns
|
202
|
+
if col.kind_of?(Arel::Nodes::Grouping) && col.name
|
203
|
+
col.as(connection.quote_column_name(col.name))
|
204
|
+
else
|
205
|
+
col
|
392
206
|
end
|
393
|
-
when String
|
394
|
-
arel_column(field, allow_alias, &:itself)
|
395
|
-
when Proc
|
396
|
-
field.call
|
397
|
-
else
|
398
|
-
field
|
399
207
|
end
|
400
|
-
|
401
|
-
end
|
402
|
-
|
403
|
-
# from ActiveRecord::QueryMethods (rails 5.2 - 6.0)
|
404
|
-
def arel_column(field, allow_alias = false, &block)
|
405
|
-
field = klass.attribute_aliases[field] || field
|
406
|
-
from = from_clause.name || from_clause.value
|
407
|
-
|
408
|
-
if klass.columns_hash.key?(field) && (!from || table_name_matches?(from))
|
409
|
-
arel_attribute(field)
|
410
|
-
elsif virtual_attribute?(field)
|
411
|
-
virtual_attribute_arel_column(field, allow_alias, &block)
|
208
|
+
arel.project(*cols)
|
412
209
|
else
|
413
|
-
|
210
|
+
super
|
414
211
|
end
|
415
212
|
end
|
416
213
|
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
elsif allow_alias && arel && arel.respond_to?(:as) && !arel.kind_of?(Arel::Nodes::As) && !arel.try(:alias)
|
422
|
-
arel.as(connection.quote_column_name(field.to_s))
|
423
|
-
else
|
214
|
+
# from ActiveRecord::QueryMethods (rails 5.2 - 6.0)
|
215
|
+
# TODO: remove from rails 7.0
|
216
|
+
def arel_column(field, &block)
|
217
|
+
if virtual_attribute?(field) && (arel = table[field])
|
424
218
|
arel
|
219
|
+
else
|
220
|
+
super
|
425
221
|
end
|
426
222
|
end
|
427
223
|
|
428
|
-
#
|
429
|
-
|
430
|
-
|
431
|
-
end
|
432
|
-
|
433
|
-
# From ActiveRecord::QueryMethods
|
434
|
-
def build_left_outer_joins(manager, outer_joins, *rest)
|
435
|
-
outer_joins = klass.replace_virtual_fields(outer_joins)
|
436
|
-
super if outer_joins.present?
|
224
|
+
def construct_join_dependency(associations, join_type) # :nodoc:
|
225
|
+
associations = klass.replace_virtual_fields(associations)
|
226
|
+
super
|
437
227
|
end
|
438
228
|
|
439
229
|
# From ActiveRecord::Calculations
|
230
|
+
# introduces virtual includes support for calculate (we mostly use COUNT(*))
|
440
231
|
def calculate(operation, attribute_name)
|
441
|
-
if ActiveRecord.version.to_s < "5.1"
|
442
|
-
if (arel = klass.arel_attribute(attribute_name)) && virtual_attribute?(attribute_name)
|
443
|
-
attribute_name = arel
|
444
|
-
end
|
445
|
-
end
|
446
|
-
|
447
232
|
# allow calculate to work with includes and a virtual attribute
|
448
233
|
real = without_virtual_includes
|
449
234
|
return super if real.equal?(self)
|
@@ -119,7 +119,7 @@ module VirtualAttributes
|
|
119
119
|
# need db access for the reflection join_keys, so delaying all this key lookup until call time
|
120
120
|
lambda do |t|
|
121
121
|
# strings and symbols are converted across, arel objects are not
|
122
|
-
column = reflection.klass.
|
122
|
+
column = reflection.klass.arel_table[column] unless column.respond_to?(:count)
|
123
123
|
|
124
124
|
# query: SELECT COUNT(*) FROM main_table JOIN foreign_table ON main_table.id = foreign_table.id JOIN ...
|
125
125
|
relation_query = joins(reflection.name).select(column.send(method_name))
|
@@ -139,11 +139,7 @@ module VirtualAttributes
|
|
139
139
|
|
140
140
|
# convert bind variables from ? to actual values. otherwise, sql is incomplete
|
141
141
|
conn = connection
|
142
|
-
sql
|
143
|
-
conn.unprepared_statement { conn.to_sql(query) }
|
144
|
-
else
|
145
|
-
conn.unprepared_statement { conn.to_sql(query, relation_query.bound_attributes) }
|
146
|
-
end
|
142
|
+
sql = conn.unprepared_statement { conn.to_sql(query) }
|
147
143
|
|
148
144
|
# add () around query
|
149
145
|
query = t.grouping(Arel::Nodes::SqlLiteral.new(sql))
|
@@ -155,4 +151,4 @@ module VirtualAttributes
|
|
155
151
|
end
|
156
152
|
end
|
157
153
|
|
158
|
-
ActiveRecord::Base.
|
154
|
+
ActiveRecord::Base.include VirtualAttributes::VirtualTotal
|
@@ -86,14 +86,7 @@ module ActiveRecord
|
|
86
86
|
def attributes_builder # :nodoc:
|
87
87
|
unless defined?(@attributes_builder) && @attributes_builder
|
88
88
|
defaults = _default_attributes.except(*(column_names - [primary_key]))
|
89
|
-
|
90
|
-
defaults = defaults.except(*virtual_attribute_names)
|
91
|
-
# end change
|
92
|
-
@attributes_builder = if ActiveRecord.version.to_s >= "5.2"
|
93
|
-
ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
|
94
|
-
else
|
95
|
-
ActiveRecord::AttributeSet::Builder.new(attribute_types, defaults)
|
96
|
-
end
|
89
|
+
@attributes_builder = ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
|
97
90
|
end
|
98
91
|
@attributes_builder
|
99
92
|
end
|
@@ -130,22 +123,7 @@ require "active_record/virtual_attributes/virtual_fields"
|
|
130
123
|
# Class extensions
|
131
124
|
#
|
132
125
|
|
133
|
-
# this patch is no longer necessary for 5.2
|
134
|
-
if ActiveRecord.version.to_s < "5.2"
|
135
|
-
require "active_record/attribute"
|
136
|
-
module ActiveRecord
|
137
|
-
# This is a bug in rails 5.0 and 5.1, but it is made much worse by virtual attributes
|
138
|
-
class Attribute
|
139
|
-
def with_value_from_database(value)
|
140
|
-
# self.class.from_database(name, value, type)
|
141
|
-
initialized? ? self.class.from_database(name, value, type) : self
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
126
|
require "active_record/virtual_attributes/virtual_total"
|
148
|
-
require "active_record/virtual_attributes/arel_groups"
|
149
127
|
|
150
128
|
# legacy support for sql types
|
151
129
|
module VirtualAttributes
|
metadata
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-virtual_attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.1.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:
|
11
|
+
date: 2022-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 6.1.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 6.1.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: byebug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: db-query-matchers
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,33 +53,33 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: manageiq-style
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '13.0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '13.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
103
|
+
version: 0.21.2
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
110
|
+
version: 0.21.2
|
111
111
|
description: Define attributes in arel
|
112
112
|
email:
|
113
113
|
- keenan@thebrocks.net
|
@@ -116,14 +116,14 @@ extensions: []
|
|
116
116
|
extra_rdoc_files: []
|
117
117
|
files:
|
118
118
|
- ".codeclimate.yml"
|
119
|
+
- ".github/workflows/ci.yaml"
|
119
120
|
- ".gitignore"
|
120
121
|
- ".rspec"
|
121
122
|
- ".rubocop.yml"
|
122
123
|
- ".rubocop_cc.yml"
|
123
124
|
- ".rubocop_local.yml"
|
124
|
-
- ".
|
125
|
+
- ".whitesource"
|
125
126
|
- ".yamllint"
|
126
|
-
- Appraisals
|
127
127
|
- CHANGELOG.md
|
128
128
|
- Gemfile
|
129
129
|
- LICENSE.txt
|
@@ -132,14 +132,9 @@ files:
|
|
132
132
|
- activerecord-virtual_attributes.gemspec
|
133
133
|
- bin/console
|
134
134
|
- bin/setup
|
135
|
-
- gemfiles/gemfile_50.gemfile
|
136
|
-
- gemfiles/gemfile_51.gemfile
|
137
|
-
- gemfiles/gemfile_52.gemfile
|
138
|
-
- gemfiles/gemfile_60.gemfile
|
139
135
|
- init.rb
|
140
136
|
- lib/active_record-virtual_attributes.rb
|
141
137
|
- lib/active_record/virtual_attributes.rb
|
142
|
-
- lib/active_record/virtual_attributes/arel_groups.rb
|
143
138
|
- lib/active_record/virtual_attributes/rspec.rb
|
144
139
|
- lib/active_record/virtual_attributes/rspec/have_virtual_attribute.rb
|
145
140
|
- lib/active_record/virtual_attributes/version.rb
|
@@ -172,8 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
167
|
- !ruby/object:Gem::Version
|
173
168
|
version: '0'
|
174
169
|
requirements: []
|
175
|
-
|
176
|
-
rubygems_version: 2.7.6.2
|
170
|
+
rubygems_version: 3.3.5
|
177
171
|
signing_key:
|
178
172
|
specification_version: 4
|
179
173
|
summary: Access non-sql attributes from sql
|
data/.travis.yml
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
---
|
2
|
-
sudo: false
|
3
|
-
language: ruby
|
4
|
-
cache: bundler
|
5
|
-
rvm:
|
6
|
-
- 2.5.6
|
7
|
-
- 2.6.4
|
8
|
-
services:
|
9
|
-
- mysql
|
10
|
-
- postgresql
|
11
|
-
env:
|
12
|
-
- DB=mysql2
|
13
|
-
- DB=pg
|
14
|
-
- DB=sqlite3
|
15
|
-
gemfile:
|
16
|
-
- gemfiles/gemfile_50.gemfile
|
17
|
-
- gemfiles/gemfile_51.gemfile
|
18
|
-
- gemfiles/gemfile_52.gemfile
|
19
|
-
- gemfiles/gemfile_60.gemfile
|
20
|
-
before_install:
|
21
|
-
- 'echo ''gem: --no-ri --no-rdoc --no-document'' > ~/.gemrc'
|
22
|
-
before_script:
|
23
|
-
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64
|
24
|
-
> ./cc-test-reporter
|
25
|
-
- chmod +x ./cc-test-reporter
|
26
|
-
- "./cc-test-reporter before-build"
|
27
|
-
- sh -c "if [ '$DB' = 'pg' ]; then psql -c 'DROP DATABASE IF EXISTS virtual_attributes;' ; psql -c ' CREATE DATABASE virtual_attributes;' ; fi"
|
28
|
-
- sh -c "if [ '$DB' = 'mysql2' ]; then mysql -e 'DROP DATABASE IF EXISTS virtual_attributes; CREATE DATABASE virtual_attributes;'; fi"
|
29
|
-
after_script:
|
30
|
-
- "./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT"
|
data/Appraisals
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
%w(5.0.7 5.1.7 5.2.3 6.0.0).each do |ar_version|
|
2
|
-
appraise "gemfile-#{ar_version.split('.').first(2).join}" do
|
3
|
-
gem "activerecord", "~> #{ar_version}"
|
4
|
-
|
5
|
-
if ar_version >= "5.0"
|
6
|
-
gem "mysql2"
|
7
|
-
elsif ar_version >= "4.2"
|
8
|
-
gem "mysql2", "~> 0.4.0"
|
9
|
-
end
|
10
|
-
|
11
|
-
if ar_version >= "5.0"
|
12
|
-
gem "pg"
|
13
|
-
else
|
14
|
-
gem "pg", "0.18.4"
|
15
|
-
end
|
16
|
-
|
17
|
-
if ar_version >= "5.2"
|
18
|
-
gem "sqlite3"
|
19
|
-
else
|
20
|
-
gem "sqlite3", "~> 1.3.13"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/gemfiles/gemfile_50.gemfile
DELETED
data/gemfiles/gemfile_51.gemfile
DELETED
data/gemfiles/gemfile_52.gemfile
DELETED
data/gemfiles/gemfile_60.gemfile
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# this is from https://github.com/rails/arel/pull/435
|
2
|
-
# this allows sorting and where clauses to work with virtual_attribute columns
|
3
|
-
# no longer needed for rails 6.0 and up (change was merged)
|
4
|
-
if ActiveRecord.version.to_s < "6.0" && defined?(Arel::Nodes::Grouping)
|
5
|
-
module Arel
|
6
|
-
module Nodes
|
7
|
-
class Grouping
|
8
|
-
include Arel::Expressions
|
9
|
-
include Arel::AliasPredication
|
10
|
-
include Arel::OrderPredications
|
11
|
-
include Arel::Math
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|