ransack 1.8.8 → 1.8.9
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/.travis.yml +9 -1
- data/CHANGELOG.md +4 -0
- data/Gemfile +3 -6
- data/README.md +37 -0
- data/lib/polyamorous.rb +55 -0
- data/lib/polyamorous/activerecord_3_and_4.0_ruby_1.9/join_association.rb +76 -0
- data/lib/polyamorous/activerecord_3_and_4.0_ruby_1.9/join_dependency.rb +96 -0
- data/lib/polyamorous/activerecord_4.1_ruby_1.9/join_association.rb +2 -0
- data/lib/polyamorous/activerecord_4.1_ruby_1.9/join_dependency.rb +4 -0
- data/lib/polyamorous/activerecord_4.1_ruby_2/join_association.rb +2 -0
- data/lib/polyamorous/activerecord_4.1_ruby_2/join_dependency.rb +3 -0
- data/lib/polyamorous/activerecord_4.1_ruby_2/make_polyamorous_inner_joins.rb +14 -0
- data/lib/polyamorous/activerecord_4.2_ruby_1.9/join_association.rb +46 -0
- data/lib/polyamorous/activerecord_4.2_ruby_1.9/join_dependency.rb +87 -0
- data/lib/polyamorous/activerecord_4.2_ruby_2/join_association.rb +2 -0
- data/lib/polyamorous/activerecord_4.2_ruby_2/join_dependency.rb +24 -0
- data/lib/polyamorous/activerecord_5.0_ruby_2/join_association.rb +2 -0
- data/lib/polyamorous/activerecord_5.0_ruby_2/join_dependency.rb +2 -0
- data/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb +39 -0
- data/lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb +130 -0
- data/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb +39 -0
- data/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb +131 -0
- data/lib/polyamorous/join.rb +70 -0
- data/lib/polyamorous/swapping_reflection_class.rb +11 -0
- data/lib/polyamorous/tree_node.rb +7 -0
- data/lib/ransack/adapters/active_record/3.0/compat.rb +1 -7
- data/lib/ransack/adapters/mongoid/ransack/nodes/condition.rb +3 -8
- data/lib/ransack/adapters/mongoid/ransack/visitor.rb +1 -7
- data/lib/ransack/helpers/form_builder.rb +14 -8
- data/lib/ransack/locale/az.yml +70 -0
- data/lib/ransack/nodes/grouping.rb +1 -5
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +1 -7
- data/ransack.gemspec +3 -5
- data/spec/helpers/polyamorous_helper.rb +26 -0
- data/spec/ransack/join_association_spec.rb +54 -0
- data/spec/ransack/join_dependency_spec.rb +102 -0
- data/spec/ransack/join_spec.rb +19 -0
- data/spec/spec_helper.rb +1 -0
- metadata +51 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 07c532ea4c1ef918e082ef7877a6fe08fb1bb881860ab28223c3c88da1143883
|
4
|
+
data.tar.gz: 6313bf0d848b95b5eb4d6b653c19dbc88a119da2e5d4979b6fcc2ee9a466d00b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e3a42c855d5e1918ed5dfb71e80d236cd5ac8b8e7b9a46d42d0b181e68ac1a6518a9f61f21f844175db2dba97dd66117a356e8a6feba1a8779f6eedc0cb13dc
|
7
|
+
data.tar.gz: b8d4bb5978ca13683932922a1ac80a619d2890f871ed56f11743e0aba863a229af33eb7ddf617650fb04fab7548c55703d73ddd77c9ef72fa6a5c34801d73c74
|
data/.travis.yml
CHANGED
@@ -11,6 +11,10 @@ env:
|
|
11
11
|
- RAILS=5-2-stable DB=mysql
|
12
12
|
- RAILS=5-2-stable DB=postgres
|
13
13
|
|
14
|
+
- RAILS=v5.2.0 DB=sqlite3
|
15
|
+
- RAILS=v5.2.0 DB=mysql
|
16
|
+
- RAILS=v5.2.0 DB=postgres
|
17
|
+
|
14
18
|
- RAILS=5-0-stable DB=sqlite3
|
15
19
|
- RAILS=5-0-stable DB=mysql
|
16
20
|
- RAILS=5-0-stable DB=postgres
|
@@ -18,7 +22,11 @@ env:
|
|
18
22
|
- RAILS=4-2-stable DB=sqlite3
|
19
23
|
- RAILS=4-2-stable DB=mysql
|
20
24
|
- RAILS=4-2-stable DB=postgres
|
21
|
-
|
25
|
+
matrix:
|
26
|
+
allow_failures:
|
27
|
+
- env: RAILS=5-2-stable DB=sqlite3
|
28
|
+
- env: RAILS=5-2-stable DB=mysql
|
29
|
+
- env: RAILS=5-2-stable DB=postgres
|
22
30
|
before_script:
|
23
31
|
- mysql -e 'create database ransack collate utf8_general_ci;'
|
24
32
|
- mysql -e 'use ransack;show variables like "%character%";show variables like "%collation%";'
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
@@ -5,12 +5,6 @@ gem 'rake'
|
|
5
5
|
|
6
6
|
rails = ENV['RAILS'] || '5-0-stable'
|
7
7
|
|
8
|
-
if rails == 'master'
|
9
|
-
gem 'polyamorous', github: 'activerecord-hackery/polyamorous'
|
10
|
-
else
|
11
|
-
gem 'polyamorous', '~> 1.3'
|
12
|
-
end
|
13
|
-
|
14
8
|
gem 'pry'
|
15
9
|
|
16
10
|
# Provide timezone information on Windows
|
@@ -28,6 +22,9 @@ when /^v/ # A tagged version
|
|
28
22
|
gem 'activerecord', require: false
|
29
23
|
gem 'actionpack'
|
30
24
|
end
|
25
|
+
if rails == 'v5.2.0'
|
26
|
+
gem 'mysql2', '~> 0.4.4'
|
27
|
+
end
|
31
28
|
else
|
32
29
|
git 'git://github.com/rails/rails.git', :branch => rails do
|
33
30
|
gem 'activesupport'
|
data/README.md
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
# Ransack
|
2
2
|
|
3
|
+
### Maintainer Wanted
|
4
|
+
|
5
|
+
A note from [Sean](https://github.com/seanfcarroll).
|
6
|
+
Ransack is a fantastic gem, and a key part of many Rails projects. It is also a core component of [ActiveAdmin](https://github.com/activeadmin/activeadmin) and generally a great way to add fairly complex search and filtering without having to resort to external services, such as Elasticsearch.
|
7
|
+
|
8
|
+
In my humble opinion, Ransack can be much more, if it does a bit less. What I mean is that the API vector of Ransack is quite large, and really has been issue-driven. There are complications with Polymorphic relations, complex joins and MongoDB. It's not clear sometimes if there is a bug or not.
|
9
|
+
|
10
|
+
I was hoping to lead Ransack to version 2.0, and in my opinion this would have included:
|
11
|
+
|
12
|
+
- Absorbing Polyamorous
|
13
|
+
- Splitting MongoDB support into a seperate gem
|
14
|
+
- Dropping support for older Rails versions; strictly follow the [Rails support policy](http://guides.rubyonrails.org/maintenance_policy.html). This is important as the codebase is littered with code for de-supported Rails versions
|
15
|
+
- Add a generator to build in Ransack with a scaffold
|
16
|
+
- Generate tests for Ransack-enabled applications
|
17
|
+
- Update the Wiki / docs with lots of examples of 'how-to', questions are the majority of issues on Ransack
|
18
|
+
- Increase supported translations
|
19
|
+
|
20
|
+
Unfortunately I am quite occupied at present with several projects, including [crowdAI](https://github.com/crowdAI/crowdai), and I will need to step down as a maintainer. I have also posted it [here](https://github.com/pickhardt/maintainers-wanted).
|
21
|
+
|
22
|
+
If you want to step up, please contact me on gmail as **sfcarroll**
|
23
|
+
|
24
|
+
|
25
|
+
|
3
26
|
[](https://travis-ci.org/activerecord-hackery/ransack)
|
4
27
|
[](http://badge.fury.io/rb/ransack)
|
5
28
|
[](https://codeclimate.com/github/activerecord-hackery/ransack)
|
@@ -513,6 +536,20 @@ def index
|
|
513
536
|
end
|
514
537
|
```
|
515
538
|
|
539
|
+
Another method to approach this when using Postgresql is to use ActiveRecords's `.includes` in combination with `.group` instead of `distinct: true`.
|
540
|
+
|
541
|
+
For example:
|
542
|
+
```ruby
|
543
|
+
def index
|
544
|
+
@q = Person.ransack(params[:q])
|
545
|
+
@people = @q.result
|
546
|
+
.group('persons.id')
|
547
|
+
.includes(:articles)
|
548
|
+
.page(params[:page])
|
549
|
+
end
|
550
|
+
|
551
|
+
```
|
552
|
+
|
516
553
|
A final way of last resort is to call `to_a.uniq` on the collection at the end
|
517
554
|
with the caveat that the de-duping is taking place in Ruby instead of in SQL,
|
518
555
|
which is potentially slower and uses more memory, and that it may display
|
data/lib/polyamorous.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
if defined?(::ActiveRecord)
|
2
|
+
module Polyamorous
|
3
|
+
if defined?(Arel::InnerJoin)
|
4
|
+
InnerJoin = Arel::InnerJoin
|
5
|
+
OuterJoin = Arel::OuterJoin
|
6
|
+
else
|
7
|
+
InnerJoin = Arel::Nodes::InnerJoin
|
8
|
+
OuterJoin = Arel::Nodes::OuterJoin
|
9
|
+
end
|
10
|
+
|
11
|
+
if defined?(::ActiveRecord::Associations::JoinDependency)
|
12
|
+
JoinDependency = ::ActiveRecord::Associations::JoinDependency
|
13
|
+
JoinAssociation = ::ActiveRecord::Associations::JoinDependency::JoinAssociation
|
14
|
+
JoinBase = ::ActiveRecord::Associations::JoinDependency::JoinBase
|
15
|
+
else
|
16
|
+
JoinDependency = ::ActiveRecord::Associations::ClassMethods::JoinDependency
|
17
|
+
JoinAssociation = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation
|
18
|
+
JoinBase = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinBase
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'polyamorous/tree_node'
|
23
|
+
require 'polyamorous/join'
|
24
|
+
require 'polyamorous/swapping_reflection_class'
|
25
|
+
|
26
|
+
ar_version = ::ActiveRecord::VERSION::STRING[0,3]
|
27
|
+
ar_version = '3_and_4.0' if ar_version < '4.1'
|
28
|
+
ar_version = ::ActiveRecord::VERSION::STRING[0,5] if ar_version == '5.2'
|
29
|
+
|
30
|
+
method, ruby_version =
|
31
|
+
if RUBY_VERSION >= '2.0' && ar_version >= '4.1'
|
32
|
+
# Ruby 2; we can use `prepend` to patch Active Record cleanly.
|
33
|
+
[:prepend, '2']
|
34
|
+
else
|
35
|
+
# Ruby 1.9; we must use `alias_method` to patch Active Record.
|
36
|
+
[:include, '1.9']
|
37
|
+
end
|
38
|
+
|
39
|
+
%w(join_association join_dependency).each do |file|
|
40
|
+
require "polyamorous/activerecord_#{ar_version}_ruby_#{ruby_version}/#{file}"
|
41
|
+
end
|
42
|
+
|
43
|
+
Polyamorous::JoinDependency.send(method, Polyamorous::JoinDependencyExtensions)
|
44
|
+
if method == :prepend
|
45
|
+
Polyamorous::JoinDependency.singleton_class
|
46
|
+
.send(:prepend, Polyamorous::JoinDependencyExtensions::ClassMethods)
|
47
|
+
end
|
48
|
+
Polyamorous::JoinAssociation.send(method, Polyamorous::JoinAssociationExtensions)
|
49
|
+
|
50
|
+
Polyamorous::JoinBase.class_eval do
|
51
|
+
if method_defined?(:active_record)
|
52
|
+
alias_method :base_klass, :active_record
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# active_record_3_and_4.0_ruby_1.9/join_association.rb
|
2
|
+
module Polyamorous
|
3
|
+
module JoinAssociationExtensions
|
4
|
+
include SwappingReflectionClass
|
5
|
+
def self.included(base)
|
6
|
+
base.class_eval do
|
7
|
+
alias_method_chain :initialize, :polymorphism
|
8
|
+
alias_method :equality_without_polymorphism, :==
|
9
|
+
alias_method :==, :equality_with_polymorphism
|
10
|
+
if base.method_defined?(:active_record)
|
11
|
+
alias_method :base_klass, :active_record
|
12
|
+
end
|
13
|
+
|
14
|
+
if ActiveRecord::VERSION::STRING =~ /^3\.0\./
|
15
|
+
alias_method_chain :association_join, :polymorphism
|
16
|
+
else
|
17
|
+
alias_method_chain :build_constraint, :polymorphism
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize_with_polymorphism(
|
23
|
+
reflection, join_dependency, parent = nil, polymorphic_class = nil
|
24
|
+
)
|
25
|
+
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
|
26
|
+
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
|
27
|
+
initialize_without_polymorphism(reflection, join_dependency, parent)
|
28
|
+
self.reflection.options[:polymorphic] = true
|
29
|
+
end
|
30
|
+
else
|
31
|
+
initialize_without_polymorphism(reflection, join_dependency, parent)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def equality_with_polymorphism(other)
|
36
|
+
equality_without_polymorphism(other) && base_klass == other.base_klass
|
37
|
+
end
|
38
|
+
|
39
|
+
def build_constraint_with_polymorphism(
|
40
|
+
reflection, table, key, foreign_table, foreign_key
|
41
|
+
)
|
42
|
+
if reflection.options[:polymorphic]
|
43
|
+
build_constraint_without_polymorphism(
|
44
|
+
reflection, table, key, foreign_table, foreign_key
|
45
|
+
)
|
46
|
+
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
|
47
|
+
else
|
48
|
+
build_constraint_without_polymorphism(
|
49
|
+
reflection, table, key, foreign_table, foreign_key
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def association_join_with_polymorphism
|
55
|
+
return @join if @Join
|
56
|
+
@join = association_join_without_polymorphism
|
57
|
+
if reflection.macro == :belongs_to && reflection.options[:polymorphic]
|
58
|
+
aliased_table = Arel::Table.new(
|
59
|
+
table_name,
|
60
|
+
as: @aliased_table_name,
|
61
|
+
engine: arel_engine,
|
62
|
+
columns: klass.columns
|
63
|
+
)
|
64
|
+
parent_table = Arel::Table.new(
|
65
|
+
parent.table_name,
|
66
|
+
as: parent.aliased_table_name,
|
67
|
+
engine: arel_engine,
|
68
|
+
columns: parent.base_klass.columns
|
69
|
+
)
|
70
|
+
@join << parent_table[reflection.options[:foreign_type]]
|
71
|
+
.eq(reflection.klass.name)
|
72
|
+
end
|
73
|
+
@join
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# active_record_3_and_4.0_ruby_1.9/join_dependency.rb
|
2
|
+
module Polyamorous
|
3
|
+
module JoinDependencyExtensions
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
alias_method_chain :build, :polymorphism
|
7
|
+
alias_method_chain :graft, :polymorphism
|
8
|
+
if base.method_defined?(:active_record)
|
9
|
+
alias_method :base_klass, :active_record
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def graft_with_polymorphism(*associations)
|
15
|
+
associations.each do |association|
|
16
|
+
unless join_associations.detect { |a| association == a }
|
17
|
+
if association.reflection.options[:polymorphic]
|
18
|
+
build(
|
19
|
+
Join.new(
|
20
|
+
association.reflection.name,
|
21
|
+
association.join_type,
|
22
|
+
association.reflection.klass
|
23
|
+
),
|
24
|
+
association.find_parent_in(self) || join_base,
|
25
|
+
association.join_type
|
26
|
+
)
|
27
|
+
else
|
28
|
+
build(
|
29
|
+
association.reflection.name,
|
30
|
+
association.find_parent_in(self) || join_base,
|
31
|
+
association.join_type
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
if ActiveRecord::VERSION::STRING =~ /^3\.0\./
|
40
|
+
def _join_parts
|
41
|
+
@joins
|
42
|
+
end
|
43
|
+
else
|
44
|
+
def _join_parts
|
45
|
+
@join_parts
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def build_with_polymorphism(
|
50
|
+
associations, parent = nil, join_type = InnerJoin
|
51
|
+
)
|
52
|
+
case associations
|
53
|
+
when Join
|
54
|
+
parent ||= _join_parts.last
|
55
|
+
reflection = parent.reflections[associations.name] or
|
56
|
+
raise ::ActiveRecord::ConfigurationError,
|
57
|
+
"Association named '#{associations.name
|
58
|
+
}' was not found; perhaps you misspelled it?"
|
59
|
+
|
60
|
+
unless join_association = find_join_association_respecting_polymorphism(
|
61
|
+
reflection, parent, associations.klass
|
62
|
+
)
|
63
|
+
@reflections << reflection
|
64
|
+
join_association = build_join_association_respecting_polymorphism(
|
65
|
+
reflection, parent, associations.klass
|
66
|
+
)
|
67
|
+
join_association.join_type = associations.type
|
68
|
+
_join_parts << join_association
|
69
|
+
cache_joined_association(join_association)
|
70
|
+
end
|
71
|
+
|
72
|
+
join_association
|
73
|
+
else
|
74
|
+
build_without_polymorphism(associations, parent, join_type)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def find_join_association_respecting_polymorphism(reflection, parent, klass)
|
79
|
+
if association = find_join_association(reflection, parent)
|
80
|
+
unless reflection.options[:polymorphic]
|
81
|
+
association
|
82
|
+
else
|
83
|
+
association if association.base_klass == klass
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def build_join_association_respecting_polymorphism(reflection, parent, klass)
|
89
|
+
if reflection.options[:polymorphic] && klass
|
90
|
+
JoinAssociation.new(reflection, self, parent, klass)
|
91
|
+
else
|
92
|
+
JoinAssociation.new(reflection, self, parent)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Polyamorous
|
2
|
+
module JoinDependencyExtensions
|
3
|
+
# Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins
|
4
|
+
#
|
5
|
+
def make_polyamorous_inner_joins(parent, child)
|
6
|
+
make_constraints(
|
7
|
+
parent, child, child.tables, child.join_type || Arel::Nodes::InnerJoin
|
8
|
+
)
|
9
|
+
.concat child.children.flat_map { |c|
|
10
|
+
make_polyamorous_inner_joins(child, c)
|
11
|
+
}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# active_record_4.2_ruby_1.9/join_association.rb
|
2
|
+
module Polyamorous
|
3
|
+
module JoinAssociationExtensions
|
4
|
+
include SwappingReflectionClass
|
5
|
+
def self.included(base)
|
6
|
+
base.class_eval do
|
7
|
+
attr_reader :join_type
|
8
|
+
alias_method_chain :initialize, :polymorphism
|
9
|
+
alias_method_chain :build_constraint, :polymorphism
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize_with_polymorphism(reflection, children,
|
14
|
+
polymorphic_class = nil, join_type = Arel::Nodes::InnerJoin)
|
15
|
+
@join_type = join_type
|
16
|
+
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
|
17
|
+
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
|
18
|
+
initialize_without_polymorphism(reflection, children)
|
19
|
+
self.reflection.options[:polymorphic] = true
|
20
|
+
end
|
21
|
+
else
|
22
|
+
initialize_without_polymorphism(reflection, children)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Reference https://github.com/rails/rails/commit/9b15db51b78028bfecdb85595624de4b838adbd1
|
27
|
+
def ==(other)
|
28
|
+
base_klass == other.base_klass
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_constraint_with_polymorphism(
|
32
|
+
klass, table, key, foreign_table, foreign_key
|
33
|
+
)
|
34
|
+
if reflection.polymorphic?
|
35
|
+
build_constraint_without_polymorphism(
|
36
|
+
klass, table, key, foreign_table, foreign_key
|
37
|
+
)
|
38
|
+
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
|
39
|
+
else
|
40
|
+
build_constraint_without_polymorphism(
|
41
|
+
klass, table, key, foreign_table, foreign_key
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# active_record_4.2_ruby_1.9/join_dependency.rb
|
2
|
+
require 'polyamorous/activerecord_4.2_ruby_2/join_dependency'
|
3
|
+
|
4
|
+
module Polyamorous
|
5
|
+
module JoinDependencyExtensions
|
6
|
+
def self.included(base)
|
7
|
+
base.extend ClassMethods
|
8
|
+
base.class_eval do
|
9
|
+
class << self
|
10
|
+
alias_method :walk_tree_without_polymorphism, :walk_tree
|
11
|
+
alias_method :walk_tree, :walk_tree_with_polymorphism
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method :build_without_polymorphism, :build
|
15
|
+
alias_method :build, :build_with_polymorphism
|
16
|
+
|
17
|
+
alias_method :join_constraints_without_polymorphism, :join_constraints
|
18
|
+
alias_method :join_constraints, :join_constraints_with_polymorphism
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Replaces ActiveRecord::Associations::JoinDependency#build
|
23
|
+
#
|
24
|
+
def build_with_polymorphism(associations, base_klass)
|
25
|
+
associations.map do |name, right|
|
26
|
+
if name.is_a? Join
|
27
|
+
reflection = find_reflection base_klass, name.name
|
28
|
+
reflection.check_validity!
|
29
|
+
klass = if reflection.polymorphic?
|
30
|
+
name.klass || base_klass
|
31
|
+
else
|
32
|
+
reflection.klass
|
33
|
+
end
|
34
|
+
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
|
35
|
+
else
|
36
|
+
reflection = find_reflection base_klass, name
|
37
|
+
reflection.check_validity!
|
38
|
+
if reflection.polymorphic?
|
39
|
+
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
40
|
+
end
|
41
|
+
JoinAssociation.new reflection, build(right, reflection.klass)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
|
47
|
+
# to call #make_polyamorous_inner_joins instead of #make_inner_joins
|
48
|
+
#
|
49
|
+
def join_constraints_with_polymorphism(outer_joins)
|
50
|
+
joins = join_root.children.flat_map { |child|
|
51
|
+
make_polyamorous_inner_joins join_root, child
|
52
|
+
}
|
53
|
+
joins.concat outer_joins.flat_map { |oj|
|
54
|
+
if join_root.match? oj.join_root
|
55
|
+
walk(join_root, oj.join_root)
|
56
|
+
else
|
57
|
+
oj.join_root.children.flat_map { |child|
|
58
|
+
make_outer_joins(oj.join_root, child)
|
59
|
+
}
|
60
|
+
end
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
module ClassMethods
|
65
|
+
# Replaces ActiveRecord::Associations::JoinDependency#self.walk_tree
|
66
|
+
#
|
67
|
+
def walk_tree_with_polymorphism(associations, hash)
|
68
|
+
case associations
|
69
|
+
when TreeNode
|
70
|
+
associations.add_to_tree(hash)
|
71
|
+
when Hash
|
72
|
+
associations.each do |k, v|
|
73
|
+
cache =
|
74
|
+
if TreeNode === k
|
75
|
+
k.add_to_tree(hash)
|
76
|
+
else
|
77
|
+
hash[k] ||= {}
|
78
|
+
end
|
79
|
+
walk_tree(v, cache)
|
80
|
+
end
|
81
|
+
else
|
82
|
+
walk_tree_without_polymorphism(associations, hash)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|