ransack 1.7.0 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +5 -5
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/SECURITY.md +12 -0
  4. data/.github/workflows/test.yml +120 -0
  5. data/.gitignore +3 -0
  6. data/CHANGELOG.md +463 -27
  7. data/CONTRIBUTING.md +52 -22
  8. data/Gemfile +24 -24
  9. data/README.md +453 -126
  10. data/Rakefile +6 -25
  11. data/lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb +24 -0
  12. data/lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb +79 -0
  13. data/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb +11 -0
  14. data/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +1 -0
  15. data/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +80 -0
  16. data/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +1 -0
  17. data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +74 -0
  18. data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +93 -0
  19. data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +1 -0
  20. data/lib/polyamorous/join.rb +70 -0
  21. data/lib/polyamorous/polyamorous.rb +24 -0
  22. data/lib/polyamorous/swapping_reflection_class.rb +11 -0
  23. data/lib/polyamorous/tree_node.rb +7 -0
  24. data/lib/ransack/adapters/active_record/base.rb +27 -2
  25. data/lib/ransack/adapters/active_record/context.rb +213 -139
  26. data/lib/ransack/adapters/active_record/ransack/constants.rb +70 -55
  27. data/lib/ransack/adapters/active_record/ransack/context.rb +10 -18
  28. data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +42 -32
  29. data/lib/ransack/adapters/active_record/ransack/translate.rb +1 -5
  30. data/lib/ransack/adapters/active_record/ransack/visitor.rb +23 -0
  31. data/lib/ransack/adapters/active_record.rb +11 -10
  32. data/lib/ransack/adapters.rb +45 -23
  33. data/lib/ransack/configuration.rb +107 -4
  34. data/lib/ransack/constants.rb +13 -26
  35. data/lib/ransack/context.rb +45 -33
  36. data/lib/ransack/helpers/form_builder.rb +21 -12
  37. data/lib/ransack/helpers/form_helper.rb +75 -70
  38. data/lib/ransack/locale/ar.yml +70 -0
  39. data/lib/ransack/locale/az.yml +70 -0
  40. data/lib/ransack/locale/bg.yml +70 -0
  41. data/lib/ransack/locale/ca.yml +70 -0
  42. data/lib/ransack/locale/da.yml +70 -0
  43. data/lib/ransack/locale/el.yml +70 -0
  44. data/lib/ransack/locale/es.yml +22 -22
  45. data/lib/ransack/locale/fa.yml +70 -0
  46. data/lib/ransack/locale/fi.yml +71 -0
  47. data/lib/ransack/locale/id.yml +70 -0
  48. data/lib/ransack/locale/it.yml +70 -0
  49. data/lib/ransack/locale/ja.yml +70 -0
  50. data/lib/ransack/locale/nl.yml +4 -4
  51. data/lib/ransack/locale/pt-BR.yml +70 -0
  52. data/lib/ransack/locale/ru.yml +70 -0
  53. data/lib/ransack/locale/sk.yml +70 -0
  54. data/lib/ransack/locale/tr.yml +70 -0
  55. data/lib/ransack/locale/{zh.yml → zh-CN.yml} +13 -13
  56. data/lib/ransack/locale/zh-TW.yml +70 -0
  57. data/lib/ransack/nodes/attribute.rb +5 -2
  58. data/lib/ransack/nodes/bindable.rb +18 -6
  59. data/lib/ransack/nodes/condition.rb +85 -28
  60. data/lib/ransack/nodes/grouping.rb +17 -11
  61. data/lib/ransack/nodes/sort.rb +9 -5
  62. data/lib/ransack/nodes/value.rb +74 -68
  63. data/lib/ransack/nodes.rb +1 -1
  64. data/lib/ransack/predicate.rb +17 -20
  65. data/lib/ransack/search.rb +17 -8
  66. data/lib/ransack/translate.rb +115 -115
  67. data/lib/ransack/version.rb +1 -1
  68. data/lib/ransack/visitor.rb +1 -12
  69. data/lib/ransack.rb +9 -9
  70. data/logo/ransack-h.png +0 -0
  71. data/logo/ransack-h.svg +34 -0
  72. data/logo/ransack-v.png +0 -0
  73. data/logo/ransack-v.svg +34 -0
  74. data/logo/ransack.png +0 -0
  75. data/logo/ransack.svg +21 -0
  76. data/ransack.gemspec +7 -24
  77. data/spec/console.rb +4 -0
  78. data/spec/helpers/polyamorous_helper.rb +19 -0
  79. data/spec/polyamorous/join_association_spec.rb +35 -0
  80. data/spec/polyamorous/join_dependency_spec.rb +97 -0
  81. data/spec/polyamorous/join_spec.rb +19 -0
  82. data/spec/ransack/adapters/active_record/base_spec.rb +370 -75
  83. data/spec/ransack/adapters/active_record/context_spec.rb +72 -34
  84. data/spec/ransack/configuration_spec.rb +97 -14
  85. data/spec/ransack/helpers/form_builder_spec.rb +2 -11
  86. data/spec/ransack/helpers/form_helper_spec.rb +481 -113
  87. data/spec/ransack/nodes/condition_spec.rb +24 -0
  88. data/spec/ransack/nodes/grouping_spec.rb +56 -0
  89. data/spec/ransack/predicate_spec.rb +79 -5
  90. data/spec/ransack/search_spec.rb +207 -81
  91. data/spec/spec_helper.rb +8 -0
  92. data/spec/support/schema.rb +100 -42
  93. metadata +57 -184
  94. data/.travis.yml +0 -69
  95. data/lib/ransack/adapters/active_record/3.0/compat.rb +0 -179
  96. data/lib/ransack/adapters/active_record/3.0/context.rb +0 -201
  97. data/lib/ransack/adapters/active_record/3.1/context.rb +0 -215
  98. data/lib/ransack/adapters/active_record/3.2/context.rb +0 -44
  99. data/lib/ransack/adapters/active_record/compat.rb +0 -14
  100. data/lib/ransack/adapters/mongoid/3.2/.gitkeep +0 -0
  101. data/lib/ransack/adapters/mongoid/attributes/attribute.rb +0 -37
  102. data/lib/ransack/adapters/mongoid/attributes/order_predications.rb +0 -17
  103. data/lib/ransack/adapters/mongoid/attributes/predications.rb +0 -141
  104. data/lib/ransack/adapters/mongoid/base.rb +0 -130
  105. data/lib/ransack/adapters/mongoid/context.rb +0 -208
  106. data/lib/ransack/adapters/mongoid/inquiry_hash.rb +0 -23
  107. data/lib/ransack/adapters/mongoid/ransack/constants.rb +0 -88
  108. data/lib/ransack/adapters/mongoid/ransack/context.rb +0 -60
  109. data/lib/ransack/adapters/mongoid/ransack/nodes/condition.rb +0 -27
  110. data/lib/ransack/adapters/mongoid/ransack/translate.rb +0 -13
  111. data/lib/ransack/adapters/mongoid/ransack/visitor.rb +0 -24
  112. data/lib/ransack/adapters/mongoid/table.rb +0 -35
  113. data/lib/ransack/adapters/mongoid.rb +0 -13
  114. data/spec/mongoid/adapters/mongoid/base_spec.rb +0 -276
  115. data/spec/mongoid/adapters/mongoid/context_spec.rb +0 -56
  116. data/spec/mongoid/configuration_spec.rb +0 -102
  117. data/spec/mongoid/dependencies_spec.rb +0 -8
  118. data/spec/mongoid/helpers/ransack_helper.rb +0 -11
  119. data/spec/mongoid/nodes/condition_spec.rb +0 -34
  120. data/spec/mongoid/nodes/grouping_spec.rb +0 -13
  121. data/spec/mongoid/predicate_spec.rb +0 -155
  122. data/spec/mongoid/search_spec.rb +0 -446
  123. data/spec/mongoid/support/mongoid.yml +0 -6
  124. data/spec/mongoid/support/schema.rb +0 -128
  125. data/spec/mongoid/translate_spec.rb +0 -14
  126. data/spec/mongoid_spec_helper.rb +0 -59
  127. 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
- rspec.rspec_opts = ['--backtrace']
9
- end
10
-
11
- RSpec::Core::RakeTask.new(:mongoid) do |rspec|
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
- if ENV['DB'] =~ /mongodb/
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 'mongoid'
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,11 @@
1
+ module Polyamorous
2
+ module ReflectionExtensions
3
+ def join_scope(table, foreign_table, foreign_klass)
4
+ if respond_to?(:polymorphic?) && polymorphic?
5
+ super.where!(foreign_table[foreign_type].eq(klass.name))
6
+ else
7
+ super
8
+ end
9
+ end
10
+ end
11
+ 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
@@ -0,0 +1,7 @@
1
+ module Polyamorous
2
+ module TreeNode
3
+ def add_to_tree(hash)
4
+ raise NotImplementedError
5
+ end
6
+ end
7
+ 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
- column_names + _ransackers.keys
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