ransack 1.8.4 → 3.2.1
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 +5 -5
- data/.github/FUNDING.yml +3 -0
- data/.github/SECURITY.md +12 -0
- data/.github/workflows/cronjob.yml +102 -0
- data/.github/workflows/deploy.yml +35 -0
- data/.github/workflows/rubocop.yml +20 -0
- data/.github/workflows/test-deploy.yml +29 -0
- data/.github/workflows/test.yml +130 -0
- data/.gitignore +3 -0
- data/{lib/ransack/adapters/mongoid/3.2/.gitkeep → .nojekyll} +0 -0
- data/.rubocop.yml +44 -0
- data/CHANGELOG.md +352 -0
- data/CONTRIBUTING.md +25 -13
- data/Gemfile +26 -27
- data/README.md +65 -815
- data/Rakefile +1 -22
- 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/.gitignore +19 -0
- data/docs/.nojekyll +0 -0
- data/docs/babel.config.js +3 -0
- data/docs/blog/2022-03-27-ransack-3.0.0.md +20 -0
- data/docs/docs/getting-started/_category_.json +4 -0
- data/docs/docs/getting-started/advanced-mode.md +46 -0
- data/docs/docs/getting-started/configuration.md +47 -0
- data/docs/docs/getting-started/search-matches.md +67 -0
- data/docs/docs/getting-started/simple-mode.md +284 -0
- data/docs/docs/getting-started/sorting.md +79 -0
- data/docs/docs/getting-started/using-predicates.md +282 -0
- data/docs/docs/going-further/_category_.json +4 -0
- data/docs/docs/going-further/acts-as-taggable-on.md +114 -0
- data/docs/docs/going-further/associations.md +70 -0
- data/docs/docs/going-further/custom-predicates.md +52 -0
- data/docs/docs/going-further/documentation.md +43 -0
- data/docs/docs/going-further/exporting-to-csv.md +49 -0
- data/docs/docs/going-further/external-guides.md +57 -0
- data/docs/docs/going-further/form-customisation.md +63 -0
- data/docs/docs/going-further/i18n.md +53 -0
- data/docs/docs/going-further/img/create_release.png +0 -0
- data/docs/docs/going-further/merging-searches.md +41 -0
- data/docs/docs/going-further/other-notes.md +428 -0
- data/docs/docs/going-further/polymorphic-search.md +40 -0
- data/docs/docs/going-further/ransackers.md +331 -0
- data/docs/docs/going-further/release_process.md +36 -0
- data/docs/docs/going-further/saving-queries.md +82 -0
- data/docs/docs/going-further/searching-postgres.md +57 -0
- data/docs/docs/going-further/wiki-contributors.md +82 -0
- data/docs/docs/intro.md +99 -0
- data/docs/docusaurus.config.js +120 -0
- data/docs/package.json +38 -0
- data/docs/sidebars.js +31 -0
- data/docs/src/components/HomepageFeatures/index.js +64 -0
- data/docs/src/components/HomepageFeatures/styles.module.css +11 -0
- data/docs/src/css/custom.css +39 -0
- data/docs/src/pages/index.module.css +23 -0
- data/docs/src/pages/markdown-page.md +7 -0
- data/docs/static/.nojekyll +0 -0
- data/docs/static/img/docusaurus.png +0 -0
- data/docs/static/img/favicon.ico +0 -0
- data/docs/static/img/logo.svg +1 -0
- data/docs/static/img/tutorial/docsVersionDropdown.png +0 -0
- data/docs/static/img/tutorial/localeDropdown.png +0 -0
- data/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
- data/docs/static/img/undraw_docusaurus_react.svg +170 -0
- data/docs/static/img/undraw_docusaurus_tree.svg +40 -0
- data/docs/static/logo/ransack-h.png +0 -0
- data/docs/static/logo/ransack-h.svg +34 -0
- data/docs/static/logo/ransack-v.png +0 -0
- data/docs/static/logo/ransack-v.svg +34 -0
- data/docs/static/logo/ransack.png +0 -0
- data/docs/static/logo/ransack.svg +21 -0
- data/docs/yarn.lock +8436 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +70 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +92 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +11 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/join_dependency.rb +1 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/reflection.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/join_dependency.rb +1 -0
- data/lib/polyamorous/activerecord_7.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/polyamorous.rb +1 -0
- data/lib/ransack/adapters/active_record/base.rb +14 -3
- data/lib/ransack/adapters/active_record/context.rb +140 -196
- data/lib/ransack/adapters/active_record/ransack/constants.rb +19 -4
- data/lib/ransack/adapters/active_record/ransack/context.rb +9 -19
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +7 -7
- 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 +0 -9
- data/lib/ransack/adapters.rb +2 -0
- data/lib/ransack/configuration.rb +52 -2
- data/lib/ransack/constants.rb +1 -5
- data/lib/ransack/context.rb +29 -24
- data/lib/ransack/helpers/form_builder.rb +12 -6
- data/lib/ransack/helpers/form_helper.rb +11 -3
- data/lib/ransack/helpers.rb +1 -1
- 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/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/nl.yml +4 -4
- data/lib/ransack/locale/ru.yml +70 -0
- data/lib/ransack/locale/sk.yml +70 -0
- data/lib/ransack/locale/sv.yml +70 -0
- data/lib/ransack/locale/tr.yml +70 -0
- data/lib/ransack/locale/zh-CN.yml +12 -12
- data/lib/ransack/nodes/attribute.rb +2 -2
- data/lib/ransack/nodes/condition.rb +7 -1
- data/lib/ransack/nodes/grouping.rb +3 -8
- data/lib/ransack/nodes/sort.rb +3 -3
- data/lib/ransack/nodes/value.rb +3 -3
- data/lib/ransack/predicate.rb +13 -20
- data/lib/ransack/search.rb +7 -4
- 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 +7 -5
- data/ransack.gemspec +9 -25
- 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 +13 -0
- data/spec/helpers/ransack_helper.rb +1 -1
- data/spec/polyamorous/activerecord_compatibility_spec.rb +15 -0
- data/spec/polyamorous/join_association_spec.rb +30 -0
- data/spec/polyamorous/join_dependency_spec.rb +81 -0
- data/spec/polyamorous/join_spec.rb +19 -0
- data/spec/ransack/adapters/active_record/base_spec.rb +105 -11
- data/spec/ransack/adapters/active_record/context_spec.rb +63 -24
- data/spec/ransack/configuration_spec.rb +24 -0
- data/spec/ransack/helpers/form_builder_spec.rb +3 -15
- data/spec/ransack/helpers/form_helper_spec.rb +135 -168
- data/spec/ransack/nodes/condition_spec.rb +13 -0
- data/spec/ransack/nodes/grouping_spec.rb +2 -2
- data/spec/ransack/nodes/value_spec.rb +115 -0
- data/spec/ransack/predicate_spec.rb +54 -2
- data/spec/ransack/search_spec.rb +266 -36
- data/spec/spec_helper.rb +14 -5
- data/spec/support/schema.rb +99 -21
- metadata +117 -187
- data/.travis.yml +0 -86
- data/lib/ransack/adapters/active_record/3.0/compat.rb +0 -179
- data/lib/ransack/adapters/active_record/3.0/context.rb +0 -203
- data/lib/ransack/adapters/active_record/3.1/context.rb +0 -212
- 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/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 -134
- data/lib/ransack/adapters/mongoid/context.rb +0 -212
- 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 -15
- data/spec/mongoid/adapters/mongoid/base_spec.rb +0 -314
- data/spec/mongoid/adapters/mongoid/context_spec.rb +0 -56
- data/spec/mongoid/configuration_spec.rb +0 -162
- 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 -49
- data/spec/mongoid/nodes/grouping_spec.rb +0 -13
- data/spec/mongoid/predicate_spec.rb +0 -155
- data/spec/mongoid/search_spec.rb +0 -445
- data/spec/mongoid/support/mongoid.yml +0 -11
- data/spec/mongoid/support/schema.rb +0 -135
- data/spec/mongoid/translate_spec.rb +0 -14
- data/spec/mongoid_spec_helper.rb +0 -63
- data/spec/ransack/dependencies_spec.rb +0 -12
data/.travis.yml
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
language: ruby
|
|
2
|
-
|
|
3
|
-
sudo: false
|
|
4
|
-
|
|
5
|
-
rvm:
|
|
6
|
-
- 2.3.3
|
|
7
|
-
- 2.2.6
|
|
8
|
-
- 2.1.10
|
|
9
|
-
- 2.0
|
|
10
|
-
|
|
11
|
-
env:
|
|
12
|
-
- RAILS=5-0-stable DB=sqlite3
|
|
13
|
-
- RAILS=5-0-stable DB=mysql
|
|
14
|
-
- RAILS=5-0-stable DB=postgres
|
|
15
|
-
|
|
16
|
-
- RAILS=4-2-stable DB=sqlite3
|
|
17
|
-
- RAILS=4-2-stable DB=mysql
|
|
18
|
-
- RAILS=4-2-stable DB=postgres
|
|
19
|
-
|
|
20
|
-
- RAILS=4-1-stable DB=sqlite3
|
|
21
|
-
- RAILS=4-1-stable DB=mysql
|
|
22
|
-
- RAILS=4-1-stable DB=postgres
|
|
23
|
-
|
|
24
|
-
- RAILS=4-0-stable DB=sqlite3
|
|
25
|
-
- RAILS=4-0-stable DB=mysql
|
|
26
|
-
- RAILS=4-0-stable DB=postgres
|
|
27
|
-
|
|
28
|
-
- RAILS=3-2-stable DB=sqlite
|
|
29
|
-
- RAILS=3-2-stable DB=mysql
|
|
30
|
-
- RAILS=3-2-stable DB=postgres
|
|
31
|
-
|
|
32
|
-
- RAILS=3-1-stable DB=sqlite
|
|
33
|
-
- RAILS=3-1-stable DB=mysql
|
|
34
|
-
- RAILS=3-1-stable DB=postgres
|
|
35
|
-
|
|
36
|
-
matrix:
|
|
37
|
-
exclude:
|
|
38
|
-
- rvm: 2.1.10
|
|
39
|
-
env: RAILS=5-0-stable DB=sqlite3
|
|
40
|
-
- rvm: 2.1.10
|
|
41
|
-
env: RAILS=5-0-stable DB=mysql
|
|
42
|
-
- rvm: 2.1.10
|
|
43
|
-
env: RAILS=5-0-stable DB=postgres
|
|
44
|
-
|
|
45
|
-
- rvm: 2.0
|
|
46
|
-
env: RAILS=5-0-stable DB=sqlite3
|
|
47
|
-
- rvm: 2.0
|
|
48
|
-
env: RAILS=5-0-stable DB=mysql
|
|
49
|
-
- rvm: 2.0
|
|
50
|
-
env: RAILS=5-0-stable DB=postgres
|
|
51
|
-
|
|
52
|
-
- rvm: 2.0
|
|
53
|
-
env: RAILS=4-2-stable DB=sqlite3
|
|
54
|
-
- rvm: 2.0
|
|
55
|
-
env: RAILS=4-2-stable DB=mysql
|
|
56
|
-
- rvm: 2.0
|
|
57
|
-
env: RAILS=4-2-stable DB=postgres
|
|
58
|
-
|
|
59
|
-
include:
|
|
60
|
-
- rvm: 2.3.3
|
|
61
|
-
env: RAILS=master DB=sqlite3
|
|
62
|
-
- rvm: 2.3.3
|
|
63
|
-
env: RAILS=master DB=mysql
|
|
64
|
-
- rvm: 2.3.3
|
|
65
|
-
env: RAILS=master DB=postgres
|
|
66
|
-
|
|
67
|
-
- rvm: 2.2.6
|
|
68
|
-
env: RAILS=master DB=sqlite3
|
|
69
|
-
- rvm: 2.2.6
|
|
70
|
-
env: RAILS=master DB=mysql
|
|
71
|
-
- rvm: 2.2.6
|
|
72
|
-
env: RAILS=master DB=postgres
|
|
73
|
-
|
|
74
|
-
allow_failures:
|
|
75
|
-
- env: RAILS=master DB=sqlite3
|
|
76
|
-
- env: RAILS=master DB=mysql
|
|
77
|
-
- env: RAILS=master DB=postgres
|
|
78
|
-
|
|
79
|
-
before_script:
|
|
80
|
-
- mysql -e 'create database ransack collate utf8_general_ci;'
|
|
81
|
-
- mysql -e 'use ransack;show variables like "%character%";show variables like "%collation%";'
|
|
82
|
-
- psql -c 'create database ransack;' -U postgres
|
|
83
|
-
|
|
84
|
-
addons:
|
|
85
|
-
code_climate:
|
|
86
|
-
repo_token: 8b701c4364d51a0217105e08c06922d600cec3d9e60d546a89e3ddfe46e0664e
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
# UGLY, UGLY MONKEY PATCHES FOR BACKWARDS COMPAT!!! AVERT YOUR EYES!!
|
|
2
|
-
if Arel::Nodes::And < Arel::Nodes::Binary
|
|
3
|
-
class Ransack::Visitor
|
|
4
|
-
def visit_Ransack_Nodes_And(object)
|
|
5
|
-
nodes = object.values.map { |o| accept(o) }.compact
|
|
6
|
-
return nil unless nodes.size > 0
|
|
7
|
-
|
|
8
|
-
if nodes.size > 1
|
|
9
|
-
nodes.inject(&:and)
|
|
10
|
-
else
|
|
11
|
-
nodes.first
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
class ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinBase
|
|
18
|
-
def table
|
|
19
|
-
Arel::Table.new(
|
|
20
|
-
table_name,
|
|
21
|
-
:as => aliased_table_name,
|
|
22
|
-
:engine => active_record.arel_engine,
|
|
23
|
-
:columns => active_record.columns
|
|
24
|
-
)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
module Arel
|
|
29
|
-
|
|
30
|
-
class Table
|
|
31
|
-
alias :table_name :name
|
|
32
|
-
|
|
33
|
-
def [] name
|
|
34
|
-
::Arel::Attribute.new self, name.to_sym
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
module Nodes
|
|
39
|
-
class Node
|
|
40
|
-
def not
|
|
41
|
-
Nodes::Not.new self
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
remove_const :And
|
|
46
|
-
class And < Arel::Nodes::Node
|
|
47
|
-
attr_reader :children
|
|
48
|
-
|
|
49
|
-
def initialize children, right = nil
|
|
50
|
-
unless Array === children
|
|
51
|
-
children = [children, right]
|
|
52
|
-
end
|
|
53
|
-
@children = children
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def left
|
|
57
|
-
children.first
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def right
|
|
61
|
-
children[1]
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
class NamedFunction < Arel::Nodes::Function
|
|
66
|
-
attr_accessor :name, :distinct
|
|
67
|
-
|
|
68
|
-
include Arel::Predications
|
|
69
|
-
|
|
70
|
-
def initialize name, expr, aliaz = nil
|
|
71
|
-
super(expr, aliaz)
|
|
72
|
-
@name = name
|
|
73
|
-
@distinct = false
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
class InfixOperation < Binary
|
|
78
|
-
include Arel::Expressions
|
|
79
|
-
include Arel::Predications
|
|
80
|
-
|
|
81
|
-
attr_reader :operator
|
|
82
|
-
|
|
83
|
-
def initialize operator, left, right
|
|
84
|
-
super(left, right)
|
|
85
|
-
@operator = operator
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
class Multiplication < InfixOperation
|
|
90
|
-
def initialize left, right
|
|
91
|
-
super(:*, left, right)
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
class Division < InfixOperation
|
|
96
|
-
def initialize left, right
|
|
97
|
-
super(:/, left, right)
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
class Addition < InfixOperation
|
|
102
|
-
def initialize left, right
|
|
103
|
-
super(:+, left, right)
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
class Subtraction < InfixOperation
|
|
108
|
-
def initialize left, right
|
|
109
|
-
super(:-, left, right)
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
module Visitors
|
|
115
|
-
class ToSql
|
|
116
|
-
def column_for attr
|
|
117
|
-
name = attr.name.to_s
|
|
118
|
-
table = attr.relation.table_name
|
|
119
|
-
|
|
120
|
-
column_cache[table][name]
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def column_cache
|
|
124
|
-
@column_cache ||= Hash.new do |hash, key|
|
|
125
|
-
hash[key] = Hash[
|
|
126
|
-
@engine.connection
|
|
127
|
-
.columns(key, "#{key} Columns")
|
|
128
|
-
.map { |c| [c.name, c] }
|
|
129
|
-
]
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def visit_Arel_Nodes_InfixOperation o
|
|
134
|
-
"#{visit o.left} #{o.operator} #{visit o.right}"
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def visit_Arel_Nodes_NamedFunction o
|
|
138
|
-
"#{
|
|
139
|
-
o.name
|
|
140
|
-
}(#{
|
|
141
|
-
o.distinct ? Ransack::Constants::DISTINCT : ''.freeze
|
|
142
|
-
}#{
|
|
143
|
-
o.expressions.map { |x| visit x }.join(', '.freeze)
|
|
144
|
-
})#{
|
|
145
|
-
o.alias ? " AS #{visit o.alias}" : ''.freeze
|
|
146
|
-
}"
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def visit_Arel_Nodes_And o
|
|
150
|
-
o.children.map { |x| visit x }.join(' AND '.freeze)
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def visit_Arel_Nodes_Not o
|
|
154
|
-
"NOT (#{visit o.expr})"
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def visit_Arel_Nodes_Values o
|
|
158
|
-
"VALUES (#{
|
|
159
|
-
o.expressions.zip(o.columns)
|
|
160
|
-
.map { |value, attr|
|
|
161
|
-
if Nodes::SqlLiteral === value
|
|
162
|
-
visit_Arel_Nodes_SqlLiteral value
|
|
163
|
-
else
|
|
164
|
-
quote(value, attr && column_for(attr))
|
|
165
|
-
end
|
|
166
|
-
}
|
|
167
|
-
.join(', '.freeze)
|
|
168
|
-
})"
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
module Predications
|
|
174
|
-
def as other
|
|
175
|
-
Nodes::As.new self, Nodes::SqlLiteral.new(other)
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
end
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
require 'ransack/context'
|
|
2
|
-
require 'polyamorous'
|
|
3
|
-
require 'ransack/adapters/active_record/3.0/compat'
|
|
4
|
-
|
|
5
|
-
module Ransack
|
|
6
|
-
|
|
7
|
-
module Adapters
|
|
8
|
-
module ActiveRecord
|
|
9
|
-
class Context < ::Ransack::Context
|
|
10
|
-
|
|
11
|
-
# Because the AR::Associations namespace is insane
|
|
12
|
-
if defined? ::ActiveRecord::Associations::ClassMethods::JoinDependency
|
|
13
|
-
JoinDependency = ::ActiveRecord::Associations::ClassMethods::JoinDependency
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Redefine a few things for ActiveRecord 3.0.
|
|
17
|
-
|
|
18
|
-
def initialize(object, options = {})
|
|
19
|
-
super
|
|
20
|
-
@arel_visitor = Arel::Visitors.visitor_for @engine
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def relation_for(object)
|
|
24
|
-
object.scoped
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def evaluate(search, opts = {})
|
|
28
|
-
viz = Visitor.new
|
|
29
|
-
relation = @object.where(viz.accept(search.base))
|
|
30
|
-
if search.sorts.any?
|
|
31
|
-
relation = relation.except(:order)
|
|
32
|
-
.reorder(viz.accept(search.sorts))
|
|
33
|
-
end
|
|
34
|
-
if opts[:distinct]
|
|
35
|
-
relation.select(Constants::DISTINCT + @klass.quoted_table_name +
|
|
36
|
-
Constants::DOT_ASTERIX)
|
|
37
|
-
else
|
|
38
|
-
relation
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def attribute_method?(str, klass = @klass)
|
|
43
|
-
exists = false
|
|
44
|
-
|
|
45
|
-
if ransackable_attribute?(str, klass)
|
|
46
|
-
exists = true
|
|
47
|
-
elsif (segments = str.split(/_/)).size > 1
|
|
48
|
-
remainder = []
|
|
49
|
-
found_assoc = nil
|
|
50
|
-
while !found_assoc && remainder.unshift(segments.pop) &&
|
|
51
|
-
segments.size > 0 do
|
|
52
|
-
assoc, poly_class = unpolymorphize_association(
|
|
53
|
-
segments.join(Constants::UNDERSCORE)
|
|
54
|
-
)
|
|
55
|
-
if found_assoc = get_association(assoc, klass)
|
|
56
|
-
exists = attribute_method?(
|
|
57
|
-
remainder.join(Constants::UNDERSCORE),
|
|
58
|
-
poly_class || found_assoc.klass
|
|
59
|
-
)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
exists
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def table_for(parent)
|
|
68
|
-
parent.table
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def type_for(attr)
|
|
72
|
-
return nil unless attr && attr.valid?
|
|
73
|
-
klassify(attr.parent)
|
|
74
|
-
.columns_hash[attr.arel_attribute.name.to_s]
|
|
75
|
-
.type
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# All dependent JoinAssociation items used in the search query
|
|
79
|
-
#
|
|
80
|
-
def join_associations
|
|
81
|
-
@join_dependency.join_associations
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def join_sources
|
|
85
|
-
raise NotImplementedError,
|
|
86
|
-
"ActiveRecord 3.0 does not use join_sources or support joining relations with Arel::Join nodes. Use join_associations."
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def alias_tracker
|
|
90
|
-
raise NotImplementedError,
|
|
91
|
-
"ActiveRecord 3.0 does not have an alias tracker"
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
private
|
|
95
|
-
|
|
96
|
-
def get_parent_and_attribute_name(str, parent = @base)
|
|
97
|
-
attr_name = nil
|
|
98
|
-
|
|
99
|
-
if ransackable_attribute?(str, klassify(parent))
|
|
100
|
-
attr_name = str
|
|
101
|
-
elsif (segments = str.split(/_/)).size > 1
|
|
102
|
-
remainder = []
|
|
103
|
-
found_assoc = nil
|
|
104
|
-
while remainder.unshift(segments.pop) && segments.size > 0 &&
|
|
105
|
-
!found_assoc do
|
|
106
|
-
assoc, klass = unpolymorphize_association(
|
|
107
|
-
segments.join(Constants::UNDERSCORE)
|
|
108
|
-
)
|
|
109
|
-
if found_assoc = get_association(assoc, parent)
|
|
110
|
-
join = build_or_find_association(
|
|
111
|
-
found_assoc.name, parent, klass
|
|
112
|
-
)
|
|
113
|
-
parent, attr_name = get_parent_and_attribute_name(
|
|
114
|
-
remainder.join(Constants::UNDERSCORE), join
|
|
115
|
-
)
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
[parent, attr_name]
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def get_association(str, parent = @base)
|
|
123
|
-
klass = klassify parent
|
|
124
|
-
ransackable_association?(str, klass) &&
|
|
125
|
-
klass.reflect_on_all_associations.detect { |a| a.name.to_s == str }
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def join_dependency(relation)
|
|
129
|
-
if relation.respond_to?(:join_dependency) # Polyamorous enables this
|
|
130
|
-
relation.join_dependency
|
|
131
|
-
else
|
|
132
|
-
build_join_dependency(relation)
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def build_join_dependency(relation)
|
|
137
|
-
buckets = relation.joins_values.group_by do |join|
|
|
138
|
-
case join
|
|
139
|
-
when String
|
|
140
|
-
Constants::STRING_JOIN
|
|
141
|
-
when Hash, Symbol, Array
|
|
142
|
-
Constants::ASSOCIATION_JOIN
|
|
143
|
-
when ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation
|
|
144
|
-
Constants::STASHED_JOIN
|
|
145
|
-
when Arel::Nodes::Join
|
|
146
|
-
Constants::JOIN_NODE
|
|
147
|
-
else
|
|
148
|
-
raise 'unknown class: %s' % join.class.name
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
association_joins = buckets[Constants::ASSOCIATION_JOIN] || []
|
|
153
|
-
|
|
154
|
-
stashed_association_joins = buckets[Constants::STASHED_JOIN] || []
|
|
155
|
-
|
|
156
|
-
join_nodes = buckets[Constants::JOIN_NODE] || []
|
|
157
|
-
|
|
158
|
-
string_joins = (buckets[Constants::STRING_JOIN] || []).map(&:strip).uniq
|
|
159
|
-
|
|
160
|
-
join_list = relation.send :custom_join_sql, (string_joins + join_nodes)
|
|
161
|
-
|
|
162
|
-
join_dependency = JoinDependency.new(
|
|
163
|
-
relation.klass,
|
|
164
|
-
association_joins,
|
|
165
|
-
join_list
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
join_nodes.each do |join|
|
|
169
|
-
join_dependency.table_aliases[join.left.name.downcase] = 1
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
join_dependency.graft(*stashed_association_joins)
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def build_or_find_association(name, parent = @base, klass = nil)
|
|
176
|
-
found_association = @join_dependency.join_associations
|
|
177
|
-
.detect do |assoc|
|
|
178
|
-
assoc.reflection.name == name &&
|
|
179
|
-
assoc.parent == parent &&
|
|
180
|
-
(!klass || assoc.reflection.klass == klass)
|
|
181
|
-
end
|
|
182
|
-
unless found_association
|
|
183
|
-
@join_dependency.send(
|
|
184
|
-
:build, Polyamorous::Join.new(name, @join_type, klass), parent
|
|
185
|
-
)
|
|
186
|
-
found_association = @join_dependency.join_associations.last
|
|
187
|
-
|
|
188
|
-
default_conditions = found_association.active_record.scoped.arel.constraints
|
|
189
|
-
if default_conditions.any?
|
|
190
|
-
and_default_conditions = "AND #{default_conditions.reduce(&:and).to_sql}"
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
# Leverage the stashed association functionality in AR
|
|
194
|
-
@object = @object.joins(found_association).joins(and_default_conditions)
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
found_association
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
end
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
require 'ransack/context'
|
|
2
|
-
require 'ransack/adapters/active_record/compat'
|
|
3
|
-
require 'polyamorous'
|
|
4
|
-
|
|
5
|
-
module Ransack
|
|
6
|
-
module Adapters
|
|
7
|
-
module ActiveRecord
|
|
8
|
-
class Context < ::Ransack::Context
|
|
9
|
-
|
|
10
|
-
# Redefine a few things for ActiveRecord 3.1.
|
|
11
|
-
|
|
12
|
-
def initialize(object, options = {})
|
|
13
|
-
super
|
|
14
|
-
@arel_visitor = Arel::Visitors.visitor_for @engine
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def relation_for(object)
|
|
18
|
-
object.scoped
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def evaluate(search, opts = {})
|
|
22
|
-
viz = Visitor.new
|
|
23
|
-
relation = @object.where(viz.accept(search.base))
|
|
24
|
-
if search.sorts.any?
|
|
25
|
-
relation = relation.except(:order)
|
|
26
|
-
.reorder(viz.accept(search.sorts))
|
|
27
|
-
end
|
|
28
|
-
if opts[:distinct]
|
|
29
|
-
relation.select(Constants::DISTINCT + @klass.quoted_table_name +
|
|
30
|
-
Constants::DOT_ASTERIX)
|
|
31
|
-
else
|
|
32
|
-
relation
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def attribute_method?(str, klass = @klass)
|
|
37
|
-
exists = false
|
|
38
|
-
|
|
39
|
-
if ransackable_attribute?(str, klass)
|
|
40
|
-
exists = true
|
|
41
|
-
elsif (segments = str.split(/_/)).size > 1
|
|
42
|
-
remainder = []
|
|
43
|
-
found_assoc = nil
|
|
44
|
-
while !found_assoc && remainder.unshift(segments.pop) &&
|
|
45
|
-
segments.size > 0 do
|
|
46
|
-
assoc, poly_class = unpolymorphize_association(
|
|
47
|
-
segments.join(Constants::UNDERSCORE)
|
|
48
|
-
)
|
|
49
|
-
if found_assoc = get_association(assoc, klass)
|
|
50
|
-
exists = attribute_method?(
|
|
51
|
-
remainder.join(Constants::UNDERSCORE),
|
|
52
|
-
poly_class || found_assoc.klass
|
|
53
|
-
)
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
exists
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def table_for(parent)
|
|
62
|
-
parent.table
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def type_for(attr)
|
|
66
|
-
return nil unless attr && attr.valid?
|
|
67
|
-
name = attr.arel_attribute.name.to_s
|
|
68
|
-
table = attr.arel_attribute.relation.table_name
|
|
69
|
-
|
|
70
|
-
unless @engine.connection_pool.table_exists?(table)
|
|
71
|
-
raise "No table named #{table} exists"
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
@engine.connection_pool.columns_hash[table][name].type
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def join_associations
|
|
78
|
-
@join_dependency.join_associations
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# All dependent Arel::Join nodes used in the search query
|
|
82
|
-
#
|
|
83
|
-
# This could otherwise be done as `@object.arel.join_sources`, except
|
|
84
|
-
# that ActiveRecord's build_joins sets up its own JoinDependency.
|
|
85
|
-
# This extracts what we need to access the joins using our existing
|
|
86
|
-
# JoinDependency to track table aliases.
|
|
87
|
-
#
|
|
88
|
-
def join_sources
|
|
89
|
-
base = Arel::SelectManager.new(@object.engine, @object.table)
|
|
90
|
-
@object.joins_values.each do |assoc|
|
|
91
|
-
next unless assoc.is_a?(JoinDependency::JoinAssociation)
|
|
92
|
-
assoc.join_to(base)
|
|
93
|
-
end
|
|
94
|
-
base.join_sources
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def alias_tracker
|
|
98
|
-
@join_dependency.alias_tracker
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
private
|
|
102
|
-
|
|
103
|
-
def get_parent_and_attribute_name(str, parent = @base)
|
|
104
|
-
attr_name = nil
|
|
105
|
-
|
|
106
|
-
if ransackable_attribute?(str, klassify(parent))
|
|
107
|
-
attr_name = str
|
|
108
|
-
elsif (segments = str.split(/_/)).size > 1
|
|
109
|
-
remainder = []
|
|
110
|
-
found_assoc = nil
|
|
111
|
-
while remainder.unshift(segments.pop) && segments.size > 0 &&
|
|
112
|
-
!found_assoc do
|
|
113
|
-
assoc, klass = unpolymorphize_association(
|
|
114
|
-
segments.join(Constants::UNDERSCORE)
|
|
115
|
-
)
|
|
116
|
-
if found_assoc = get_association(assoc, parent)
|
|
117
|
-
join = build_or_find_association(
|
|
118
|
-
found_assoc.name, parent, klass
|
|
119
|
-
)
|
|
120
|
-
parent, attr_name = get_parent_and_attribute_name(
|
|
121
|
-
remainder.join(Constants::UNDERSCORE), join
|
|
122
|
-
)
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
[parent, attr_name]
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def get_association(str, parent = @base)
|
|
131
|
-
klass = klassify parent
|
|
132
|
-
ransackable_association?(str, klass) &&
|
|
133
|
-
klass.reflect_on_all_associations.detect { |a| a.name.to_s == str }
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def join_dependency(relation)
|
|
137
|
-
if relation.respond_to?(:join_dependency) # Polyamorous enables this
|
|
138
|
-
relation.join_dependency
|
|
139
|
-
else
|
|
140
|
-
build_join_dependency(relation)
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
def build_join_dependency(relation)
|
|
145
|
-
buckets = relation.joins_values.group_by do |join|
|
|
146
|
-
case join
|
|
147
|
-
when String
|
|
148
|
-
Constants::STRING_JOIN
|
|
149
|
-
when Hash, Symbol, Array
|
|
150
|
-
Constants::ASSOCIATION_JOIN
|
|
151
|
-
when JoinDependency::JoinAssociation
|
|
152
|
-
Constants::STASHED_JOIN
|
|
153
|
-
when Arel::Nodes::Join
|
|
154
|
-
Constants::JOIN_NODE
|
|
155
|
-
else
|
|
156
|
-
raise 'unknown class: %s' % join.class.name
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
association_joins = buckets[Constants::ASSOCIATION_JOIN] || []
|
|
161
|
-
|
|
162
|
-
stashed_association_joins = buckets[Constants::STASHED_JOIN] || []
|
|
163
|
-
|
|
164
|
-
join_nodes = buckets[Constants::JOIN_NODE] || []
|
|
165
|
-
|
|
166
|
-
string_joins = (buckets[Constants::STRING_JOIN] || []).map(&:strip).uniq
|
|
167
|
-
|
|
168
|
-
join_list = relation.send :custom_join_ast,
|
|
169
|
-
relation.table.from(relation.table), string_joins
|
|
170
|
-
|
|
171
|
-
join_dependency = JoinDependency.new(
|
|
172
|
-
relation.klass,
|
|
173
|
-
association_joins,
|
|
174
|
-
join_list
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
join_nodes.each do |join|
|
|
178
|
-
join_dependency.alias_tracker.aliases[join.left.name.downcase] = 1
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
join_dependency.graft(*stashed_association_joins)
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
def build_or_find_association(name, parent = @base, klass = nil)
|
|
185
|
-
found_association = @join_dependency.join_associations
|
|
186
|
-
.detect do |assoc|
|
|
187
|
-
assoc.reflection.name == name &&
|
|
188
|
-
assoc.parent == parent &&
|
|
189
|
-
(!klass || assoc.reflection.klass == klass)
|
|
190
|
-
end
|
|
191
|
-
unless found_association
|
|
192
|
-
@join_dependency.send(
|
|
193
|
-
:build, Polyamorous::Join.new(name, @join_type, klass), parent
|
|
194
|
-
)
|
|
195
|
-
found_association = @join_dependency.join_associations.last
|
|
196
|
-
|
|
197
|
-
default_conditions = found_association.active_record.scoped.arel.constraints
|
|
198
|
-
if default_conditions.any?
|
|
199
|
-
and_default_conditions = "AND #{default_conditions.reduce(&:and).to_sql}"
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
# Leverage the stashed association functionality in AR
|
|
203
|
-
@object = @object.joins(found_association).joins(and_default_conditions)
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
found_association
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
end
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
end
|