activerecord-virtual_attributes 2.0.0 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ceef88d5be93e1f696e382623d09b421031eae65de7608241b14a943ff5c76c
4
- data.tar.gz: bcf53221633defb009e5dbf739cf2466360c0a00e35bc312dec15d25def7406b
3
+ metadata.gz: 8a35d6c7665469341b76ae68e1a84180ccef887c47f56b7000efc2f0024d0a93
4
+ data.tar.gz: ba57d73a5034e461d3c6bd77a50eb5475d1fe0dab8c3332f91142c893fa736a2
5
5
  SHA512:
6
- metadata.gz: 554b781f47a4fe637bad32ab5c194e4aa364c78dfb5d9a39f8877a3d22ed9c704b4f5ee8312a4220fe07b08eb5a9d4cb3aeb05af200cf0a54af10c4c2052bad4
7
- data.tar.gz: 3feaf1fa331f0e40813591d33f7543cda134acf88e6a70516e8f5aa27c4941c999cfb63ceb2bc86b44bce359daed0ce11f79276f7d832d553f82c754f7206d07
6
+ metadata.gz: 55f8e509034dc3a13dae283733da176c308d25538c38595cebfd98008d07be372c0843752e547be6afb5af361fd1610900f05fc52cdcdfbd8bff834b66233060
7
+ data.tar.gz: c4511ba748f911a985f308bdfa61f9d6c64c57ec1245003dea509205f3aa4e0085f20f7e9adb5674d3657d750c34e6c4d64d41ee5faebb18846c9e8ef3ea4c32
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/guides/master/.rubocop_base.yml
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/guides/master/.rubocop_cc_base.yml
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
- channel: "rubocop-0-67"
31
- config:
32
- file: ".rubocop_cc.yml"
33
+ config: ".rubocop_cc.yml"
34
+ channel: rubocop-0-82
@@ -0,0 +1,69 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+ schedule:
7
+ - cron: '0 0 * * 0'
8
+
9
+ jobs:
10
+ ci:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ ruby-version:
15
+ - '2.7'
16
+ services:
17
+ postgres:
18
+ image: postgres:13
19
+ env:
20
+ POSTGRES_PASSWORD: password
21
+ POSTGRES_DB: virtual_attributes
22
+ options: --health-cmd pg_isready --health-interval 2s --health-timeout 5s --health-retries 5
23
+ ports:
24
+ - 5432:5432
25
+ mysql:
26
+ image: mysql:8.0
27
+ env:
28
+ MYSQL_ROOT_PASSWORD: password
29
+ MYSQL_DATABASE: virtual_attributes
30
+ options: --health-cmd="mysqladmin ping -h 127.0.0.1 -P 3306 --silent" --health-interval 10s --health-timeout 5s --health-retries 3
31
+ ports:
32
+ - 3306:3306
33
+ env:
34
+ CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
35
+ # for the pg cli (psql, pg_isready) and rails
36
+ PGHOST: localhost
37
+ PGPORT: 5432
38
+ PGUSER: postgres
39
+ PGPASSWORD: password
40
+ # for the mysql cli (mysql, mysqladmin)
41
+ MYSQL_HOST: 127.0.0.1
42
+ MYSQL_PWD: password
43
+ steps:
44
+ - uses: actions/checkout@v2
45
+ - name: Set up Ruby
46
+ uses: ruby/setup-ruby@v1
47
+ with:
48
+ ruby-version: ${{ matrix.ruby-version }}
49
+ bundler-cache: true
50
+ timeout-minutes: 30
51
+ - name: Run SQLite tests
52
+ env:
53
+ DB: sqlite3
54
+ run: bundle exec rake
55
+ - name: Run PostgreSQL tests
56
+ env:
57
+ DB: pg
58
+ COLLATE_SYMBOLS: false
59
+ run: bundle exec rake
60
+ - name: Run MySQL tests
61
+ env:
62
+ DB: mysql2
63
+ run: bundle exec rake
64
+ - name: Report code coverage
65
+ if: ${{ github.ref == 'refs/heads/master' && matrix.ruby-version == '2.7' }}
66
+ continue-on-error: true
67
+ uses: paambaati/codeclimate-action@v3.0.0
68
+ env:
69
+ CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
data/.rubocop.yml CHANGED
@@ -1,3 +1,4 @@
1
1
  inherit_from:
2
- - https://raw.githubusercontent.com/ManageIQ/guides/master/.rubocop_base.yml
3
- - .rubocop_local.yml
2
+ - ".rubocop_local.yml"
3
+ inherit_gem:
4
+ manageiq-style: ".rubocop_base.yml"
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
@@ -0,0 +1,3 @@
1
+ {
2
+ "settingsInheritedFrom": "ManageIQ/whitesource-config@master"
3
+ }
data/CHANGELOG.md CHANGED
@@ -1,23 +1,43 @@
1
- # Virtual Attributes Changelog
1
+ # Change Log
2
2
 
