ransack 2.1.1 → 2.4.2
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/.github/FUNDING.yml +3 -0
- data/.github/SECURITY.md +12 -0
- data/.github/workflows/cronjob.yml +105 -0
- data/.github/workflows/rubocop.yml +20 -0
- data/.github/workflows/test.yml +154 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +44 -0
- data/CHANGELOG.md +55 -1
- data/CONTRIBUTING.md +13 -11
- data/Gemfile +23 -17
- data/README.md +119 -52
- data/bug_report_templates/test-ransack-scope-and-column-same-name.rb +78 -0
- data/bug_report_templates/test-ransacker-arel-present-predicate.rb +71 -0
- data/docs/img/create_release.png +0 -0
- data/docs/release_process.md +20 -0
- data/lib/polyamorous/{activerecord_5.2.1_ruby_2 → activerecord_5.2_ruby_2}/join_association.rb +2 -9
- data/lib/polyamorous/{activerecord_5.2.1_ruby_2 → activerecord_5.2_ruby_2}/join_dependency.rb +25 -3
- data/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb +11 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +80 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +1 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +74 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +93 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +1 -0
- data/lib/polyamorous/activerecord_6.2_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_6.2_ruby_2/join_dependency.rb +1 -0
- data/lib/polyamorous/activerecord_6.2_ruby_2/reflection.rb +1 -0
- data/lib/{polyamorous.rb → polyamorous/polyamorous.rb} +4 -5
- data/lib/ransack.rb +3 -3
- data/lib/ransack/adapters/active_record/base.rb +4 -0
- data/lib/ransack/adapters/active_record/context.rb +67 -68
- data/lib/ransack/adapters/active_record/ransack/constants.rb +18 -3
- data/lib/ransack/adapters/active_record/ransack/context.rb +2 -6
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +12 -5
- data/lib/ransack/adapters/active_record/ransack/translate.rb +1 -1
- data/lib/ransack/configuration.rb +17 -1
- data/lib/ransack/constants.rb +3 -5
- data/lib/ransack/context.rb +19 -18
- data/lib/ransack/helpers.rb +1 -1
- data/lib/ransack/helpers/form_builder.rb +8 -14
- data/lib/ransack/helpers/form_helper.rb +1 -1
- data/lib/ransack/locale/az.yml +1 -1
- data/lib/ransack/locale/ca.yml +70 -0
- data/lib/ransack/locale/es.yml +22 -22
- data/lib/ransack/locale/fa.yml +70 -0
- data/lib/ransack/locale/fi.yml +71 -0
- data/lib/ransack/locale/sk.yml +70 -0
- data/lib/ransack/nodes/attribute.rb +1 -1
- data/lib/ransack/nodes/condition.rb +7 -1
- data/lib/ransack/nodes/grouping.rb +1 -1
- data/lib/ransack/nodes/sort.rb +1 -1
- data/lib/ransack/nodes/value.rb +1 -1
- data/lib/ransack/predicate.rb +2 -1
- data/lib/ransack/search.rb +3 -1
- data/lib/ransack/translate.rb +115 -115
- data/lib/ransack/version.rb +1 -1
- data/ransack.gemspec +8 -23
- data/spec/blueprints/articles.rb +1 -1
- data/spec/blueprints/comments.rb +1 -1
- data/spec/blueprints/notes.rb +1 -1
- data/spec/blueprints/tags.rb +1 -1
- data/spec/console.rb +5 -5
- data/spec/helpers/polyamorous_helper.rb +3 -8
- data/spec/helpers/ransack_helper.rb +1 -1
- data/spec/{ransack → polyamorous}/join_association_spec.rb +7 -0
- data/spec/{ransack → polyamorous}/join_dependency_spec.rb +18 -7
- data/spec/{ransack → polyamorous}/join_spec.rb +0 -0
- data/spec/ransack/adapters/active_record/base_spec.rb +9 -6
- data/spec/ransack/adapters/active_record/context_spec.rb +60 -18
- data/spec/ransack/configuration_spec.rb +10 -0
- data/spec/ransack/helpers/form_helper_spec.rb +16 -16
- data/spec/ransack/nodes/grouping_spec.rb +2 -2
- data/spec/ransack/predicate_spec.rb +54 -2
- data/spec/ransack/search_spec.rb +127 -15
- data/spec/spec_helper.rb +10 -5
- data/spec/support/schema.rb +14 -3
- metadata +41 -137
- data/.travis.yml +0 -37
- data/lib/polyamorous/activerecord_5.0_ruby_2/join_association.rb +0 -2
- data/lib/polyamorous/activerecord_5.0_ruby_2/join_dependency.rb +0 -2
- data/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb +0 -32
- data/lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb +0 -112
- data/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb +0 -32
- data/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb +0 -113
Binary file
|
@@ -0,0 +1,20 @@
|
|
1
|
+
## Release Process
|
2
|
+
|
3
|
+
*For maintainers of Ransack.*
|
4
|
+
|
5
|
+
To release a new version of Ransack and publish it to RubyGems, take the following steps:
|
6
|
+
|
7
|
+
- Create a new release, marked `Prerelease`.
|
8
|
+
<<<<<<< Updated upstream
|
9
|
+
- Update the versions file to the new release, commit and push to `master`.
|
10
|
+
=======
|
11
|
+
- Update the [version.rb](../lib/ransack/version.rb) file to the new release, commit and push to `master`.
|
12
|
+
>>>>>>> Stashed changes
|
13
|
+
- From the terminal, run the following commands
|
14
|
+
|
15
|
+
```bash
|
16
|
+
rake build
|
17
|
+
rake release
|
18
|
+
```
|
19
|
+
|
20
|
+

