scoped_from 0.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +18 -18
- data/README.mdown +5 -7
- data/VERSION +1 -1
- data/lib/scoped_from/query.rb +15 -5
- data/spec/scoped_from/query_spec.rb +89 -27
- data/spec/spec_helper.rb +2 -2
- data/spec/support/bootsrap/database.rb +2 -1
- metadata +4 -4
data/Gemfile.lock
CHANGED
@@ -8,39 +8,39 @@ PATH
|
|
8
8
|
GEM
|
9
9
|
remote: http://rubygems.org/
|
10
10
|
specs:
|
11
|
-
actionpack (3.1.
|
12
|
-
activemodel (= 3.1.
|
13
|
-
activesupport (= 3.1.
|
11
|
+
actionpack (3.1.3)
|
12
|
+
activemodel (= 3.1.3)
|
13
|
+
activesupport (= 3.1.3)
|
14
14
|
builder (~> 3.0.0)
|
15
15
|
erubis (~> 2.7.0)
|
16
16
|
i18n (~> 0.6)
|
17
|
-
rack (~> 1.3.
|
17
|
+
rack (~> 1.3.5)
|
18
18
|
rack-cache (~> 1.1)
|
19
19
|
rack-mount (~> 0.8.2)
|
20
20
|
rack-test (~> 0.6.1)
|
21
|
-
sprockets (~> 2.0.
|
22
|
-
activemodel (3.1.
|
23
|
-
activesupport (= 3.1.
|
21
|
+
sprockets (~> 2.0.3)
|
22
|
+
activemodel (3.1.3)
|
23
|
+
activesupport (= 3.1.3)
|
24
24
|
builder (~> 3.0.0)
|
25
25
|
i18n (~> 0.6)
|
26
|
-
activerecord (3.1.
|
27
|
-
activemodel (= 3.1.
|
28
|
-
activesupport (= 3.1.
|
26
|
+
activerecord (3.1.3)
|
27
|
+
activemodel (= 3.1.3)
|
28
|
+
activesupport (= 3.1.3)
|
29
29
|
arel (~> 2.2.1)
|
30
30
|
tzinfo (~> 0.3.29)
|
31
|
-
activesupport (3.1.
|
31
|
+
activesupport (3.1.3)
|
32
32
|
multi_json (~> 1.0)
|
33
33
|
arel (2.2.1)
|
34
34
|
builder (3.0.0)
|
35
|
-
columnize (0.3.
|
35
|
+
columnize (0.3.5)
|
36
36
|
diff-lcs (1.1.3)
|
37
37
|
erubis (2.7.0)
|
38
38
|
hike (1.2.1)
|
39
39
|
i18n (0.6.0)
|
40
|
-
json (1.6.
|
40
|
+
json (1.6.2)
|
41
41
|
linecache (0.46)
|
42
42
|
rbx-require-relative (> 0.0.4)
|
43
|
-
multi_json (1.0.
|
43
|
+
multi_json (1.0.4)
|
44
44
|
rack (1.3.5)
|
45
45
|
rack-cache (1.1)
|
46
46
|
rack (>= 0.4)
|
@@ -50,9 +50,9 @@ GEM
|
|
50
50
|
rack
|
51
51
|
rack-test (0.6.1)
|
52
52
|
rack (>= 1.0)
|
53
|
-
railties (3.1.
|
54
|
-
actionpack (= 3.1.
|
55
|
-
activesupport (= 3.1.
|
53
|
+
railties (3.1.3)
|
54
|
+
actionpack (= 3.1.3)
|
55
|
+
activesupport (= 3.1.3)
|
56
56
|
rack-ssl (~> 1.3.2)
|
57
57
|
rake (>= 0.8.7)
|
58
58
|
rdoc (~> 3.4)
|
@@ -88,7 +88,7 @@ GEM
|
|
88
88
|
sqlite3 (>= 1.3.3)
|
89
89
|
thor (0.14.6)
|
90
90
|
tilt (1.3.3)
|
91
|
-
tzinfo (0.3.
|
91
|
+
tzinfo (0.3.31)
|
92
92
|
|
93
93
|
PLATFORMS
|
94
94
|
ruby
|
data/README.mdown
CHANGED
@@ -66,6 +66,8 @@ All scopes can be mapped with `scoped_from` method **except** scopes taking a
|
|
66
66
|
Scopes with no argument are invoked if parameter value is evaluated as `true`.
|
67
67
|
It includes `"true"`, `"yes"`, `"y"`, `"on"`, and `"1"` strings.
|
68
68
|
|
69
|
+
Columns are also automatically scoped.
|
70
|
+
|
69
71
|
## Scopes restriction
|
70
72
|
|
71
73
|
You can restrict mapping to some scopes with `:only` option:
|
@@ -100,14 +102,10 @@ is equivalent to
|
|
100
102
|
|
101
103
|
@posts = Post.search('bar').search('foo')
|
102
104
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
@posts = Post.scoped_from(params, :include_blank => true)
|
107
|
-
|
108
|
-
You may also want to filter on columns, just specify `:include_columns` option:
|
105
|
+
You may also not want to filter on columns, just specify `:exclude_columns`
|
106
|
+
option:
|
109
107
|
|
110
|
-
@posts = Post.scoped_from(params, :
|
108
|
+
@posts = Post.scoped_from(params, :exclude_columns => true)
|
111
109
|
|
112
110
|
A query string can also be given to `scoped_from` method:
|
113
111
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3
|
data/lib/scoped_from/query.rb
CHANGED
@@ -2,6 +2,7 @@ module ScopedFrom
|
|
2
2
|
|
3
3
|
class Query
|
4
4
|
|
5
|
+
FALSE_VALUES = %w( false no n off 0 ).freeze
|
5
6
|
ORDER_DIRECTIONS = %w( asc desc ).freeze
|
6
7
|
TRUE_VALUES = %w( true yes y on 1 ).freeze
|
7
8
|
|
@@ -9,8 +10,6 @@ module ScopedFrom
|
|
9
10
|
|
10
11
|
# Available options are: - :only : to restrict to specified keys.
|
11
12
|
# - :except : to ignore specified keys.
|
12
|
-
# - :include_blank : to include blank values
|
13
|
-
# (default false).
|
14
13
|
def initialize(scope, params, options = {})
|
15
14
|
@scope = scope.scoped
|
16
15
|
@options = options
|
@@ -46,6 +45,10 @@ module ScopedFrom
|
|
46
45
|
scope
|
47
46
|
end
|
48
47
|
|
48
|
+
def false?(value)
|
49
|
+
FALSE_VALUES.include?(value.to_s.strip.downcase)
|
50
|
+
end
|
51
|
+
|
49
52
|
def order_to_sql(value)
|
50
53
|
order = parse_order(value)
|
51
54
|
"#{order[:column]} #{order[:direction].upcase}" if order.present?
|
@@ -71,16 +74,23 @@ module ScopedFrom
|
|
71
74
|
@params = ActiveSupport::HashWithIndifferentAccess.new
|
72
75
|
params.each do |name, value|
|
73
76
|
values = [value].flatten
|
74
|
-
values.delete_if(&:blank?) unless @options[:include_blank]
|
75
77
|
next if values.empty?
|
76
78
|
if name.to_s == 'order'
|
77
79
|
order = parse_order(values.last)
|
78
80
|
@params[name] = "#{order[:column]}.#{order[:direction]}" if order.present?
|
79
81
|
elsif @scope.scope_without_argument?(name)
|
80
|
-
@params[name] = true if values.
|
81
|
-
elsif @scope.scope_with_one_argument?(name)
|
82
|
+
@params[name] = true if values.all? { |value| true?(value) }
|
83
|
+
elsif @scope.scope_with_one_argument?(name)
|
82
84
|
value = values.many? ? values : values.first
|
83
85
|
@params[name] = @params[name] ? [@params[name], value].flatten : value
|
86
|
+
elsif @options[:exclude_columns].blank? && @scope.column_names.include?(name.to_s)
|
87
|
+
if @scope.columns_hash[name.to_s].type == :boolean
|
88
|
+
@params[name] = true if values.all? { |value| true?(value) }
|
89
|
+
@params[name] = false if values.all? { |value| false?(value) }
|
90
|
+
else
|
91
|
+
value = values.many? ? values : values.first
|
92
|
+
@params[name] = @params[name] ? [@params[name], value].flatten : value
|
93
|
+
end
|
84
94
|
end
|
85
95
|
end
|
86
96
|
@params.slice!(*[@options[:only]].flatten) if @options[:only].present?
|
@@ -6,6 +6,61 @@ describe ScopedFrom::Query do
|
|
6
6
|
ScopedFrom::Query.new(scope, params, options)
|
7
7
|
end
|
8
8
|
|
9
|
+
describe '#false?' do
|
10
|
+
|
11
|
+
it 'is true if false is given' do
|
12
|
+
query.send(:false?, false).should be_true
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'is true if "false" is given' do
|
16
|
+
query.send(:false?, 'false').should be_true
|
17
|
+
query.send(:false?, 'False').should be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'is true if "0" is given' do
|
21
|
+
query.send(:false?, '0').should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'is true if "off" is given' do
|
25
|
+
query.send(:false?, 'off').should be_true
|
26
|
+
query.send(:false?, 'OFF ').should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'is true if "no" is given' do
|
30
|
+
query.send(:false?, 'no').should be_true
|
31
|
+
query.send(:false?, ' No ').should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'is true if "n" is given' do
|
35
|
+
query.send(:false?, 'n').should be_true
|
36
|
+
query.send(:false?, 'N ').should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'is false if true is given' do
|
40
|
+
query.send(:false?, true).should be_false
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'is false if "true" is given' do
|
44
|
+
query.send(:false?, 'true').should be_false
|
45
|
+
query.send(:false?, 'TrUe').should be_false
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'is false if "1" is given' do
|
49
|
+
query.send(:false?, '1').should be_false
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'is false if "on" is given' do
|
53
|
+
query.send(:false?, "on").should be_false
|
54
|
+
query.send(:false?, "On").should be_false
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'is false otherwise' do
|
58
|
+
query.send(:false?, 42).should be_false
|
59
|
+
query.send(:false?, 'bam').should be_false
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
9
64
|
describe '#initialize' do
|
10
65
|
|
11
66
|
it 'invokes #scoped method on specified scope' do
|
@@ -90,10 +145,6 @@ describe ScopedFrom::Query do
|
|
90
145
|
query(User, :foo => 'bar', 'search' => 'foo', :enabled => true).params.should == { 'search' => 'foo', 'enabled' => true }
|
91
146
|
end
|
92
147
|
|
93
|
-
it 'removes blank values' do
|
94
|
-
query(User, 'enabled' => true, 'search' => " \n").params.should == { 'enabled' => true }
|
95
|
-
end
|
96
|
-
|
97
148
|
it 'is case sensitive' do
|
98
149
|
query(User, 'Enabled' => true, "SEARCH" => 'bar').params.should be_empty
|
99
150
|
end
|
@@ -118,27 +169,32 @@ describe ScopedFrom::Query do
|
|
118
169
|
query(User, 'search=bar&search=baz').params.should == { 'search' => ['bar', 'baz'] }
|
119
170
|
end
|
120
171
|
|
121
|
-
it 'removes blank values from array' do
|
122
|
-
query(User, :search => [nil, 'bar', "\n ", 'baz']).params.should == { 'search' => ['bar', 'baz'] }
|
123
|
-
end
|
124
|
-
|
125
172
|
it 'converts value to true (or remove it) if scope takes no argument' do
|
126
173
|
query(User, :latest => 'y').params.should == { 'latest' => true }
|
127
174
|
query(User, :latest => 'no').params.should == {}
|
128
175
|
end
|
129
176
|
|
177
|
+
it 'converts value to true (or false) if column is a boolean one' do
|
178
|
+
query(User, :admin => 'y').params.should == { 'admin' => true }
|
179
|
+
query(User, :admin => 'False').params.should == { 'admin' => false }
|
180
|
+
query(User, :admin => 'bar').params.should == {}
|
181
|
+
query(User, :admin => ['y', false]).params.should == {}
|
182
|
+
end
|
183
|
+
|
130
184
|
it 'converts array value to true (or remove it) if scope takes no argument' do
|
131
|
-
query(User, :latest =>
|
185
|
+
query(User, :latest => true).params.should == { 'latest' => true }
|
186
|
+
query(User, :latest => ['Yes']).params.should == { 'latest' => true }
|
187
|
+
query(User, :latest => ['no', 'yes']).params.should == {}
|
132
188
|
query(User, :latest => ['no', nil]).params.should == {}
|
133
189
|
query(User, :latest => ['fo']).params.should == {}
|
134
190
|
end
|
135
191
|
|
136
192
|
it 'flats array' do
|
137
|
-
query(User, :search => [nil, ['bar', '', 'foo', ["\n ", 'baz']]]).params.should == { 'search' => ['bar', 'foo', 'baz'] }
|
193
|
+
query(User, :search => [nil, ['bar', '', 'foo', ["\n ", 'baz']]]).params.should == { 'search' => [nil, 'bar', '', 'foo', "\n ", 'baz'] }
|
138
194
|
end
|
139
195
|
|
140
196
|
it 'change array with a single value in one value' do
|
141
|
-
query(User, :search => [
|
197
|
+
query(User, :search => ['bar']).params.should == { 'search' => 'bar' }
|
142
198
|
end
|
143
199
|
|
144
200
|
it 'does not modify given hash' do
|
@@ -156,40 +212,46 @@ describe ScopedFrom::Query do
|
|
156
212
|
it 'accepts :only option' do
|
157
213
|
query(User, { :search => 'bar', :enabled => 'true' }, :only => [:search]).params.should == { 'search' => 'bar' }
|
158
214
|
query(User, { :search => 'bar', :enabled => 'true' }, :only => 'search').params.should == { 'search' => 'bar' }
|
215
|
+
query(User, { :search => 'bar', :firstname => 'Jane', :enabled => 'true' }, :only => 'search').params.should == { 'search' => 'bar' }
|
216
|
+
query(User, { :search => 'bar', :firstname => 'Jane', :enabled => 'true' }, :only => ['search', :firstname]).params.should == { 'search' => 'bar', 'firstname' => 'Jane' }
|
159
217
|
end
|
160
218
|
|
161
219
|
it 'accepts :except option' do
|
162
220
|
query(User, { :search => 'bar', :enabled => true }, :except => [:search]).params.should == { 'enabled' => true }
|
163
221
|
query(User, { :search => 'bar', :enabled => true }, :except => 'search').params.should == { 'enabled' => true }
|
222
|
+
query(User, { :search => 'bar', :firstname => 'Jane', :enabled => true }, :except => 'search').params.should == { 'enabled' => true, 'firstname' => 'Jane' }
|
223
|
+
query(User, { :search => 'bar', :firstname => 'Jane', :enabled => true }, :except => ['search', :firstname]).params.should == { 'enabled' => true }
|
164
224
|
end
|
165
225
|
|
166
226
|
it 'accepts a query instance' do
|
167
227
|
query(User, query(User, :search => 'toto')).params.should == { 'search' => 'toto' }
|
168
228
|
end
|
169
229
|
|
170
|
-
it 'preserve blank values
|
171
|
-
query(User, { :search => "\n ", 'enabled' => true }
|
230
|
+
it 'preserve blank values' do
|
231
|
+
query(User, { :search => "\n ", 'enabled' => true }).params.should == { 'search' => "\n ", 'enabled' => true }
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'preserve blank values from array' do
|
235
|
+
query(User, { 'search' => ["\n ", 'toto', 'titi'] }).params.should == { 'search' => ["\n ", 'toto', 'titi'] }
|
236
|
+
query(User, { 'search' => [] }).params.should == {}
|
172
237
|
end
|
173
238
|
|
174
|
-
it 'preserve blank
|
175
|
-
query(User,
|
176
|
-
query(User, { 'search' => [] }, :include_blank => true).params.should == {}
|
239
|
+
it 'also preserve blank on query string' do
|
240
|
+
query(User, 'search=%20&enabled=true&search=foo').params.should == { 'search' => [' ', 'foo'], 'enabled' => true }
|
177
241
|
end
|
178
242
|
|
179
|
-
it '
|
180
|
-
query(User, '
|
243
|
+
it 'includes column values' do
|
244
|
+
query(User, 'firstname' => 'Jane', 'foo' => 'bar').params.should == { 'firstname' => 'Jane' }
|
245
|
+
query(User, :firstname => 'Jane', 'foo' => 'bar').params.should == { 'firstname' => 'Jane' }
|
181
246
|
end
|
182
247
|
|
183
|
-
it '
|
184
|
-
query(User, 'firstname' => 'Jane', 'foo' => 'bar').params.should == {}
|
248
|
+
it 'exclude column values if :exclude_columns option is specified' do
|
249
|
+
query(User, { :enabled => true, 'firstname' => 'Jane', 'foo' => 'bar' }, :exclude_columns => true).params.should == { 'enabled' => true }
|
250
|
+
query(User, { :enabled => true, :firstname => 'Jane', :foo => 'bar' }, :exclude_columns => true).params.should == { 'enabled' => true }
|
185
251
|
end
|
186
252
|
|
187
|
-
it '
|
188
|
-
query(User,
|
189
|
-
query(User, { :firstname => 'Jane', :foo => 'bar' }, :include_columns => true).params.should == { 'firstname' => 'Jane' }
|
190
|
-
query(User, { 'firstname' => ['Jane', 'John'], 'foo' => 'bar' }, :include_columns => true).params.should == { 'firstname' => ['Jane', 'John'] }
|
191
|
-
query(User, { 'firstname' => "\n ", 'foo' => 'bar' }, :include_columns => true).params.should == {}
|
192
|
-
query(User, { 'firstname' => "\n ", 'foo' => 'bar' }, :include_columns => true, :include_blank => true).params.should == { 'firstname' => "\n " }
|
253
|
+
it 'scopes have priority on columns' do
|
254
|
+
query(User, :enabled => false).params.should == {}
|
193
255
|
end
|
194
256
|
|
195
257
|
it 'maps an "order"' do
|
@@ -345,7 +407,7 @@ describe ScopedFrom::Query do
|
|
345
407
|
query.send(:scoped, User, :created_between, true).should == User
|
346
408
|
end
|
347
409
|
|
348
|
-
it 'invokes scope without arguments if scope takes
|
410
|
+
it 'invokes scope without arguments if scope takes no arguments' do
|
349
411
|
query.send(:scoped, User.scoped, :enabled, true).should == [users(:john)]
|
350
412
|
query.send(:scoped, User.scoped, :enabled, ' 1 ').should == [users(:john)]
|
351
413
|
query.send(:scoped, User.scoped, :enabled, 'off').should == [users(:john)]
|
data/spec/spec_helper.rb
CHANGED
@@ -19,7 +19,7 @@ RSpec.configure do |config|
|
|
19
19
|
User.delete_all
|
20
20
|
Vote.delete_all
|
21
21
|
|
22
|
-
create_user(:john, :firstname => 'John', :lastname => 'Doe', :enabled => true)
|
23
|
-
create_user(:jane, :firstname => 'Jane', :lastname => 'Doe', :enabled => false)
|
22
|
+
create_user(:john, :firstname => 'John', :lastname => 'Doe', :enabled => true, :admin => true)
|
23
|
+
create_user(:jane, :firstname => 'Jane', :lastname => 'Doe', :enabled => false, :admin => false)
|
24
24
|
end
|
25
25
|
end
|
@@ -5,7 +5,8 @@ ActiveRecord::Base.connection.create_table(:posts, :force => true)
|
|
5
5
|
ActiveRecord::Base.connection.create_table(:users, :force => true) do |t|
|
6
6
|
t.string :firstname, :null => false
|
7
7
|
t.string :lastname, :null => false
|
8
|
-
t.boolean :enabled, :null => false
|
8
|
+
t.boolean :enabled, :null => false, :default => false
|
9
|
+
t.boolean :admin, :null => false, :default => false
|
9
10
|
t.timestamps
|
10
11
|
end
|
11
12
|
ActiveRecord::Base.connection.create_table(:votes, :force => true)
|
metadata
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scoped_from
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: "0.
|
8
|
+
- 3
|
9
|
+
version: "0.3"
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Alexis Toulotte
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-
|
17
|
+
date: 2011-11-30 00:00:00 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: activerecord
|