ransack 1.7.0 → 2.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/FUNDING.yml +3 -0
- data/.github/SECURITY.md +12 -0
- data/.github/workflows/test.yml +120 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +463 -27
- data/CONTRIBUTING.md +52 -22
- data/Gemfile +24 -24
- data/README.md +453 -126
- data/Rakefile +6 -25
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb +24 -0
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb +79 -0
- 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/join.rb +70 -0
- data/lib/polyamorous/polyamorous.rb +24 -0
- data/lib/polyamorous/swapping_reflection_class.rb +11 -0
- data/lib/polyamorous/tree_node.rb +7 -0
- data/lib/ransack/adapters/active_record/base.rb +27 -2
- data/lib/ransack/adapters/active_record/context.rb +213 -139
- data/lib/ransack/adapters/active_record/ransack/constants.rb +70 -55
- data/lib/ransack/adapters/active_record/ransack/context.rb +10 -18
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +42 -32
- data/lib/ransack/adapters/active_record/ransack/translate.rb +1 -5
- data/lib/ransack/adapters/active_record/ransack/visitor.rb +23 -0
- data/lib/ransack/adapters/active_record.rb +11 -10
- data/lib/ransack/adapters.rb +45 -23
- data/lib/ransack/configuration.rb +107 -4
- data/lib/ransack/constants.rb +13 -26
- data/lib/ransack/context.rb +45 -33
- data/lib/ransack/helpers/form_builder.rb +21 -12
- data/lib/ransack/helpers/form_helper.rb +75 -70
- data/lib/ransack/locale/ar.yml +70 -0
- data/lib/ransack/locale/az.yml +70 -0
- data/lib/ransack/locale/bg.yml +70 -0
- data/lib/ransack/locale/ca.yml +70 -0
- data/lib/ransack/locale/da.yml +70 -0
- data/lib/ransack/locale/el.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/id.yml +70 -0
- data/lib/ransack/locale/it.yml +70 -0
- data/lib/ransack/locale/ja.yml +70 -0
- data/lib/ransack/locale/nl.yml +4 -4
- data/lib/ransack/locale/pt-BR.yml +70 -0
- data/lib/ransack/locale/ru.yml +70 -0
- data/lib/ransack/locale/sk.yml +70 -0
- data/lib/ransack/locale/tr.yml +70 -0
- data/lib/ransack/locale/{zh.yml → zh-CN.yml} +13 -13
- data/lib/ransack/locale/zh-TW.yml +70 -0
- data/lib/ransack/nodes/attribute.rb +5 -2
- data/lib/ransack/nodes/bindable.rb +18 -6
- data/lib/ransack/nodes/condition.rb +85 -28
- data/lib/ransack/nodes/grouping.rb +17 -11
- data/lib/ransack/nodes/sort.rb +9 -5
- data/lib/ransack/nodes/value.rb +74 -68
- data/lib/ransack/nodes.rb +1 -1
- data/lib/ransack/predicate.rb +17 -20
- data/lib/ransack/search.rb +17 -8
- data/lib/ransack/translate.rb +115 -115
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +1 -12
- data/lib/ransack.rb +9 -9
- data/logo/ransack-h.png +0 -0
- data/logo/ransack-h.svg +34 -0
- data/logo/ransack-v.png +0 -0
- data/logo/ransack-v.svg +34 -0
- data/logo/ransack.png +0 -0
- data/logo/ransack.svg +21 -0
- data/ransack.gemspec +7 -24
- data/spec/console.rb +4 -0
- data/spec/helpers/polyamorous_helper.rb +19 -0
- data/spec/polyamorous/join_association_spec.rb +35 -0
- data/spec/polyamorous/join_dependency_spec.rb +97 -0
- data/spec/polyamorous/join_spec.rb +19 -0
- data/spec/ransack/adapters/active_record/base_spec.rb +370 -75
- data/spec/ransack/adapters/active_record/context_spec.rb +72 -34
- data/spec/ransack/configuration_spec.rb +97 -14
- data/spec/ransack/helpers/form_builder_spec.rb +2 -11
- data/spec/ransack/helpers/form_helper_spec.rb +481 -113
- data/spec/ransack/nodes/condition_spec.rb +24 -0
- data/spec/ransack/nodes/grouping_spec.rb +56 -0
- data/spec/ransack/predicate_spec.rb +79 -5
- data/spec/ransack/search_spec.rb +207 -81
- data/spec/spec_helper.rb +8 -0
- data/spec/support/schema.rb +100 -42
- metadata +57 -184
- data/.travis.yml +0 -69
- data/lib/ransack/adapters/active_record/3.0/compat.rb +0 -179
- data/lib/ransack/adapters/active_record/3.0/context.rb +0 -201
- data/lib/ransack/adapters/active_record/3.1/context.rb +0 -215
- data/lib/ransack/adapters/active_record/3.2/context.rb +0 -44
- data/lib/ransack/adapters/active_record/compat.rb +0 -14
- data/lib/ransack/adapters/mongoid/3.2/.gitkeep +0 -0
- data/lib/ransack/adapters/mongoid/attributes/attribute.rb +0 -37
- data/lib/ransack/adapters/mongoid/attributes/order_predications.rb +0 -17
- data/lib/ransack/adapters/mongoid/attributes/predications.rb +0 -141
- data/lib/ransack/adapters/mongoid/base.rb +0 -130
- data/lib/ransack/adapters/mongoid/context.rb +0 -208
- data/lib/ransack/adapters/mongoid/inquiry_hash.rb +0 -23
- data/lib/ransack/adapters/mongoid/ransack/constants.rb +0 -88
- data/lib/ransack/adapters/mongoid/ransack/context.rb +0 -60
- data/lib/ransack/adapters/mongoid/ransack/nodes/condition.rb +0 -27
- data/lib/ransack/adapters/mongoid/ransack/translate.rb +0 -13
- data/lib/ransack/adapters/mongoid/ransack/visitor.rb +0 -24
- data/lib/ransack/adapters/mongoid/table.rb +0 -35
- data/lib/ransack/adapters/mongoid.rb +0 -13
- data/spec/mongoid/adapters/mongoid/base_spec.rb +0 -276
- data/spec/mongoid/adapters/mongoid/context_spec.rb +0 -56
- data/spec/mongoid/configuration_spec.rb +0 -102
- data/spec/mongoid/dependencies_spec.rb +0 -8
- data/spec/mongoid/helpers/ransack_helper.rb +0 -11
- data/spec/mongoid/nodes/condition_spec.rb +0 -34
- data/spec/mongoid/nodes/grouping_spec.rb +0 -13
- data/spec/mongoid/predicate_spec.rb +0 -155
- data/spec/mongoid/search_spec.rb +0 -446
- data/spec/mongoid/support/mongoid.yml +0 -6
- data/spec/mongoid/support/schema.rb +0 -128
- data/spec/mongoid/translate_spec.rb +0 -14
- data/spec/mongoid_spec_helper.rb +0 -59
- data/spec/ransack/dependencies_spec.rb +0 -12
data/Rakefile
CHANGED
@@ -5,39 +5,20 @@ Bundler::GemHelper.install_tasks
|
|
5
5
|
|
6
6
|
RSpec::Core::RakeTask.new(:spec) do |rspec|
|
7
7
|
ENV['SPEC'] = 'spec/ransack/**/*_spec.rb'
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
ENV['SPEC'] = 'spec/mongoid/**/*_spec.rb'
|
13
|
-
rspec.rspec_opts = ['--backtrace']
|
8
|
+
# With Rails 3, using `--backtrace` raises 'invalid option' when testing.
|
9
|
+
# With Rails 4 and 5 it can be uncommented to see the backtrace:
|
10
|
+
#
|
11
|
+
# rspec.rspec_opts = ['--backtrace']
|
14
12
|
end
|
15
13
|
|
16
14
|
task :default do
|
17
|
-
|
18
|
-
Rake::Task["mongoid"].invoke
|
19
|
-
else
|
20
|
-
Rake::Task["spec"].invoke
|
21
|
-
end
|
15
|
+
Rake::Task["spec"].invoke
|
22
16
|
end
|
23
17
|
|
24
18
|
desc "Open an irb session with Ransack and the sample data used in specs"
|
25
19
|
task :console do
|
26
|
-
require 'irb'
|
27
|
-
require 'irb/completion'
|
28
|
-
require 'console'
|
29
|
-
ARGV.clear
|
30
|
-
IRB.start
|
31
|
-
end
|
32
|
-
|
33
|
-
desc "Open an irb session with Ransack, Mongoid and the sample data used in specs"
|
34
|
-
task :mongoid_console do
|
35
|
-
require 'irb'
|
36
|
-
require 'irb/completion'
|
37
20
|
require 'pry'
|
38
|
-
require '
|
39
|
-
require File.expand_path('../lib/ransack.rb', __FILE__)
|
40
|
-
require File.expand_path('../spec/mongoid/support/schema.rb', __FILE__)
|
21
|
+
require File.expand_path('../spec/console.rb', __FILE__)
|
41
22
|
ARGV.clear
|
42
23
|
Pry.start
|
43
24
|
end
|
@@ -0,0 +1,24 @@
|
|
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
|
+
def ==(other)
|
21
|
+
base_klass == other.base_klass
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Polyamorous
|
2
|
+
module JoinDependencyExtensions
|
3
|
+
# Replaces ActiveRecord::Associations::JoinDependency#build
|
4
|
+
def build(associations, base_klass)
|
5
|
+
associations.map do |name, right|
|
6
|
+
if name.is_a? Join
|
7
|
+
reflection = find_reflection base_klass, name.name
|
8
|
+
reflection.check_validity!
|
9
|
+
reflection.check_eager_loadable!
|
10
|
+
|
11
|
+
klass = if reflection.polymorphic?
|
12
|
+
name.klass || base_klass
|
13
|
+
else
|
14
|
+
reflection.klass
|
15
|
+
end
|
16
|
+
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
|
17
|
+
else
|
18
|
+
reflection = find_reflection base_klass, name
|
19
|
+
reflection.check_validity!
|
20
|
+
reflection.check_eager_loadable!
|
21
|
+
|
22
|
+
if reflection.polymorphic?
|
23
|
+
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
24
|
+
end
|
25
|
+
JoinAssociation.new(reflection, build(right, reflection.klass))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
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
|
+
|
55
|
+
module ClassMethods
|
56
|
+
# Prepended before ActiveRecord::Associations::JoinDependency#walk_tree
|
57
|
+
#
|
58
|
+
def walk_tree(associations, hash)
|
59
|
+
case associations
|
60
|
+
when TreeNode
|
61
|
+
associations.add_to_tree(hash)
|
62
|
+
when Hash
|
63
|
+
associations.each do |k, v|
|
64
|
+
cache =
|
65
|
+
if TreeNode === k
|
66
|
+
k.add_to_tree(hash)
|
67
|
+
else
|
68
|
+
hash[k] ||= {}
|
69
|
+
end
|
70
|
+
walk_tree(v, cache)
|
71
|
+
end
|
72
|
+
else
|
73
|
+
super(associations, hash)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
@@ -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,70 @@
|
|
1
|
+
module Polyamorous
|
2
|
+
class Join
|
3
|
+
include TreeNode
|
4
|
+
|
5
|
+
attr_accessor :name
|
6
|
+
attr_reader :type, :klass
|
7
|
+
|
8
|
+
def initialize(name, type = InnerJoin, klass = nil)
|
9
|
+
@name = name
|
10
|
+
@type = convert_to_arel_join_type(type)
|
11
|
+
@klass = convert_to_class(klass) if klass
|
12
|
+
end
|
13
|
+
|
14
|
+
def klass=(klass)
|
15
|
+
@klass = convert_to_class(klass) if klass
|
16
|
+
end
|
17
|
+
|
18
|
+
def type=(type)
|
19
|
+
@type = convert_to_arel_join_type(type) if type
|
20
|
+
end
|
21
|
+
|
22
|
+
def hash
|
23
|
+
[@name, @type, @klass].hash
|
24
|
+
end
|
25
|
+
|
26
|
+
def eql?(other)
|
27
|
+
self.class == other.class &&
|
28
|
+
self.name == other.name &&
|
29
|
+
self.type == other.type &&
|
30
|
+
self.klass == other.klass
|
31
|
+
end
|
32
|
+
|
33
|
+
alias :== :eql?
|
34
|
+
|
35
|
+
def add_to_tree(hash)
|
36
|
+
hash[self] ||= {}
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def convert_to_arel_join_type(type)
|
42
|
+
case type
|
43
|
+
when 'inner', :inner
|
44
|
+
InnerJoin
|
45
|
+
when 'outer', :outer
|
46
|
+
OuterJoin
|
47
|
+
when Class
|
48
|
+
if [InnerJoin, OuterJoin].include? type
|
49
|
+
type
|
50
|
+
else
|
51
|
+
raise ArgumentError, "#{type} cannot be converted to an ARel join type"
|
52
|
+
end
|
53
|
+
else
|
54
|
+
raise ArgumentError, "#{type} cannot be converted to an ARel join type"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def convert_to_class(value)
|
59
|
+
case value
|
60
|
+
when String, Symbol
|
61
|
+
Kernel.const_get(value)
|
62
|
+
when Class
|
63
|
+
value
|
64
|
+
else
|
65
|
+
raise ArgumentError, "#{value} cannot be converted to a Class"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
if defined?(::ActiveRecord)
|
2
|
+
module Polyamorous
|
3
|
+
InnerJoin = Arel::Nodes::InnerJoin
|
4
|
+
OuterJoin = Arel::Nodes::OuterJoin
|
5
|
+
|
6
|
+
JoinDependency = ::ActiveRecord::Associations::JoinDependency
|
7
|
+
JoinAssociation = ::ActiveRecord::Associations::JoinDependency::JoinAssociation
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'polyamorous/tree_node'
|
11
|
+
require 'polyamorous/join'
|
12
|
+
require 'polyamorous/swapping_reflection_class'
|
13
|
+
|
14
|
+
ar_version = ::ActiveRecord::VERSION::STRING[0,3]
|
15
|
+
%w(join_association join_dependency reflection).each do |file|
|
16
|
+
require "polyamorous/activerecord_#{ar_version}_ruby_2/#{file}"
|
17
|
+
end
|
18
|
+
|
19
|
+
ActiveRecord::Reflection::AbstractReflection.send(:prepend, Polyamorous::ReflectionExtensions)
|
20
|
+
|
21
|
+
Polyamorous::JoinDependency.send(:prepend, Polyamorous::JoinDependencyExtensions)
|
22
|
+
Polyamorous::JoinDependency.singleton_class.send(:prepend, Polyamorous::JoinDependencyExtensions::ClassMethods)
|
23
|
+
Polyamorous::JoinAssociation.send(:prepend, Polyamorous::JoinAssociationExtensions)
|
24
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Polyamorous
|
2
|
+
module SwappingReflectionClass
|
3
|
+
def swapping_reflection_klass(reflection, klass)
|
4
|
+
new_reflection = reflection.clone
|
5
|
+
new_reflection.instance_variable_set(:@options, reflection.options.clone)
|
6
|
+
new_reflection.options.delete(:polymorphic)
|
7
|
+
new_reflection.instance_variable_set(:@klass, klass)
|
8
|
+
yield new_reflection
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -7,25 +7,42 @@ module Ransack
|
|
7
7
|
alias :search :ransack unless base.respond_to? :search
|
8
8
|
base.class_eval do
|
9
9
|
class_attribute :_ransackers
|
10
|
+
class_attribute :_ransack_aliases
|
10
11
|
self._ransackers ||= {}
|
12
|
+
self._ransack_aliases ||= {}
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
14
16
|
def ransack(params = {}, options = {})
|
17
|
+
ActiveSupport::Deprecation.warn("#search is deprecated and will be removed in 2.3, please use #ransack instead") if __callee__ == :search
|
15
18
|
Search.new(self, params, options)
|
16
19
|
end
|
17
20
|
|
21
|
+
def ransack!(params = {}, options = {})
|
22
|
+
ransack(params, options.merge(ignore_unknown_conditions: false))
|
23
|
+
end
|
24
|
+
|
18
25
|
def ransacker(name, opts = {}, &block)
|
19
26
|
self._ransackers = _ransackers.merge name.to_s => Ransacker
|
20
27
|
.new(self, name, opts, &block)
|
21
28
|
end
|
22
29
|
|
30
|
+
def ransack_alias(new_name, old_name)
|
31
|
+
self._ransack_aliases = _ransack_aliases.merge new_name.to_s =>
|
32
|
+
old_name.to_s
|
33
|
+
end
|
34
|
+
|
23
35
|
# Ransackable_attributes, by default, returns all column names
|
24
36
|
# and any defined ransackers as an array of strings.
|
25
37
|
# For overriding with a whitelist array of strings.
|
26
38
|
#
|
27
39
|
def ransackable_attributes(auth_object = nil)
|
28
|
-
|
40
|
+
@ransackable_attributes ||= if Ransack::SUPPORTS_ATTRIBUTE_ALIAS
|
41
|
+
column_names + _ransackers.keys + _ransack_aliases.keys +
|
42
|
+
attribute_aliases.keys
|
43
|
+
else
|
44
|
+
column_names + _ransackers.keys + _ransack_aliases.keys
|
45
|
+
end
|
29
46
|
end
|
30
47
|
|
31
48
|
# Ransackable_associations, by default, returns the names
|
@@ -33,7 +50,7 @@ module Ransack
|
|
33
50
|
# For overriding with a whitelist array of strings.
|
34
51
|
#
|
35
52
|
def ransackable_associations(auth_object = nil)
|
36
|
-
reflect_on_all_associations.map { |a| a.name.to_s }
|
53
|
+
@ransackable_associations ||= reflect_on_all_associations.map { |a| a.name.to_s }
|
37
54
|
end
|
38
55
|
|
39
56
|
# Ransortable_attributes, by default, returns the names
|
@@ -52,6 +69,14 @@ module Ransack
|
|
52
69
|
[]
|
53
70
|
end
|
54
71
|
|
72
|
+
# ransack_scope_skip_sanitize_args, by default, returns an empty array.
|
73
|
+
# i.e. use the sanitize_scope_args setting to determin if args should be converted.
|
74
|
+
# For overriding with a list of scopes which should be passed the args as-is.
|
75
|
+
#
|
76
|
+
def ransackable_scopes_skip_sanitize_args
|
77
|
+
[]
|
78
|
+
end
|
79
|
+
|
55
80
|
end
|
56
81
|
end
|
57
82
|
end
|