|
data/lib/polyamorous/{activerecord_5.2.1_ruby_2 → activerecord_5.2_ruby_2}/join_association.rb
RENAMED
@@ -1,5 +1,3 @@
|
|
1
|
-
# active_record_5.2.1_ruby_2/join_association.rb
|
2
|
-
|
3
1
|
module Polyamorous
|
4
2
|
module JoinAssociationExtensions
|
5
3
|
include SwappingReflectionClass
|
@@ -19,13 +17,8 @@ module Polyamorous
|
|
19
17
|
end
|
20
18
|
end
|
21
19
|
|
22
|
-
def
|
23
|
-
|
24
|
-
super(klass, table, key, foreign_table, foreign_key)
|
25
|
-
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
|
26
|
-
else
|
27
|
-
super(klass, table, key, foreign_table, foreign_key)
|
28
|
-
end
|
20
|
+
def ==(other)
|
21
|
+
base_klass == other.base_klass
|
29
22
|
end
|
30
23
|
end
|
31
24
|
end
|
data/lib/polyamorous/{activerecord_5.2.1_ruby_2 → activerecord_5.2_ruby_2}/join_dependency.rb
RENAMED
@@ -1,9 +1,6 @@
|
|
1
|
-
# active_record_5.2.1_ruby_2/join_dependency.rb
|
2
|
-
|
3
1
|
module Polyamorous
|
4
2
|
module JoinDependencyExtensions
|
5
3
|
# Replaces ActiveRecord::Associations::JoinDependency#build
|
6
|
-
#
|
7
4
|
def build(associations, base_klass)
|
8
5
|
associations.map do |name, right|
|
9
6
|
if name.is_a? Join
|
@@ -30,6 +27,31 @@ module Polyamorous
|
|
30
27
|
end
|
31
28
|
end
|
32
29
|
|
30
|
+
def join_constraints(joins_to_add, join_type, alias_tracker)
|
31
|
+
@alias_tracker = alias_tracker
|
32
|
+
|
33
|
+
construct_tables!(join_root)
|
34
|
+
joins = make_join_constraints(join_root, join_type)
|
35
|
+
|
36
|
+
joins.concat joins_to_add.flat_map { |oj|
|
37
|
+
construct_tables!(oj.join_root)
|
38
|
+
if join_root.match?(oj.join_root) && join_root.table.name == oj.join_root.table.name
|
39
|
+
walk join_root, oj.join_root
|
40
|
+
else
|
41
|
+
make_join_constraints(oj.join_root, join_type)
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def make_constraints(parent, child, join_type = Arel::Nodes::OuterJoin)
|
48
|
+
foreign_table = parent.table
|
49
|
+
foreign_klass = parent.base_klass
|
50
|
+
join_type = child.join_type || join_type if join_type == Arel::Nodes::InnerJoin
|
51
|
+
joins = child.join_constraints(foreign_table, foreign_klass, join_type, alias_tracker)
|
52
|
+
joins.concat child.children.flat_map { |c| make_constraints(child, c, join_type) }
|
53
|
+
end
|
54
|
+
|
33
55
|
module ClassMethods
|
34
56
|
# Prepended before ActiveRecord::Associations::JoinDependency#walk_tree
|
35
57
|
#
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'polyamorous/activerecord_5.2_ruby_2/join_association'
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# active_record_6.0_ruby_2/join_dependency.rb
|
2
|
+
module Polyamorous
|
3
|
+
module JoinDependencyExtensions
|
4
|
+
# Replaces ActiveRecord::Associations::JoinDependency#build
|
5
|
+
def build(associations, base_klass)
|
6
|
+
associations.map do |name, right|
|
7
|
+
if name.is_a? Join
|
8
|
+
reflection = find_reflection base_klass, name.name
|
9
|
+
reflection.check_validity!
|
10
|
+
reflection.check_eager_loadable!
|
11
|
+
|
12
|
+
klass = if reflection.polymorphic?
|
13
|
+
name.klass || base_klass
|
14
|
+
else
|
15
|
+
reflection.klass
|
16
|
+
end
|
17
|
+
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
|
18
|
+
else
|
19
|
+
reflection = find_reflection base_klass, name
|
20
|
+
reflection.check_validity!
|
21
|
+
reflection.check_eager_loadable!
|
22
|
+
|
23
|
+
if reflection.polymorphic?
|
24
|
+
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
25
|
+
end
|
26
|
+
JoinAssociation.new(reflection, build(right, reflection.klass))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def join_constraints(joins_to_add, alias_tracker)
|
32
|
+
@alias_tracker = alias_tracker
|
33
|
+
|
34
|
+
construct_tables!(join_root)
|
35
|
+
joins = make_join_constraints(join_root, join_type)
|
36
|
+
|
37
|
+
joins.concat joins_to_add.flat_map { |oj|
|
38
|
+
construct_tables!(oj.join_root)
|
39
|
+
if join_root.match?(oj.join_root) && join_root.table.name == oj.join_root.table.name
|
40
|
+
walk join_root, oj.join_root, oj.join_type
|
41
|
+
else
|
42
|
+
make_join_constraints(oj.join_root, oj.join_type)
|
43
|
+
end
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def make_constraints(parent, child, join_type = Arel::Nodes::OuterJoin)
|
49
|
+
foreign_table = parent.table
|
50
|
+
foreign_klass = parent.base_klass
|
51
|
+
join_type = child.join_type || join_type if join_type == Arel::Nodes::InnerJoin
|
52
|
+
joins = child.join_constraints(foreign_table, foreign_klass, join_type, alias_tracker)
|
53
|
+
joins.concat child.children.flat_map { |c| make_constraints(child, c, join_type) }
|
54
|
+
end
|
55
|
+
|
56
|
+
module ClassMethods
|
57
|
+
# Prepended before ActiveRecord::Associations::JoinDependency#walk_tree
|
58
|
+
#
|
59
|
+
def walk_tree(associations, hash)
|
60
|
+
case associations
|
61
|
+
when TreeNode
|
62
|
+
associations.add_to_tree(hash)
|
63
|
+
when Hash
|
64
|
+
associations.each do |k, v|
|
65
|
+
cache =
|
66
|
+
if TreeNode === k
|
67
|
+
k.add_to_tree(hash)
|
68
|
+
else
|
69
|
+
hash[k] ||= {}
|
70
|
+
end
|
71
|
+
walk_tree(v, cache)
|
72
|
+
end
|
73
|
+
else
|
74
|
+
super(associations, hash)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'polyamorous/activerecord_5.2_ruby_2/reflection'
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Polyamorous
|
2
|
+
module JoinAssociationExtensions
|
3
|
+
include SwappingReflectionClass
|
4
|
+
def self.prepended(base)
|
5
|
+
base.class_eval { attr_reader :join_type }
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(reflection, children, polymorphic_class = nil, join_type = Arel::Nodes::InnerJoin)
|
9
|
+
@join_type = join_type
|
10
|
+
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
|
11
|
+
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
|
12
|
+
super(reflection, children)
|
13
|
+
self.reflection.options[:polymorphic] = true
|
14
|
+
end
|
15
|
+
else
|
16
|
+
super(reflection, children)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Same as #join_constraints, but instead of constructing tables from the
|
21
|
+
# given block, uses the ones passed
|
22
|
+
def join_constraints_with_tables(foreign_table, foreign_klass, join_type, alias_tracker, tables)
|
23
|
+
joins = []
|
24
|
+
chain = []
|
25
|
+
|
26
|
+
reflection.chain.each.with_index do |reflection, i|
|
27
|
+
table = tables[i]
|
28
|
+
|
29
|
+
@table ||= table
|
30
|
+
chain << [reflection, table]
|
31
|
+
end
|
32
|
+
|
33
|
+
# The chain starts with the target table, but we want to end with it here (makes
|
34
|
+
# more sense in this context), so we reverse
|
35
|
+
chain.reverse_each do |reflection, table|
|
36
|
+
klass = reflection.klass
|
37
|
+
|
38
|
+
join_scope = reflection.join_scope(table, foreign_table, foreign_klass)
|
39
|
+
|
40
|
+
unless join_scope.references_values.empty?
|
41
|
+
join_dependency = join_scope.construct_join_dependency(
|
42
|
+
join_scope.eager_load_values | join_scope.includes_values, Arel::Nodes::OuterJoin
|
43
|
+
)
|
44
|
+
join_scope.joins!(join_dependency)
|
45
|
+
end
|
46
|
+
|
47
|
+
arel = join_scope.arel(alias_tracker.aliases)
|
48
|
+
nodes = arel.constraints.first
|
49
|
+
|
50
|
+
if nodes.is_a?(Arel::Nodes::And)
|
51
|
+
others = nodes.children.extract! do |node|
|
52
|
+
!Arel.fetch_attribute(node) { |attr| attr.relation.name == table.name }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
joins << table.create_join(table, table.create_on(nodes), join_type)
|
57
|
+
|
58
|
+
if others && !others.empty?
|
59
|
+
joins.concat arel.join_sources
|
60
|
+
append_constraints(joins.last, others)
|
61
|
+
end
|
62
|
+
|
63
|
+
# The current table in this iteration becomes the foreign table in the next
|
64
|
+
foreign_table, foreign_klass = table, klass
|
65
|
+
end
|
66
|
+
|
67
|
+
joins
|
68
|
+
end
|
69
|
+
|
70
|
+
def ==(other)
|
71
|
+
base_klass == other.base_klass
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# active_record_6.1_ruby_2/join_dependency.rb
|
2
|
+
module Polyamorous
|
3
|
+
module JoinDependencyExtensions
|
4
|
+
# Replaces ActiveRecord::Associations::JoinDependency#build
|
5
|
+
def build(associations, base_klass)
|
6
|
+
associations.map do |name, right|
|
7
|
+
if name.is_a? Join
|
8
|
+
reflection = find_reflection base_klass, name.name
|
9
|
+
reflection.check_validity!
|
10
|
+
reflection.check_eager_loadable!
|
11
|
+
|
12
|
+
klass = if reflection.polymorphic?
|
13
|
+
name.klass || base_klass
|
14
|
+
else
|
15
|
+
reflection.klass
|
16
|
+
end
|
17
|
+
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
|
18
|
+
else
|
19
|
+
reflection = find_reflection base_klass, name
|
20
|
+
reflection.check_validity!
|
21
|
+
reflection.check_eager_loadable!
|
22
|
+
|
23
|
+
if reflection.polymorphic?
|
24
|
+
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
25
|
+
end
|
26
|
+
JoinAssociation.new(reflection, build(right, reflection.klass))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def join_constraints(joins_to_add, alias_tracker, references)
|
32
|
+
@alias_tracker = alias_tracker
|
33
|
+
@joined_tables = {}
|
34
|
+
@references = {}
|
35
|
+
|
36
|
+
references.each do |table_name|
|
37
|
+
@references[table_name.to_sym] = table_name if table_name.is_a?(String)
|
38
|
+
end
|
39
|
+
|
40
|
+
joins = make_join_constraints(join_root, join_type)
|
41
|
+
|
42
|
+
joins.concat joins_to_add.flat_map { |oj|
|
43
|
+
if join_root.match?(oj.join_root) && join_root.table.name == oj.join_root.table.name
|
44
|
+
walk join_root, oj.join_root, oj.join_type
|
45
|
+
else
|
46
|
+
make_join_constraints(oj.join_root, oj.join_type)
|
47
|
+
end
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def construct_tables_for_association!(join_root, association)
|
52
|
+
tables = table_aliases_for(join_root, association)
|
53
|
+
association.table = tables.first
|
54
|
+
tables
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def table_aliases_for(parent, node)
|
60
|
+
node.reflection.chain.map { |reflection|
|
61
|
+
alias_tracker.aliased_table_for(reflection.klass.arel_table) do
|
62
|
+
root = reflection == node.reflection
|
63
|
+
name = reflection.alias_candidate(parent.table_name)
|
64
|
+
root ? name : "#{name}_join"
|
65
|
+
end
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
module ClassMethods
|
70
|
+
# Prepended before ActiveRecord::Associations::JoinDependency#walk_tree
|
71
|
+
#
|
72
|
+
def walk_tree(associations, hash)
|
73
|
+
case associations
|
74
|
+
when TreeNode
|
75
|
+
associations.add_to_tree(hash)
|
76
|
+
when Hash
|
77
|
+
associations.each do |k, v|
|
78
|
+
cache =
|
79
|
+
if TreeNode === k
|
80
|
+
k.add_to_tree(hash)
|
81
|
+
else
|
82
|
+
hash[k] ||= {}
|
83
|
+
end
|
84
|
+
walk_tree(v, cache)
|
85
|
+
end
|
86
|
+
else
|
87
|
+
super(associations, hash)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'polyamorous/activerecord_6.0_ruby_2/reflection'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'polyamorous/activerecord_6.1_ruby_2/join_association'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'polyamorous/activerecord_6.1_ruby_2/join_dependency'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'polyamorous/activerecord_6.1_ruby_2/reflection'
|
@@ -11,14 +11,13 @@ if defined?(::ActiveRecord)
|
|
11
11
|
require 'polyamorous/join'
|
12
12
|
require 'polyamorous/swapping_reflection_class'
|
13
13
|
|
14
|
-
ar_version = ::ActiveRecord::VERSION::STRING[0,3]
|
15
|
-
|
16
|
-
ar_version = "5.2.1" if ::ActiveRecord::VERSION::STRING >= "5.2.1"
|
17
|
-
|
18
|
-
%w(join_association join_dependency).each do |file|
|
14
|
+
ar_version = ::ActiveRecord::VERSION::STRING[0, 3]
|
15
|
+
%w(join_association join_dependency reflection).each do |file|
|
19
16
|
require "polyamorous/activerecord_#{ar_version}_ruby_2/#{file}"
|
20
17
|
end
|
21
18
|
|
19
|
+
ActiveRecord::Reflection::AbstractReflection.send(:prepend, Polyamorous::ReflectionExtensions)
|
20
|
+
|
22
21
|
Polyamorous::JoinDependency.send(:prepend, Polyamorous::JoinDependencyExtensions)
|
23
22
|
Polyamorous::JoinDependency.singleton_class.send(:prepend, Polyamorous::JoinDependencyExtensions::ClassMethods)
|
24
23
|
Polyamorous::JoinAssociation.send(:prepend, Polyamorous::JoinAssociationExtensions)
|
data/lib/ransack.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'active_support/core_ext'
|
2
2
|
require 'ransack/configuration'
|
3
3
|
require 'ransack/adapters'
|
4
|
+
require 'polyamorous/polyamorous'
|
4
5
|
|
5
6
|
Ransack::Adapters.object_mapper.require_constants
|
6
7
|
|
7
8
|
module Ransack
|
8
9
|
extend Configuration
|
9
|
-
class UntraversableAssociationError < StandardError; end
|
10
|
+
class UntraversableAssociationError < StandardError; end
|
10
11
|
end
|
11
12
|
|
12
13
|
Ransack.configure do |config|
|
@@ -20,12 +21,11 @@ end
|
|
20
21
|
|
21
22
|
require 'ransack/search'
|
22
23
|
require 'ransack/ransacker'
|
23
|
-
require 'ransack/helpers'
|
24
|
-
require 'action_controller'
|
25
24
|
require 'ransack/translate'
|
26
25
|
|
27
26
|
Ransack::Adapters.object_mapper.require_adapter
|
28
27
|
|
29
28
|
ActiveSupport.on_load(:action_controller) do
|
29
|
+
require 'ransack/helpers'
|
30
30
|
ActionController::Base.helper Ransack::Helpers::FormHelper
|
31
31
|
end
|
@@ -18,6 +18,10 @@ module Ransack
|
|
18
18
|
Search.new(self, params, options)
|
19
19
|
end
|
20
20
|
|
21
|
+
def ransack!(params = {}, options = {})
|
22
|
+
ransack(params, options.merge(ignore_unknown_conditions: false))
|
23
|
+
end
|
24
|
+
|
21
25
|
def ransacker(name, opts = {}, &block)
|
22
26
|
self._ransackers = _ransackers.merge name.to_s => Ransacker
|
23
27
|
.new(self, name, opts, &block)
|
@@ -1,18 +1,11 @@
|
|
1
1
|
require 'ransack/context'
|
2
|
-
require 'polyamorous'
|
2
|
+
require 'polyamorous/polyamorous'
|
3
3
|
|
4
4
|
module Ransack
|
5
5
|
module Adapters
|
6
6
|
module ActiveRecord
|
7
7
|
class Context < ::Ransack::Context
|
8
8
|
|
9
|
-
def initialize(object, options = {})
|
10
|
-
super
|
11
|
-
if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2
|
12
|
-
@arel_visitor = @engine.connection.visitor
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
9
|
def relation_for(object)
|
17
10
|
object.all
|
18
11
|
end
|
@@ -49,6 +42,13 @@ module Ransack
|
|
49
42
|
if scope_or_sort.is_a?(Symbol)
|
50
43
|
relation = relation.send(scope_or_sort)
|
51
44
|
else
|
45
|
+
case Ransack.options[:postgres_fields_sort_option]
|
46
|
+
when :nulls_first
|
47
|
+
scope_or_sort = scope_or_sort.direction == :asc ? "#{scope_or_sort.to_sql} NULLS FIRST" : "#{scope_or_sort.to_sql} NULLS LAST"
|
48
|
+
when :nulls_last
|
49
|
+
scope_or_sort = scope_or_sort.direction == :asc ? "#{scope_or_sort.to_sql} NULLS LAST" : "#{scope_or_sort.to_sql} NULLS FIRST"
|
50
|
+
end
|
51
|
+
|
52
52
|
relation = relation.order(scope_or_sort)
|
53
53
|
end
|
54
54
|
end
|
@@ -104,20 +104,21 @@ module Ransack
|
|
104
104
|
# JoinDependency to track table aliases.
|
105
105
|
#
|
106
106
|
def join_sources
|
107
|
-
base, joins =
|
108
|
-
if ::ActiveRecord::VERSION::STRING > Constants::RAILS_5_2_0
|
107
|
+
base, joins = begin
|
109
108
|
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, @object.table.name, [])
|
110
|
-
|
111
|
-
|
109
|
+
constraints = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_1)
|
110
|
+
@join_dependency.join_constraints(@object.joins_values, alias_tracker, @object.references_values)
|
111
|
+
elsif ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_0)
|
112
|
+
@join_dependency.join_constraints(@object.joins_values, alias_tracker)
|
113
|
+
else
|
112
114
|
@join_dependency.join_constraints(@object.joins_values, @join_type, alias_tracker)
|
113
|
-
|
114
|
-
|
115
|
+
end
|
116
|
+
|
115
117
|
[
|
116
118
|
Arel::SelectManager.new(@object.table),
|
117
|
-
|
119
|
+
constraints
|
118
120
|
]
|
119
121
|
end
|
120
|
-
joins = joins.collect(&:joins).flatten if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2
|
121
122
|
joins.each do |aliased_join|
|
122
123
|
base.from(aliased_join)
|
123
124
|
end
|
@@ -163,7 +164,7 @@ module Ransack
|
|
163
164
|
def build_correlated_subquery(association)
|
164
165
|
join_constraints = extract_joins(association)
|
165
166
|
join_root = join_constraints.shift
|
166
|
-
correlated_key = join_root
|
167
|
+
correlated_key = extract_correlated_key(join_root)
|
167
168
|
subquery = Arel::SelectManager.new(association.base_klass)
|
168
169
|
subquery.from(join_root.left)
|
169
170
|
subquery.project(correlated_key)
|
@@ -179,6 +180,35 @@ module Ransack
|
|
179
180
|
|
180
181
|
private
|
181
182
|
|
183
|
+
def extract_correlated_key(join_root)
|
184
|
+
case join_root
|
185
|
+
when Arel::Nodes::OuterJoin
|
186
|
+
# one of join_root.right/join_root.left is expected to be Arel::Nodes::On
|
187
|
+
if join_root.right.is_a?(Arel::Nodes::On)
|
188
|
+
extract_correlated_key(join_root.right.expr)
|
189
|
+
elsif join_root.left.is_a?(Arel::Nodes::On)
|
190
|
+
extract_correlated_key(join_root.left.expr)
|
191
|
+
else
|
192
|
+
raise 'Ransack encountered an unexpected arel structure'
|
193
|
+
end
|
194
|
+
when Arel::Nodes::Equality
|
195
|
+
pk = primary_key
|
196
|
+
if join_root.left == pk
|
197
|
+
join_root.right
|
198
|
+
elsif join_root.right == pk
|
199
|
+
join_root.left
|
200
|
+
else
|
201
|
+
nil
|
202
|
+
end
|
203
|
+
when Arel::Nodes::And
|
204
|
+
extract_correlated_key(join_root.left) || extract_correlated_key(join_root.right)
|
205
|
+
else
|
206
|
+
# eg parent was Arel::Nodes::And and the evaluated side was one of
|
207
|
+
# Arel::Nodes::Grouping or MultiTenant::TenantEnforcementClause
|
208
|
+
nil
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
182
212
|
def get_parent_and_attribute_name(str, parent = @base)
|
183
213
|
attr_name = nil
|
184
214
|
|
@@ -248,24 +278,15 @@ module Ransack
|
|
248
278
|
|
249
279
|
join_list = join_nodes + convert_join_strings_to_ast(relation.table, string_joins)
|
250
280
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
|
255
|
-
end
|
256
|
-
elsif ::ActiveRecord::VERSION::STRING == Constants::RAILS_5_2_0
|
257
|
-
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, relation.table.name, join_list)
|
258
|
-
join_dependency = Polyamorous::JoinDependency.new(relation.klass, relation.table, association_joins, alias_tracker)
|
259
|
-
join_nodes.each do |join|
|
260
|
-
join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
|
261
|
-
end
|
281
|
+
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, relation.table.name, join_list)
|
282
|
+
join_dependency = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_0)
|
283
|
+
Polyamorous::JoinDependency.new(relation.klass, relation.table, association_joins, Arel::Nodes::OuterJoin)
|
262
284
|
else
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
end
|
285
|
+
Polyamorous::JoinDependency.new(relation.klass, relation.table, association_joins)
|
286
|
+
end
|
287
|
+
join_dependency.instance_variable_set(:@alias_tracker, alias_tracker)
|
288
|
+
join_nodes.each do |join|
|
289
|
+
join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
|
269
290
|
end
|
270
291
|
join_dependency
|
271
292
|
end
|
@@ -289,32 +310,23 @@ module Ransack
|
|
289
310
|
end
|
290
311
|
|
291
312
|
def build_association(name, parent = @base, klass = nil)
|
292
|
-
if ::ActiveRecord::VERSION::STRING
|
293
|
-
jd = Polyamorous::JoinDependency.new(
|
294
|
-
parent.base_klass,
|
295
|
-
Polyamorous::Join.new(name, @join_type, klass),
|
296
|
-
[]
|
297
|
-
)
|
298
|
-
found_association = jd.join_root.children.last
|
299
|
-
elsif ::ActiveRecord::VERSION::STRING == Constants::RAILS_5_2_0
|
300
|
-
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, parent.table.name, [])
|
313
|
+
if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_0)
|
301
314
|
jd = Polyamorous::JoinDependency.new(
|
302
315
|
parent.base_klass,
|
303
|
-
parent.
|
316
|
+
parent.table,
|
304
317
|
Polyamorous::Join.new(name, @join_type, klass),
|
305
|
-
|
318
|
+
@join_type
|
306
319
|
)
|
307
320
|
found_association = jd.instance_variable_get(:@join_root).children.last
|
308
321
|
else
|
309
322
|
jd = Polyamorous::JoinDependency.new(
|
310
323
|
parent.base_klass,
|
311
|
-
parent.
|
312
|
-
Polyamorous::Join.new(name, @join_type, klass)
|
324
|
+
parent.table,
|
325
|
+
Polyamorous::Join.new(name, @join_type, klass)
|
313
326
|
)
|
314
327
|
found_association = jd.instance_variable_get(:@join_root).children.last
|
315
328
|
end
|
316
329
|
|
317
|
-
|
318
330
|
@associations_pot[found_association] = parent
|
319
331
|
|
320
332
|
# TODO maybe we dont need to push associations here, we could loop
|
@@ -322,40 +334,27 @@ module Ransack
|
|
322
334
|
@join_dependency.instance_variable_get(:@join_root).children.push found_association
|
323
335
|
|
324
336
|
# Builds the arel nodes properly for this association
|
325
|
-
if ::ActiveRecord::VERSION::STRING
|
326
|
-
@join_dependency.
|
337
|
+
if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_1)
|
338
|
+
@tables_pot[found_association] = @join_dependency.construct_tables_for_association!(jd.instance_variable_get(:@join_root), found_association)
|
327
339
|
else
|
328
|
-
@join_dependency.send(
|
329
|
-
:construct_tables!, jd.instance_variable_get(:@join_root), found_association
|
330
|
-
)
|
340
|
+
@join_dependency.send(:construct_tables!, jd.instance_variable_get(:@join_root))
|
331
341
|
end
|
332
342
|
|
333
343
|
# Leverage the stashed association functionality in AR
|
334
344
|
@object = @object.joins(jd)
|
335
|
-
|
336
345
|
found_association
|
337
346
|
end
|
338
347
|
|
339
348
|
def extract_joins(association)
|
340
349
|
parent = @join_dependency.instance_variable_get(:@join_root)
|
341
350
|
reflection = association.reflection
|
342
|
-
join_constraints = if ::ActiveRecord::VERSION::STRING
|
343
|
-
association.
|
344
|
-
parent.table,
|
345
|
-
parent.base_klass,
|
346
|
-
association,
|
347
|
-
Arel::Nodes::OuterJoin,
|
348
|
-
association.tables,
|
349
|
-
reflection.scope_chain,
|
350
|
-
reflection.chain
|
351
|
-
)
|
352
|
-
elsif ::ActiveRecord::VERSION::STRING <= Constants::RAILS_5_2_0
|
353
|
-
association.join_constraints(
|
351
|
+
join_constraints = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_1)
|
352
|
+
association.join_constraints_with_tables(
|
354
353
|
parent.table,
|
355
354
|
parent.base_klass,
|
356
355
|
Arel::Nodes::OuterJoin,
|
357
|
-
|
358
|
-
|
356
|
+
@join_dependency.instance_variable_get(:@alias_tracker),
|
357
|
+
@tables_pot[association]
|
359
358
|
)
|
360
359
|
else
|
361
360
|
association.join_constraints(
|