ransack 1.8.8 → 1.8.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://travis-ci.org/activerecord-hackery/ransack.svg)](https://travis-ci.org/activerecord-hackery/ransack)
|
4
27
|
[![Gem Version](https://badge.fury.io/rb/ransack.svg)](http://badge.fury.io/rb/ransack)
|
5
28
|
[![Code Climate](https://codeclimate.com/github/activerecord-hackery/ransack/badges/gpa.svg)](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
|