ransack 1.1.0 → 1.2.0
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/.travis.yml +12 -4
- data/CONTRIBUTING.md +10 -4
- data/Gemfile +12 -9
- data/README.md +46 -11
- data/lib/ransack.rb +4 -2
- data/lib/ransack/adapters/active_record.rb +1 -1
- data/lib/ransack/adapters/active_record/3.0/compat.rb +16 -6
- data/lib/ransack/adapters/active_record/3.0/context.rb +32 -16
- data/lib/ransack/adapters/active_record/3.1/context.rb +32 -15
- data/lib/ransack/adapters/active_record/3.2/context.rb +1 -1
- data/lib/ransack/adapters/active_record/base.rb +9 -6
- data/lib/ransack/adapters/active_record/context.rb +193 -2
- data/lib/ransack/configuration.rb +4 -4
- data/lib/ransack/constants.rb +81 -18
- data/lib/ransack/context.rb +27 -12
- data/lib/ransack/helpers/form_builder.rb +126 -91
- data/lib/ransack/helpers/form_helper.rb +34 -12
- data/lib/ransack/naming.rb +2 -1
- data/lib/ransack/nodes/attribute.rb +6 -4
- data/lib/ransack/nodes/bindable.rb +3 -1
- data/lib/ransack/nodes/condition.rb +40 -27
- data/lib/ransack/nodes/grouping.rb +19 -13
- data/lib/ransack/nodes/node.rb +3 -3
- data/lib/ransack/nodes/sort.rb +5 -3
- data/lib/ransack/nodes/value.rb +2 -2
- data/lib/ransack/predicate.rb +18 -9
- data/lib/ransack/ransacker.rb +4 -4
- data/lib/ransack/search.rb +9 -12
- data/lib/ransack/translate.rb +42 -21
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +4 -4
- data/ransack.gemspec +17 -7
- data/spec/blueprints/notes.rb +2 -0
- data/spec/blueprints/people.rb +4 -1
- data/spec/console.rb +3 -3
- data/spec/ransack/adapters/active_record/base_spec.rb +149 -22
- data/spec/ransack/adapters/active_record/context_spec.rb +5 -5
- data/spec/ransack/configuration_spec.rb +17 -8
- data/spec/ransack/dependencies_spec.rb +8 -0
- data/spec/ransack/helpers/form_builder_spec.rb +37 -14
- data/spec/ransack/helpers/form_helper_spec.rb +5 -5
- data/spec/ransack/predicate_spec.rb +6 -3
- data/spec/ransack/search_spec.rb +95 -73
- data/spec/ransack/translate_spec.rb +14 -0
- data/spec/spec_helper.rb +14 -8
- data/spec/support/en.yml +6 -0
- data/spec/support/schema.rb +76 -31
- metadata +48 -29
@@ -26,10 +26,11 @@ module Ransack
|
|
26
26
|
end
|
27
27
|
|
28
28
|
describe '#sort_link with default search_key' do
|
29
|
-
subject {
|
30
|
-
|
31
|
-
[:main_app, Person.search(:
|
32
|
-
:name,
|
29
|
+
subject { @controller.view_context.
|
30
|
+
sort_link(
|
31
|
+
[:main_app, Person.search(sorts: ['name desc'])],
|
32
|
+
:name,
|
33
|
+
controller: 'people'
|
33
34
|
)
|
34
35
|
}
|
35
36
|
it { should match(
|
@@ -75,7 +76,6 @@ module Ransack
|
|
75
76
|
}
|
76
77
|
end
|
77
78
|
|
78
|
-
|
79
79
|
context 'view has existing parameters' do
|
80
80
|
before do
|
81
81
|
@controller.view_context.params.merge!({ :exist => 'existing' })
|
@@ -22,14 +22,17 @@ module Ransack
|
|
22
22
|
describe 'eq' do
|
23
23
|
it 'generates an equality condition for boolean true' do
|
24
24
|
@s.awesome_eq = true
|
25
|
-
field = "#{quote_table_name("people")}.#{
|
26
|
-
|
25
|
+
field = "#{quote_table_name("people")}.#{
|
26
|
+
quote_column_name("awesome")}"
|
27
|
+
@s.result.to_sql.should match /#{field} = #{
|
28
|
+
ActiveRecord::Base.connection.quoted_true}/
|
27
29
|
end
|
28
30
|
|
29
31
|
it 'generates an equality condition for boolean false' do
|
30
32
|
@s.awesome_eq = false
|
31
33
|
field = "#{quote_table_name("people")}.#{quote_column_name("awesome")}"
|
32
|
-
@s.result.to_sql.should match /#{field} = #{
|
34
|
+
@s.result.to_sql.should match /#{field} = #{
|
35
|
+
ActiveRecord::Base.connection.quoted_false}/
|
33
36
|
end
|
34
37
|
|
35
38
|
it 'does not generate a condition for nil' do
|
data/spec/ransack/search_spec.rb
CHANGED
@@ -3,9 +3,15 @@ require 'spec_helper'
|
|
3
3
|
module Ransack
|
4
4
|
describe Search do
|
5
5
|
|
6
|
+
describe '#initialize' do
|
7
|
+
it 'does not raise exception for string :params argument' do
|
8
|
+
lambda { Search.new(Person, '') }.should_not raise_error
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
6
12
|
describe '#build' do
|
7
|
-
it 'creates
|
8
|
-
search = Search.new(Person, :
|
13
|
+
it 'creates conditions for top-level attributes' do
|
14
|
+
search = Search.new(Person, name_eq: 'Ernie')
|
9
15
|
condition = search.base[:name_eq]
|
10
16
|
condition.should be_a Nodes::Condition
|
11
17
|
condition.predicate.name.should eq 'eq'
|
@@ -13,8 +19,8 @@ module Ransack
|
|
13
19
|
condition.value.should eq 'Ernie'
|
14
20
|
end
|
15
21
|
|
16
|
-
it 'creates
|
17
|
-
search = Search.new(Person, :
|
22
|
+
it 'creates conditions for association attributes' do
|
23
|
+
search = Search.new(Person, children_name_eq: 'Ernie')
|
18
24
|
condition = search.base[:children_name_eq]
|
19
25
|
condition.should be_a Nodes::Condition
|
20
26
|
condition.predicate.name.should eq 'eq'
|
@@ -22,8 +28,8 @@ module Ransack
|
|
22
28
|
condition.value.should eq 'Ernie'
|
23
29
|
end
|
24
30
|
|
25
|
-
it 'creates
|
26
|
-
search = Search.new(Note, :
|
31
|
+
it 'creates conditions for polymorphic belongs_to association attributes' do
|
32
|
+
search = Search.new(Note, notable_of_Person_type_name_eq: 'Ernie')
|
27
33
|
condition = search.base[:notable_of_Person_type_name_eq]
|
28
34
|
condition.should be_a Nodes::Condition
|
29
35
|
condition.predicate.name.should eq 'eq'
|
@@ -31,9 +37,9 @@ module Ransack
|
|
31
37
|
condition.value.should eq 'Ernie'
|
32
38
|
end
|
33
39
|
|
34
|
-
it 'creates
|
40
|
+
it 'creates conditions for multiple polymorphic belongs_to association attributes' do
|
35
41
|
search = Search.new(Note,
|
36
|
-
:
|
42
|
+
notable_of_Person_type_name_or_notable_of_Article_type_title_eq: 'Ernie')
|
37
43
|
condition = search.
|
38
44
|
base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
|
39
45
|
condition.should be_a Nodes::Condition
|
@@ -44,16 +50,16 @@ module Ransack
|
|
44
50
|
end
|
45
51
|
|
46
52
|
it 'discards empty conditions' do
|
47
|
-
search = Search.new(Person, :
|
53
|
+
search = Search.new(Person, children_name_eq: '')
|
48
54
|
condition = search.base[:children_name_eq]
|
49
55
|
condition.should be_nil
|
50
56
|
end
|
51
57
|
|
52
58
|
it 'accepts arrays of groupings' do
|
53
59
|
search = Search.new(Person,
|
54
|
-
:
|
55
|
-
{ :
|
56
|
-
{ :
|
60
|
+
g: [
|
61
|
+
{ m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie' },
|
62
|
+
{ m: 'or', name_eq: 'Bert', children_name_eq: 'Bert' },
|
57
63
|
]
|
58
64
|
)
|
59
65
|
ors = search.groupings
|
@@ -67,9 +73,9 @@ module Ransack
|
|
67
73
|
|
68
74
|
it 'accepts "attributes" hashes for groupings' do
|
69
75
|
search = Search.new(Person,
|
70
|
-
:
|
71
|
-
'0' => { :
|
72
|
-
'1' => { :
|
76
|
+
g: {
|
77
|
+
'0' => { m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie' },
|
78
|
+
'1' => { m: 'or', name_eq: 'Bert', children_name_eq: 'Bert' },
|
73
79
|
}
|
74
80
|
)
|
75
81
|
ors = search.groupings
|
@@ -85,20 +91,22 @@ module Ransack
|
|
85
91
|
search = Search.new(Person,
|
86
92
|
:c => {
|
87
93
|
'0' => { :a => ['name'], :p => 'eq', :v => ['Ernie'] },
|
88
|
-
'1' => { :a => ['children_name', 'parent_name'],
|
89
|
-
|
94
|
+
'1' => { :a => ['children_name', 'parent_name'],
|
95
|
+
:p => 'eq', :v => ['Ernie'], :m => 'or' }
|
96
|
+
}
|
90
97
|
)
|
91
98
|
conditions = search.base.conditions
|
92
99
|
conditions.should have(2).items
|
93
|
-
conditions.map {|c| c.class}
|
100
|
+
conditions.map { |c| c.class }
|
101
|
+
.should eq [Nodes::Condition, Nodes::Condition]
|
94
102
|
end
|
95
103
|
|
96
|
-
it 'creates
|
104
|
+
it 'creates conditions for custom predicates that take arrays' do
|
97
105
|
Ransack.configure do |config|
|
98
106
|
config.add_predicate 'ary_pred', :wants_array => true
|
99
107
|
end
|
100
108
|
|
101
|
-
search = Search.new(Person, :
|
109
|
+
search = Search.new(Person, name_ary_pred: ['Ernie', 'Bert'])
|
102
110
|
condition = search.base[:name_ary_pred]
|
103
111
|
condition.should be_a Nodes::Condition
|
104
112
|
condition.predicate.name.should eq 'ary_pred'
|
@@ -107,56 +115,59 @@ module Ransack
|
|
107
115
|
end
|
108
116
|
|
109
117
|
it 'does not evaluate the query on #inspect' do
|
110
|
-
search = Search.new(Person, :
|
118
|
+
search = Search.new(Person, children_id_in: [1, 2, 3])
|
111
119
|
search.inspect.should_not match /ActiveRecord/
|
112
120
|
end
|
113
121
|
end
|
114
122
|
|
115
123
|
describe '#result' do
|
116
|
-
let(:people_name_field) {
|
117
|
-
|
124
|
+
let(:people_name_field) {
|
125
|
+
"#{quote_table_name("people")}.#{quote_column_name("name")}"
|
126
|
+
}
|
127
|
+
let(:children_people_name_field) {
|
128
|
+
"#{quote_table_name("children_people")}.#{quote_column_name("name")}"
|
129
|
+
}
|
118
130
|
it 'evaluates conditions contextually' do
|
119
|
-
search = Search.new(Person, :
|
131
|
+
search = Search.new(Person, children_name_eq: 'Ernie')
|
120
132
|
search.result.should be_an ActiveRecord::Relation
|
121
133
|
where = search.result.where_values.first
|
122
134
|
where.to_sql.should match /#{children_people_name_field} = 'Ernie'/
|
123
135
|
end
|
124
136
|
|
125
137
|
it 'evaluates compound conditions contextually' do
|
126
|
-
search = Search.new(Person, :
|
138
|
+
search = Search.new(Person, children_name_or_name_eq: 'Ernie')
|
127
139
|
search.result.should be_an ActiveRecord::Relation
|
128
140
|
where = search.result.where_values.first
|
129
|
-
where.to_sql.should match /#{children_people_name_field
|
141
|
+
where.to_sql.should match /#{children_people_name_field
|
142
|
+
} = 'Ernie' OR #{people_name_field} = 'Ernie'/
|
130
143
|
end
|
131
144
|
|
132
145
|
it 'evaluates polymorphic belongs_to association conditions contextually' do
|
133
|
-
search = Search.new(Note, :
|
146
|
+
search = Search.new(Note, notable_of_Person_type_name_eq: 'Ernie')
|
134
147
|
search.result.should be_an ActiveRecord::Relation
|
135
148
|
where = search.result.where_values.first
|
136
149
|
where.to_sql.should match /#{people_name_field} = 'Ernie'/
|
137
150
|
end
|
138
151
|
|
139
152
|
it 'evaluates nested conditions' do
|
140
|
-
search = Search.new(Person, :
|
141
|
-
:
|
142
|
-
{ :
|
143
|
-
:name_eq => 'Ernie',
|
144
|
-
:children_children_name_eq => 'Ernie'
|
145
|
-
}
|
153
|
+
search = Search.new(Person, children_name_eq: 'Ernie',
|
154
|
+
g: [
|
155
|
+
{ m: 'or', name_eq: 'Ernie', children_children_name_eq: 'Ernie' }
|
146
156
|
]
|
147
157
|
)
|
148
158
|
search.result.should be_an ActiveRecord::Relation
|
149
159
|
where = search.result.where_values.first
|
150
160
|
where.to_sql.should match /#{children_people_name_field} = 'Ernie'/
|
151
161
|
where.to_sql.should match /#{people_name_field} = 'Ernie'/
|
152
|
-
where.to_sql.should match /#{quote_table_name("children_people_2")
|
162
|
+
where.to_sql.should match /#{quote_table_name("children_people_2")
|
163
|
+
}.#{quote_column_name("name")} = 'Ernie'/
|
153
164
|
end
|
154
165
|
|
155
166
|
it 'evaluates arrays of groupings' do
|
156
167
|
search = Search.new(Person,
|
157
|
-
:
|
158
|
-
{ :
|
159
|
-
{ :
|
168
|
+
g: [
|
169
|
+
{ m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie'},
|
170
|
+
{ m: 'or', name_eq: 'Bert', children_name_eq: 'Bert'},
|
160
171
|
]
|
161
172
|
)
|
162
173
|
search.result.should be_an ActiveRecord::Relation
|
@@ -169,26 +180,42 @@ module Ransack
|
|
169
180
|
second.should match /#{children_people_name_field} = 'Bert'/
|
170
181
|
end
|
171
182
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
:
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
183
|
+
if ::ActiveRecord::VERSION::STRING >= "4"
|
184
|
+
it 'returns distinct records when passed distinct: true' do
|
185
|
+
search = Search.new(
|
186
|
+
Person, g: [
|
187
|
+
{ m: 'or',
|
188
|
+
comments_body_cont: 'e',
|
189
|
+
articles_comments_body_cont: 'e'
|
190
|
+
}
|
191
|
+
]
|
192
|
+
)
|
193
|
+
search.result.load.should have(9000).items
|
194
|
+
search.result(distinct: true).should have(10).items
|
195
|
+
search.result.load.uniq.should eq search.result(distinct: true).load
|
196
|
+
end
|
197
|
+
else
|
198
|
+
it 'returns distinct records when passed :distinct => true' do
|
199
|
+
search = Search.new(
|
200
|
+
Person, :g => [
|
201
|
+
{ :m => 'or',
|
202
|
+
:comments_body_cont => 'e',
|
203
|
+
:articles_comments_body_cont => 'e'
|
204
|
+
}
|
205
|
+
]
|
206
|
+
)
|
207
|
+
if ActiveRecord::VERSION::MAJOR == 3
|
208
|
+
all_or_load, uniq_or_distinct = :all, :uniq
|
209
|
+
else
|
210
|
+
all_or_load, uniq_or_distinct = :load, :distinct
|
211
|
+
end
|
212
|
+
search.result.send(all_or_load).
|
213
|
+
should have(9000).items
|
214
|
+
search.result(:distinct => true).
|
215
|
+
should have(10).items
|
216
|
+
search.result.send(all_or_load).send(uniq_or_distinct).
|
217
|
+
should eq search.result(:distinct => true).send(all_or_load)
|
185
218
|
end
|
186
|
-
search.result.send(all_or_load).
|
187
|
-
should have(920).items
|
188
|
-
search.result(:distinct => true).
|
189
|
-
should have(330).items
|
190
|
-
search.result.send(all_or_load).send(uniq_or_distinct).
|
191
|
-
should eq search.result(:distinct => true).send(all_or_load)
|
192
219
|
end
|
193
220
|
end
|
194
221
|
|
@@ -225,7 +252,7 @@ module Ransack
|
|
225
252
|
end
|
226
253
|
|
227
254
|
it 'creates sorts based on multiple attributes/directions in array format' do
|
228
|
-
@s.sorts = ['id desc', 'name asc']
|
255
|
+
@s.sorts = ['id desc', { name: 'name', dir: 'asc' }]
|
229
256
|
@s.sorts.should have(2).items
|
230
257
|
sort1, sort2 = @s.sorts
|
231
258
|
sort1.should be_a Nodes::Sort
|
@@ -237,7 +264,7 @@ module Ransack
|
|
237
264
|
end
|
238
265
|
|
239
266
|
it 'creates sorts based on multiple attributes and uppercase directions in array format' do
|
240
|
-
@s.sorts = ['id DESC', 'name ASC']
|
267
|
+
@s.sorts = ['id DESC', { name: 'name', dir: 'ASC' }]
|
241
268
|
@s.sorts.should have(2).items
|
242
269
|
sort1, sort2 = @s.sorts
|
243
270
|
sort1.should be_a Nodes::Sort
|
@@ -249,7 +276,7 @@ module Ransack
|
|
249
276
|
end
|
250
277
|
|
251
278
|
it 'creates sorts based on multiple attributes and different directions in array format' do
|
252
|
-
@s.sorts = ['id DESC', 'name']
|
279
|
+
@s.sorts = ['id DESC', { name: 'name', dir: nil }]
|
253
280
|
@s.sorts.should have(2).items
|
254
281
|
sort1, sort2 = @s.sorts
|
255
282
|
sort1.should be_a Nodes::Sort
|
@@ -262,8 +289,8 @@ module Ransack
|
|
262
289
|
|
263
290
|
it 'creates sorts based on multiple attributes/directions in hash format' do
|
264
291
|
@s.sorts = {
|
265
|
-
'0' => { :
|
266
|
-
'1' => { :
|
292
|
+
'0' => { name: 'id', dir: 'desc' },
|
293
|
+
'1' => { name: 'name', dir: 'asc' }
|
267
294
|
}
|
268
295
|
@s.sorts.should have(2).items
|
269
296
|
@s.sorts.should be_all { |s| Nodes::Sort === s }
|
@@ -275,8 +302,8 @@ module Ransack
|
|
275
302
|
|
276
303
|
it 'creates sorts based on multiple attributes and uppercase directions in hash format' do
|
277
304
|
@s.sorts = {
|
278
|
-
'0' => { :
|
279
|
-
'1' => { :
|
305
|
+
'0' => { name: 'id', dir: 'DESC' },
|
306
|
+
'1' => { name: 'name', dir: 'ASC' }
|
280
307
|
}
|
281
308
|
@s.sorts.should have(2).items
|
282
309
|
@s.sorts.should be_all { |s| Nodes::Sort === s }
|
@@ -288,8 +315,8 @@ module Ransack
|
|
288
315
|
|
289
316
|
it 'creates sorts based on multiple attributes and different directions in hash format' do
|
290
317
|
@s.sorts = {
|
291
|
-
'0' => { :
|
292
|
-
'1' => { :
|
318
|
+
'0' => { name: 'id', dir: 'DESC' },
|
319
|
+
'1' => { name: 'name', dir: nil }
|
293
320
|
}
|
294
321
|
@s.sorts.should have(2).items
|
295
322
|
@s.sorts.should be_all { |s| Nodes::Sort === s }
|
@@ -320,16 +347,11 @@ module Ransack
|
|
320
347
|
end
|
321
348
|
|
322
349
|
it 'allows chaining to access nested conditions' do
|
323
|
-
@s.groupings = [
|
350
|
+
@s.groupings = [
|
351
|
+
{ m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie' }
|
352
|
+
]
|
324
353
|
@s.groupings.first.children_name_eq.should eq 'Ernie'
|
325
354
|
end
|
326
355
|
end
|
327
|
-
|
328
|
-
describe '#respond_to' do
|
329
|
-
it 'is aware of second argument' do
|
330
|
-
Search.new(Person).respond_to?(:name_eq, true).should be_true
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
356
|
end
|
335
357
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Ransack
|
4
|
+
describe Translate do
|
5
|
+
|
6
|
+
describe '.attribute' do
|
7
|
+
it 'translate namespaced attribute like AR does' do
|
8
|
+
ar_translation = ::Namespace::Article.human_attribute_name(:title)
|
9
|
+
ransack_translation = Ransack::Translate.attribute(:title, :context => ::Namespace::Article.search.context)
|
10
|
+
ransack_translation.should eq ar_translation
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -6,17 +6,22 @@ require 'ransack'
|
|
6
6
|
Time.zone = 'Eastern Time (US & Canada)'
|
7
7
|
I18n.load_path += Dir[File.join(File.dirname(__FILE__), 'support', '*.yml')]
|
8
8
|
|
9
|
-
Dir[File.expand_path('../{helpers,support,blueprints}/*.rb', __FILE__)]
|
9
|
+
Dir[File.expand_path('../{helpers,support,blueprints}/*.rb', __FILE__)]
|
10
|
+
.each do |f|
|
10
11
|
require f
|
11
12
|
end
|
12
13
|
|
13
14
|
Sham.define do
|
14
|
-
name
|
15
|
-
title
|
16
|
-
body
|
17
|
-
salary
|
18
|
-
tag_name
|
19
|
-
note
|
15
|
+
name { Faker::Name.name }
|
16
|
+
title { Faker::Lorem.sentence }
|
17
|
+
body { Faker::Lorem.paragraph }
|
18
|
+
salary { |index| 30000 + (index * 1000) }
|
19
|
+
tag_name { Faker::Lorem.words(3).join(' ') }
|
20
|
+
note { Faker::Lorem.words(7).join(' ') }
|
21
|
+
only_admin { Faker::Lorem.words(3).join(' ') }
|
22
|
+
only_search { Faker::Lorem.words(3).join(' ') }
|
23
|
+
only_sort { Faker::Lorem.words(3).join(' ') }
|
24
|
+
notable_id { |id| id }
|
20
25
|
end
|
21
26
|
|
22
27
|
RSpec.configure do |config|
|
@@ -25,7 +30,8 @@ RSpec.configure do |config|
|
|
25
30
|
config.before(:suite) do
|
26
31
|
puts '=' * 80
|
27
32
|
connection_name = ActiveRecord::Base.connection.adapter_name
|
28
|
-
puts "Running specs against #{connection_name}, ActiveRecord #{
|
33
|
+
puts "Running specs against #{connection_name}, ActiveRecord #{
|
34
|
+
ActiveRecord::VERSION::STRING} and ARel #{Arel::VERSION}..."
|
29
35
|
puts '=' * 80
|
30
36
|
Schema.create
|
31
37
|
end
|
data/spec/support/en.yml
CHANGED
data/spec/support/schema.rb
CHANGED
@@ -26,24 +26,56 @@ class Person < ActiveRecord::Base
|
|
26
26
|
if ActiveRecord::VERSION::MAJOR == 3
|
27
27
|
default_scope order('id DESC')
|
28
28
|
else
|
29
|
-
default_scope { order(
|
30
|
-
# The new activerecord syntax "{ order(id: :desc) }" does not work
|
31
|
-
# with Ruby 1.8.7 which we still need to support for Rails 3
|
29
|
+
default_scope { order(id: :desc) }
|
32
30
|
end
|
33
|
-
belongs_to :parent, :
|
34
|
-
has_many :children, :
|
31
|
+
belongs_to :parent, class_name: 'Person', foreign_key: :parent_id
|
32
|
+
has_many :children, class_name: 'Person', foreign_key: :parent_id
|
35
33
|
has_many :articles
|
36
34
|
has_many :comments
|
37
|
-
has_many :authored_article_comments, :
|
38
|
-
|
39
|
-
has_many :notes, :
|
35
|
+
has_many :authored_article_comments, through: :articles,
|
36
|
+
source: :comments, foreign_key: :person_id
|
37
|
+
has_many :notes, as: :notable
|
40
38
|
|
41
|
-
ransacker :reversed_name, :
|
39
|
+
ransacker :reversed_name, formatter: proc { |v| v.reverse } do |parent|
|
42
40
|
parent.table[:name]
|
43
41
|
end
|
44
42
|
|
45
43
|
ransacker :doubled_name do |parent|
|
46
|
-
Arel::Nodes::InfixOperation.new(
|
44
|
+
Arel::Nodes::InfixOperation.new(
|
45
|
+
'||', parent.table[:name], parent.table[:name]
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.ransackable_attributes(auth_object = nil)
|
50
|
+
if auth_object == :admin
|
51
|
+
column_names + _ransackers.keys - ['only_sort']
|
52
|
+
else
|
53
|
+
column_names + _ransackers.keys - ['only_sort', 'only_admin']
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.ransortable_attributes(auth_object = nil)
|
58
|
+
if auth_object == :admin
|
59
|
+
column_names + _ransackers.keys - ['only_search']
|
60
|
+
else
|
61
|
+
column_names + _ransackers.keys - ['only_search', 'only_admin']
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.ransackable_attributes(auth_object = nil)
|
66
|
+
if auth_object == :admin
|
67
|
+
column_names + _ransackers.keys - ['only_sort']
|
68
|
+
else
|
69
|
+
column_names + _ransackers.keys - ['only_sort', 'only_admin']
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.ransortable_attributes(auth_object = nil)
|
74
|
+
if auth_object == :admin
|
75
|
+
column_names + _ransackers.keys - ['only_search']
|
76
|
+
else
|
77
|
+
column_names + _ransackers.keys - ['only_search', 'only_admin']
|
78
|
+
end
|
47
79
|
end
|
48
80
|
end
|
49
81
|
|
@@ -51,7 +83,19 @@ class Article < ActiveRecord::Base
|
|
51
83
|
belongs_to :person
|
52
84
|
has_many :comments
|
53
85
|
has_and_belongs_to_many :tags
|
54
|
-
has_many
|
86
|
+
has_many :notes, as: :notable
|
87
|
+
end
|
88
|
+
|
89
|
+
module Namespace
|
90
|
+
class Article < ::Article
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
module Namespace
|
96
|
+
class Article < ::Article
|
97
|
+
|
98
|
+
end
|
55
99
|
end
|
56
100
|
|
57
101
|
class Comment < ActiveRecord::Base
|
@@ -64,7 +108,7 @@ class Tag < ActiveRecord::Base
|
|
64
108
|
end
|
65
109
|
|
66
110
|
class Note < ActiveRecord::Base
|
67
|
-
belongs_to :notable, :
|
111
|
+
belongs_to :notable, polymorphic: true
|
68
112
|
end
|
69
113
|
|
70
114
|
module Schema
|
@@ -72,63 +116,64 @@ module Schema
|
|
72
116
|
ActiveRecord::Migration.verbose = false
|
73
117
|
|
74
118
|
ActiveRecord::Schema.define do
|
75
|
-
create_table :people, :
|
119
|
+
create_table :people, force: true do |t|
|
76
120
|
t.integer :parent_id
|
77
121
|
t.string :name
|
78
122
|
t.string :email
|
123
|
+
t.string :only_search
|
124
|
+
t.string :only_sort
|
125
|
+
t.string :only_admin
|
79
126
|
t.integer :salary
|
80
|
-
t.boolean :awesome, :
|
127
|
+
t.boolean :awesome, default: false
|
81
128
|
t.timestamps
|
82
129
|
end
|
83
130
|
|
84
|
-
create_table :articles, :
|
131
|
+
create_table :articles, force: true do |t|
|
85
132
|
t.integer :person_id
|
86
133
|
t.string :title
|
87
134
|
t.text :body
|
88
135
|
end
|
89
136
|
|
90
|
-
create_table :comments, :
|
137
|
+
create_table :comments, force: true do |t|
|
91
138
|
t.integer :article_id
|
92
139
|
t.integer :person_id
|
93
|
-
t.text
|
140
|
+
t.text :body
|
94
141
|
end
|
95
142
|
|
96
|
-
create_table :tags, :
|
143
|
+
create_table :tags, force: true do |t|
|
97
144
|
t.string :name
|
98
145
|
end
|
99
146
|
|
100
|
-
create_table :articles_tags, :
|
147
|
+
create_table :articles_tags, force: true, id: false do |t|
|
101
148
|
t.integer :article_id
|
102
149
|
t.integer :tag_id
|
103
150
|
end
|
104
151
|
|
105
|
-
create_table :notes, :
|
152
|
+
create_table :notes, force: true do |t|
|
106
153
|
t.integer :notable_id
|
107
|
-
t.string
|
108
|
-
t.string
|
154
|
+
t.string :notable_type
|
155
|
+
t.string :note
|
109
156
|
end
|
110
157
|
|
111
158
|
end
|
112
159
|
|
113
160
|
10.times do
|
114
161
|
person = Person.make
|
115
|
-
Note.make(:
|
162
|
+
Note.make(notable: person)
|
116
163
|
3.times do
|
117
|
-
article = Article.make(:
|
164
|
+
article = Article.make(person: person)
|
118
165
|
3.times do
|
119
166
|
article.tags = [Tag.make, Tag.make, Tag.make]
|
120
167
|
end
|
121
|
-
Note.make(:
|
168
|
+
Note.make(notable: article)
|
122
169
|
10.times do
|
123
|
-
Comment.make(:article
|
170
|
+
Comment.make(article: article, person: person)
|
124
171
|
end
|
125
172
|
end
|
126
|
-
2.times do
|
127
|
-
Comment.make(:person => person)
|
128
|
-
end
|
129
173
|
end
|
130
174
|
|
131
|
-
Comment.make(
|
132
|
-
|
175
|
+
Comment.make(
|
176
|
+
body: 'First post!', article: Article.make(title: 'Hello, world!')
|
177
|
+
)
|
133
178
|
end
|
134
179
|
end
|