3
- Doing our best at supporting [SemVer](http://semver.org/) with
4
- a nice looking [Changelog](http://keepachangelog.com).
3
+ The versioning of this gem follows ActiveRecord versioning, and does not follow SemVer. See the [README](./README.md) for more details.
5
4
 
6
- ## Version [Unreleased] <small>tbd</small>
5
+ ## [Unreleased]
7
6
 
8
- ## Version [2.0.0] <small>2020-05-22</small>
7
+ ## [6.1.1] - 2022-08-09
8
+
9
+ * fix HomogeneousIn clauses [#111](https://github.com/ManageIQ/activerecord-virtual_attributes/pull/111)
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
23
+
24
+ * fix virtual_aggregate to return a consistent 0 when calculating a sum of no records
25
+ * fix virtual delegate to include the type column when fetching associated models for polymorphism
26
+ * add virtual_average, virtual_minimum, and virtual_maximum
27
+
28
+ ## [2.0.0] - 2020-05-22
9
29
 
10
30
  * This is a trivial release, but because it modifies a public interface, the jump makes it look significant.
11
- * 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)
12
32
  * fixed warnings in ruby 2.7
13
33
 
14
- ## Version [1.6.0] <small>2019-12-02</small>
34
+ ## [1.6.0] - 2019-12-02
15
35
 
16
36
  * rails 5.2 support
17
37
  * fix Arel#name error
18
38
  * Display deprecation notices for invalid associations (rather than throw an error)
19
39
 
20
- ## Version [1.5.0] <small>2019-12-02</small>
40
+ ## [1.5.0] - 2019-12-02
21
41
 
22
42
  * `select()` no longer modifies `select_values`. It understands virtual attributes at a lower level.
23
43
  * `includes()` can now handle all proper values presented.
@@ -26,22 +46,22 @@ a nice looking [Changelog](http://keepachangelog.com).
26
46
  * rails 6.0 support, (rails 5.2 only fails `habtm` preloading)
27
47
  * ruby 2.6.x support (no longer testing ruby 2.4)
28
48
 
29
- ## Version [1.4.0] <small>2019-07-13</small>
49
+ ## [1.4.0] - 2019-07-13
30
50
 
31
51
  * fix includes to include all associations
32
52
  * fix bin/console to now actually run
33
53
  * select no longer munges field attribute
34
54
  * support virtual attributes in left_outer_joins
35
55
 
36
- ## Version [1.3.1] <small>2019-06-06</small>
56
+ ## [1.3.1] - 2019-06-06
37
57
 
38
58
  * quote column aliases
39
59
 
40
- ## Version [1.3.0] <small>2019-05-24</small>
60
+ ## [1.3.0] - 2019-05-24
41
61
 
42
62
  * Rails 5.2 support
43
63
 
44
- ## Version [1.2.0] <small>2019-04-23</small>
64
+ ## [1.2.0] - 2019-04-23
45
65
 
46
66
  * Virtual_delegate :type now specified to avoid rare race conditions with attribute discovery
47
67
  * Delays interpreting delegate until column is used
@@ -49,24 +69,27 @@ a nice looking [Changelog](http://keepachangelog.com).
49
69
  * More flexible includes. e.g.: Arrays of symbols now work
50
70
  * Raises errors for invalid `includes()` and `:uses`
51
71
 
52
- ## Version [1.1.0] <small>2019-04-23</small>
72
+ ## [1.1.0] - 2019-04-23
53
73
 
54
74
  * Add legacy types for `VirtualAttribute::Types`
55
75
  * Fix rails 5.1 bug with `includes()`
56
76
  * Remove reference to `MiqPreloader`
57
77
 
58
- ## Version [1.0.0] <small>2019-03-05</small>
78
+ ## [1.0.0] - 2019-03-05
59
79
 
60
80
  * Renamed to activerecord-virtual_attributes
61
81
  * Moved from ManageIQ to own repo
62
82
  * Added support for Rails 5.1
63
83
 
64
- ## Version 0.1.0 <small>2019-01-17</small>
84
+ ## 0.1.0 - 2019-01-17
65
85
 
66
86
  * Initial Release
67
87
  * Extracted from ManageIQ/manageiq
68
88
 
69
- [Unreleased]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v2.0.0...HEAD
89
+ [Unreleased]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v6.1.1...HEAD
90
+ [6.1.1]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v6.1.0...v6.1.1
91
+ [6.1.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v3.0.0...v6.1.0
92
+ [3.0.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v2.0.0...v3.0.0
70
93
  [2.0.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v1.6.0...v2.0.0
71
94
  [1.6.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v1.5.0...v1.6.0
72
95
  [1.5.0]: https://github.com/ManageIQ/activerecord-virtual_attributes/compare/v1.4.0...v1.5.0
data/Gemfile CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "~> 5.0.7"
6
- gem "mysql2", '~> 0.4.0'
5
+ gem "activerecord", "~> 6.1.4"
6
+ gem "mysql2"
7
7
  gem "pg"
8
- gem "sqlite3", "~> 1.3.6"
8
+ gem "sqlite3"
9
9
 
10
10
  gemspec
data/README.md CHANGED
@@ -1,20 +1,22 @@
1
1
  # VirtualAttributes
2
2
 
3
- [![Build Status](https://travis-ci.org/ManageIQ/activerecord-virtual_attributes.svg?branch=master)](https://travis-ci.org/ManageIQ/activerecord-virtual_attributes)
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
- This allows you to define a ruby method that acts like an attribute or relation.
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, but you want to sort by it or filter by it.
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 attribute in sql so `ORDER BY` `WHERE` clauses will work.
11
+ This gem allows you to represent these attributes in sql so `ORDER BY` `WHERE` clauses will work.
15
12
 
16
- This gem also allows you to calculate counts, and treat those counts as a field accessible with `select(:child_count)`
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.
14
+
15
+ ## Versioning
16
+
17
+ As of v6.1.0, the versioning of this gem follows ActiveRecord versioning, and does not follow SemVer (e.g. virtual attributes v6.1.x supports all versions of Rails 6.1). Version v3.0.0 supports Rails 6.0 and lower.
18
+
19
+ Use the latest version of both this gem and Rails where the first 2 digits match.
18
20
 
19
21
  ## Installation
20
22
 
@@ -45,7 +47,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
45
47
 
46
48
  To test with different versions of ruby, use `wwtd` gem or
47
49
 
48
- DB=pg BUNDLE_GEMFILE=gemfiles/gemfile_${version-52}.gemfile beer "$@"
50
+ DB=pg BUNDLE_GEMFILE=gemfiles/gemfile_${version-52}.gemfile bundle exec rake
49
51
 
50
52
  ## Contributing
51
53
 
@@ -25,11 +25,12 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.require_paths = ["lib"]
27
27
 
28
- spec.add_runtime_dependency "activerecord", ">= 5.0"
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 "rake", "~> 10.0"
31
+ spec.add_development_dependency "db-query-matchers"
32
+ spec.add_development_dependency "manageiq-style"
33
+ spec.add_development_dependency "rake", "~> 13.0"
33
34
  spec.add_development_dependency "rspec", "~> 3.0"
34
- spec.add_development_dependency "simplecov"
35
+ spec.add_development_dependency "simplecov", ">= 0.21.2"
35
36
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module VirtualAttributes
3
- VERSION = "2.0.0".freeze
3
+ VERSION = "6.1.1".freeze
4
4
  end
5
5
  end
@@ -9,11 +9,59 @@ 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
- attr_accessor :name
15
+ attr_accessor :name, :relation
16
+
17
+ # methods from Arel::Nodes::Attribute
18
+ def type_caster
19
+ relation.type_for_attribute(name)
20
+ end
21
+
22
+ # Create a node for lowering this attribute
23
+ def lower
24
+ relation.lower(self)
25
+ end
26
+
27
+ def type_cast_for_database(value)
28
+ relation.type_cast_for_database(name, value)
29
+ end
30
+
31
+ # rubocop:disable Rails/Delegate
32
+ def able_to_type_cast?
33
+ relation.able_to_type_cast?
34
+ end
35
+ # rubocop:enable Rails/Delegate
14
36
  end
15
37
 
16
38
  module VirtualArel
39
+ # This arel table proxy is our shim to get our functionality into rails
40
+ class ArelTableProxy < Arel::Table
41
+ attr_accessor :klass
42
+
43
+ # overrides Arel::Table#[]
44
+ # adds aliases and virtual attribute arel (aka sql)
45
+ #
46
+ # @returns Arel::Attributes::Attribute|Arel::Nodes::Grouping|Nil
47
+ # for regular database columns:
48
+ # returns an Arel::Attribute (just like Arel::Table#[])
49
+ # for virtual attributes:
50
+ # returns the arel for the value
51
+ # for non sql friendly virtual attributes:
52
+ # returns nil
53
+ def [](name, table = self)
54
+ if (col_alias = @klass.attribute_alias(name))
55
+ name = col_alias
56
+ end
57
+ if @klass.virtual_attribute?(name)
58
+ @klass.arel_for_virtual_attribute(name, table)
59
+ else
60
+ super
61
+ end
62
+ end
63
+ end
64
+
17
65
  extend ActiveSupport::Concern
18
66
 
19
67
  included do
@@ -22,20 +70,19 @@ module ActiveRecord
22
70
  end
23
71
 
24
72
  module ClassMethods
25
- def arel_attribute(column_name, arel_table = self.arel_table)
26
- load_schema
27
- if virtual_attribute?(column_name) && !attribute_alias?(column_name)
28
- if (col = _virtual_arel[column_name.to_s])
29
- arel = col.call(arel_table)
30
- arel.name = column_name if arel.kind_of?(Arel::Nodes::Grouping)
31
- arel
32
- end
33
- else
34
- super
73
+ if ActiveRecord.version.to_s < "6.1"
74
+ # ActiveRecord::Core 6.0 (every version of active record seems to do this differently)
75
+ def arel_table
76
+ @arel_table ||= ArelTableProxy.new(table_name, :type_caster => type_caster).tap { |t| t.klass = self }
77
+ end
78
+ else
79
+ # ActiveRecord::Core 6.1
80
+ def arel_table
81
+ @arel_table ||= ArelTableProxy.new(table_name, :klass => self)
35
82
  end
36
83
  end
37
84
 
38
- # supported by sql if
85
+ # supported by sql if any are true:
39
86
  # - it is an attribute alias
40
87
  # - it is an attribute that is non virtual
41
88
  # - it is an attribute that is virtual and has arel defined
@@ -45,12 +92,70 @@ module ActiveRecord
45
92
  (has_attribute?(name) && (!virtual_attribute?(name) || !!_virtual_arel[name.to_s]))
46
93
  end
47
94
 
95
+ # private api
96
+ #
97
+ # @return [Nil|Arel::Nodes::Grouping]
98
+ # for virtual attributes:
99
+ # returns the arel for the column
100
+ # for non sql friendly virtual attributes:
101
+ # returns nil
102
+ def arel_for_virtual_attribute(column_name, table) # :nodoc:
103
+ arel_lambda = _virtual_arel[column_name.to_s]
104
+ return unless arel_lambda
105
+
106
+ arel = arel_lambda.call(table)
107
+ arel = Arel::Nodes::Grouping.new(arel) unless arel.kind_of?(Arel::Nodes::Grouping)
108
+ arel.name = column_name
109
+ arel.relation = table
110
+ arel
111
+ end
112
+
48
113
  private
49
114
 
50
- def define_virtual_arel(name, arel)
115
+ def define_virtual_arel(name, arel) # :nodoc:
51
116
  self._virtual_arel = _virtual_arel.merge(name => arel)
52
117
  end
53
118
  end
54
119
  end
55
120
  end
56
121
  end
122
+
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
@@ -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
- join_keys = if ActiveRecord.version.to_s >= "5.1"
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, join_keys.key, src_model_id, &blk)
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
@@ -240,6 +235,7 @@ module ActiveRecord
240
235
  # (SELECT "vms_sub"."name" FROM "vms" AS "vms_ss" WHERE "vms_ss"."id" = "vms"."src_template_id")
241
236
  #
242
237
 
238
+ # Based upon ActiveRecord AssociationScope.scope
243
239
  def self.select_from_alias(to_ref, col, to_model_col_name, src_model_id)
244
240
  query = if to_ref.scope
245
241
  to_ref.klass.instance_exec(nil, &to_ref.scope)
@@ -247,16 +243,25 @@ module ActiveRecord
247
243
  to_ref.klass.all
248
244
  end
249
245
 
250
- to_table = select_from_alias_table(to_ref.klass, src_model_id.relation)
251
- to_model_id = to_ref.klass.arel_attribute(to_model_col_name, to_table)
252
- to_column = to_ref.klass.arel_attribute(col, to_table)
253
- arel = query.except(:select).select(to_column).arel
254
- .from(to_table)
255
- .where(to_model_id.eq(src_model_id))
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))
253
+
254
+ # :type is in the reflection definition (meaning it is polymorphic)
255
+ if to_ref.type
256
+ # get the class name (e.g. "Host")
257
+ polymorphic_type = src_model.base_class.name
258
+ arel = arel.where(to_ref.klass.arel_table[to_ref.type].eq(polymorphic_type))
259
+ end
256
260
 
257
261
  yield arel if block_given?
258
262
 
259
- Arel.sql("(#{arel.to_sql})")
263
+ # convert arel to sql to populate with bind variables
264
+ ::Arel::Nodes::Grouping.new(Arel.sql(arel.to_sql))
260
265
  end
261
266
 
262
267
  # determine table reference to use for a sub query