scoped_from 1.0.1 → 1.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 88f3cb11e67b82da5d005daacea281154d2818ba
4
- data.tar.gz: 981bb72c4e756353749084e3503ab9b03469cfd4
3
+ metadata.gz: 91ae1b8a113e2c3b176c538a4d83870913cdb16c
4
+ data.tar.gz: e06f1e812ed6ed939eaa37b90dab44728225d2b7
5
5
  SHA512:
6
- metadata.gz: 82a281b707f6eb1d102131e06c9da5dcf7dec0a178d2ecc0b034e84589dc7ec4267362c56be037792011e809c6e1eb2200f2d6f0bce92af0576fc08b2e6378d1
7
- data.tar.gz: 79c0f7e9e6b4ab871aa2243fae328f004a6a1aa8ebb4bb750d1a58903e8e059626dd52f65d0e0fb5e9937f2df67f5513a19262a0a77dc14952c6c1947faa6cf6
6
+ metadata.gz: e8c903abd9c23d0a66c4956119c810eef2523be47e7cec2772fe5afa3345e716516fd015d084da3d4cd27a1f5e5437054fe60005c0ca8ae3c66ceea96300f12d
7
+ data.tar.gz: 7eedfbdca7944970a41fffd50806c6788406bff4f37b9f1f533e3af4ef3ee03596340f79b57ce7e5c149e5507de2cd4432411d158f82d229cc11411af95e7722
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.1
1
+ 1.0.2
data/scoped_from.gemspec CHANGED
@@ -9,13 +9,12 @@ Gem::Specification.new do |s|
9
9
  s.description = 'Provides a simple mapping between Active Record scopes and controller parameters for Ruby On Rails 4'
10
10
  s.license = 'MIT'
11
11
 
12
- s.rubyforge_project = 'scoped_from'
13
-
14
- s.files = `git ls-files`.split("\n")
15
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
12
+ s.files = `git ls-files | grep -vE '^(spec/|test/|\\.|Gemfile|Rakefile)'`.split("\n")
16
13
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
14
  s.require_paths = ['lib']
18
15
 
16
+ s.required_ruby_version = '>= 2.0.0'
17
+
19
18
  s.add_dependency 'activerecord', '>= 5.0.0', '< 5.1.0'
20
19
  s.add_dependency 'activesupport', '>= 5.0.0', '< 5.1.0'
21
20
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scoped_from
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexis Toulotte
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-22 00:00:00.000000000 Z
11
+ date: 2017-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -157,30 +157,13 @@ executables: []
157
157
  extensions: []
158
158
  extra_rdoc_files: []
159
159
  files:
160
- - ".gitignore"
161
- - ".rspec"
162
- - Gemfile
163
160
  - MIT-LICENSE
164
161
  - README.mdown
165
- - Rakefile
166
162
  - VERSION
167
163
  - lib/scoped_from.rb
168
164
  - lib/scoped_from/active_record.rb
169
165
  - lib/scoped_from/query.rb
170
166
  - scoped_from.gemspec
171
- - spec/mocks/comment.rb
172
- - spec/mocks/comment_query.rb
173
- - spec/mocks/post.rb
174
- - spec/mocks/user.rb
175
- - spec/mocks/user_query.rb
176
- - spec/mocks/vote.rb
177
- - spec/mocks/vote_query.rb
178
- - spec/scoped_from/active_record_spec.rb
179
- - spec/scoped_from/query_spec.rb
180
- - spec/scoped_from_spec.rb
181
- - spec/spec_helper.rb
182
- - spec/support/bootstrap/database.rb
183
- - spec/support/macros/user_macro.rb
184
167
  homepage: https://github.com/alexistoulotte/scoped_from
185
168
  licenses:
186
169
  - MIT
@@ -193,15 +176,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
193
176
  requirements:
194
177
  - - ">="
195
178
  - !ruby/object:Gem::Version
196
- version: '0'
179
+ version: 2.0.0
197
180
  required_rubygems_version: !ruby/object:Gem::Requirement
198
181
  requirements:
199
182
  - - ">="
200
183
  - !ruby/object:Gem::Version
201
184
  version: '0'
202
185
  requirements: []
203
- rubyforge_project: scoped_from
204
- rubygems_version: 2.5.1
186
+ rubyforge_project:
187
+ rubygems_version: 2.6.8
205
188
  signing_key:
206
189
  specification_version: 4
207
190
  summary: Mapping between scopes and parameters for Rails
data/.gitignore DELETED
@@ -1,7 +0,0 @@
1
- .DS_Store
2
- .byebug_history
3
- /.bundle/
4
- /.ruby-version
5
- /Gemfile.lock
6
- /pkg/
7
- /spec/test.sqlite3
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --colour
2
- --order random
data/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
data/Rakefile DELETED
@@ -1,10 +0,0 @@
1
- require 'bundler'
2
- require 'rspec/core/rake_task'
3
-
4
- Bundler::GemHelper.install_tasks
5
-
6
- desc 'Default: runs specs.'
7
- task default: :spec
8
-
9
- desc 'Run all specs in spec directory.'
10
- RSpec::Core::RakeTask.new(:spec)
@@ -1,2 +0,0 @@
1
- class Comment < ActiveRecord::Base
2
- end
@@ -1,2 +0,0 @@
1
- class CommentQuery < ScopedFrom::Query
2
- end
data/spec/mocks/post.rb DELETED
@@ -1,2 +0,0 @@
1
- class Post < ActiveRecord::Base
2
- end
data/spec/mocks/user.rb DELETED
@@ -1,8 +0,0 @@
1
- class User < ActiveRecord::Base
2
-
3
- scope :enabled, -> { where(enabled: true) }
4
- scope :search, -> (pattern) { where('firstname LIKE ? OR lastname LIKE ?', "%#{pattern}%", "%#{pattern}%") }
5
- scope :created_between, -> (after, before) { where('created_at >= ? AND created_at <= ?', after, before) }
6
- scope :latest, -> { where('created_at >= ?', 1.week.ago) }
7
-
8
- end
@@ -1,2 +0,0 @@
1
- class UserQuery < String
2
- end
data/spec/mocks/vote.rb DELETED
@@ -1,2 +0,0 @@
1
- class Vote < ActiveRecord::Base
2
- end
@@ -1,2 +0,0 @@
1
- module VoteQuery
2
- end
@@ -1,125 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ScopedFrom::ActiveRecord do
4
-
5
- describe '#scope_with_one_argument?' do
6
-
7
- it 'is true if scope has one argument' do
8
- expect(User.scope_with_one_argument?(:search)).to be(true)
9
- expect(User.scope_with_one_argument?('search')).to be(true)
10
- end
11
-
12
- it 'is false if scope has no argument' do
13
- expect(User.scope_with_one_argument?(:latest)).to be(false)
14
- expect(User.scope_with_one_argument?('latest')).to be(false)
15
- end
16
-
17
- it 'is false if scope has more than one argument' do
18
- expect(User.scope_with_one_argument?(:created_between)).to be(false)
19
- expect(User.scope_with_one_argument?('created_between')).to be(false)
20
- end
21
-
22
- it 'is false if scope is not a proc' do
23
- expect(User.scope_with_one_argument?(:enabled)).to be(false)
24
- expect(User.scope_with_one_argument?('enabled')).to be(false)
25
- end
26
-
27
- it 'is false if scope does not exist' do
28
- expect(User.scope_with_one_argument?(:foo)).to be(false)
29
- expect(User.scope_with_one_argument?('foo')).to be(false)
30
- end
31
-
32
- end
33
-
34
- describe 'scope_without_argument?' do
35
-
36
- it 'is true if scope has no argument' do
37
- expect(User.scope_without_argument?(:latest)).to be(true)
38
- expect(User.scope_without_argument?('latest')).to be(true)
39
- end
40
-
41
- it 'is true if scope is not a proc' do
42
- expect(User.scope_without_argument?(:enabled)).to be(true)
43
- expect(User.scope_without_argument?('enabled')).to be(true)
44
- end
45
-
46
- it 'is false if scope has one argument' do
47
- expect(User.scope_without_argument?(:search)).to be(false)
48
- expect(User.scope_without_argument?('search')).to be(false)
49
- end
50
-
51
- it 'is false if scope has more than one argument' do
52
- expect(User.scope_without_argument?(:created_between)).to be(false)
53
- expect(User.scope_without_argument?('created_between')).to be(false)
54
- end
55
-
56
- it 'is false if scope does not exist' do
57
- expect(User.scope_without_argument?(:foo)).to be(false)
58
- expect(User.scope_without_argument?('foo')).to be(false)
59
- end
60
-
61
- end
62
-
63
- describe '#scoped_from' do
64
-
65
- it 'just build a new query and return its scope' do
66
- query = double(:query)
67
- expect(query).to receive(:relation).and_return(42)
68
- expect(ScopedFrom::Query).to receive(:new).with(User, 'foo', except: 'bam').and_return(query)
69
- expect(User.scoped_from('foo', except: 'bam')).to eq(42)
70
- end
71
-
72
- it 'build scopes' do
73
- expect(User.scoped_from(search: 'jane')).to eq([users(:jane)])
74
- expect(User.scoped_from(search: 'john')).to eq([users(:john)])
75
- end
76
-
77
- it 'can be chained with other scopes' do
78
- expect(User.scoped_from(search: 'jane')).to eq([users(:jane)])
79
- expect(User.enabled.scoped_from(search: 'jane')).to eq([])
80
- end
81
-
82
- it 'can be used with order as parameter' do
83
- expect(User.scoped_from(order: 'firstname').first).to eq(users(:jane))
84
- expect(User.scoped_from(order: 'firstname.desc').first).to eq(users(:john))
85
- end
86
-
87
- it 'builds a ScopedFrom::Query' do
88
- expect(User.scoped_from({}).query.class).to be(ScopedFrom::Query)
89
- end
90
-
91
- it 'builds a ScopedFrom::Query if #{RecordClassName}Query is not defined' do
92
- expect(Post.scoped_from({}).query.class).to be(ScopedFrom::Query)
93
- expect(Object.const_defined?('PostQuery')).to be(false)
94
- expect {
95
- PostQuery
96
- }.to raise_error(NameError, 'uninitialized constant PostQuery')
97
- end
98
-
99
- it 'builds a #{Class}Query if #{RecordClassName}Query is defined and is a ScopedFrom::Query' do
100
- expect(Comment.scoped_from({}).query.class).to be(CommentQuery)
101
- expect(Comment.where(foo: 'bar').scoped_from({}).query.class).to be(CommentQuery)
102
- expect(CommentQuery).to be_a(Class)
103
- expect(CommentQuery.ancestors).to include(ScopedFrom::Query)
104
- end
105
-
106
- it 'builds a ScopedFrom::Query if #{RecordClassName}Query is defined but not a subclass of ScopedFrom::Query' do
107
- expect(User.scoped_from({}).query.class).to be(ScopedFrom::Query)
108
- expect(Object.const_defined?('UserQuery')).to be(true)
109
- expect(UserQuery).to be_a(Class)
110
- expect(UserQuery.ancestors).not_to include(ScopedFrom::Query)
111
- end
112
-
113
- it 'builds a ScopedFrom::Query if #{RecordClassName}Query is defined but is a module' do
114
- expect(Vote.scoped_from({}).query.class).to be(ScopedFrom::Query)
115
- expect(Object.const_defined?('VoteQuery')).to be(true)
116
- expect(VoteQuery).to be_a(Module)
117
- end
118
-
119
- it 'is accepts ActionController::Parameters' do
120
- expect(User.scoped_from(ActionController::Parameters.new(search: 'jane'))).to eq([users(:jane)])
121
- end
122
-
123
- end
124
-
125
- end
@@ -1,490 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ScopedFrom::Query do
4
-
5
- def query(relation = User, params = {}, options = {})
6
- ScopedFrom::Query.new(relation, params, options)
7
- end
8
-
9
- describe '#false?' do
10
-
11
- it 'is true if false is given' do
12
- expect(query.send(:false?, false)).to be(true)
13
- end
14
-
15
- it 'is true if "false" is given' do
16
- expect(query.send(:false?, 'false')).to be(true)
17
- expect(query.send(:false?, 'False')).to be(true)
18
- end
19
-
20
- it 'is true if "0" is given' do
21
- expect(query.send(:false?, '0')).to be(true)
22
- end
23
-
24
- it 'is true if "off" is given' do
25
- expect(query.send(:false?, 'off')).to be(true)
26
- expect(query.send(:false?, 'OFF ')).to be(true)
27
- end
28
-
29
- it 'is true if "no" is given' do
30
- expect(query.send(:false?, 'no')).to be(true)
31
- expect(query.send(:false?, ' No ')).to be(true)
32
- end
33
-
34
- it 'is true if "n" is given' do
35
- expect(query.send(:false?, 'n')).to be(true)
36
- expect(query.send(:false?, 'N ')).to be(true)
37
- end
38
-
39
- it 'is false if true is given' do
40
- expect(query.send(:false?, true)).to be(false)
41
- end
42
-
43
- it 'is false if "true" is given' do
44
- expect(query.send(:false?, 'true')).to be(false)
45
- expect(query.send(:false?, 'TrUe')).to be(false)
46
- end
47
-
48
- it 'is false if "1" is given' do
49
- expect(query.send(:false?, '1')).to be(false)
50
- end
51
-
52
- it 'is false if "on" is given' do
53
- expect(query.send(:false?, "on")).to be(false)
54
- expect(query.send(:false?, "On")).to be(false)
55
- end
56
-
57
- it 'is false otherwise' do
58
- expect(query.send(:false?, 42)).to be(false)
59
- expect(query.send(:false?, 'bam')).to be(false)
60
- end
61
-
62
- end
63
-
64
- describe '#initialize' do
65
-
66
- it 'invokes .all method on given class' do
67
- expect(User).to receive(:all)
68
- ScopedFrom::Query.new(User, {})
69
- end
70
-
71
- it 'does not invokes .all method on given relation' do
72
- relation = User.all
73
- expect(relation).not_to receive(:all)
74
- ScopedFrom::Query.new(relation, {})
75
- end
76
-
77
- end
78
-
79
- describe '#invoke_param' do
80
-
81
- it 'returns given scope if it has no scope with specified name' do
82
- expect(query.send(:invoke_param, User, :foo, true)).to eq(User)
83
- end
84
-
85
- it 'returns given scope if scope takes more than 1 argument' do
86
- expect(query.send(:invoke_param, User, :created_between, true)).to eq(User)
87
- end
88
-
89
- it 'invokes scope without arguments if scope takes no arguments' do
90
- expect(query.send(:invoke_param, User.all, :enabled, true)).to eq([users(:john)])
91
- expect(query.send(:invoke_param, User.all, :enabled, ' 1 ')).to eq([users(:john)])
92
- expect(query.send(:invoke_param, User.all, :enabled, 'off')).to eq([users(:john)])
93
- end
94
-
95
- it 'invokes scope with value has argument if scope takes one argument' do
96
- expect(query.send(:invoke_param, User.all, :search, 'doe')).to eq([users(:john), users(:jane)])
97
- expect(query.send(:invoke_param, User.all, :search, 'john')).to eq([users(:john)])
98
- expect(query.send(:invoke_param, User.all, :search, 'jane')).to eq([users(:jane)])
99
- end
100
-
101
- it 'scope on column conditions' do
102
- expect(query.send(:invoke_param, User.all, :firstname, 'Jane')).to eq([users(:jane)])
103
- end
104
-
105
- it 'invokes "order"' do
106
- expect(query.send(:invoke_param, User.all, :order, 'firstname.asc')).to eq([users(:jane), users(:john)])
107
- expect(query.send(:invoke_param, User.all, :order, 'firstname.desc')).to eq([users(:john), users(:jane)])
108
- end
109
-
110
- end
111
-
112
- describe '#options' do
113
-
114
- it 'is set at initialization' do
115
- expect(ScopedFrom::Query.new(User, {}, bar: 'foo').instance_variable_get(:@options)).to eq(bar: 'foo')
116
- end
117
-
118
- it 'keys are symbolized' do
119
- expect(ScopedFrom::Query.new(User, {}, 'bar' => 'foo').instance_variable_get(:@options)).to eq(bar: 'foo')
120
- end
121
-
122
- end
123
-
124
- describe '#order_column' do
125
-
126
- it 'is column specified into "order" parameter' do
127
- expect(query(User, order: 'firstname').order_column).to eq('firstname')
128
- expect(query(User, order: 'lastname.desc').order_column).to eq('lastname')
129
- end
130
-
131
- it 'is nil if column does not exist' do
132
- expect(query(User, order: 'foo').order_column).to be_nil
133
- end
134
-
135
- it 'is nil if "order" param is not specified' do
136
- expect(query(User, search: 'foo').order_column).to be_nil
137
- end
138
-
139
- end
140
-
141
- describe '#order_direction' do
142
-
143
- it 'is direction specified into "order" parameter' do
144
- expect(query(User, order: 'firstname.asc').order_direction).to eq('asc')
145
- expect(query(User, order: 'firstname.desc').order_direction).to eq('desc')
146
- end
147
-
148
- it 'is "asc" if direction is not specified' do
149
- expect(query(User, order: 'firstname').order_direction).to eq('asc')
150
- end
151
-
152
- it 'is "asc" if direction is invalid' do
153
- expect(query(User, order: 'firstname.foo').order_direction).to eq('asc')
154
- end
155
-
156
- it 'is direction even specified in another case' do
157
- expect(query(User, order: 'firstname.ASc').order_direction).to eq('asc')
158
- expect(query(User, order: 'firstname.DeSC').order_direction).to eq('desc')
159
- end
160
-
161
- it 'is nil if column does not exist' do
162
- expect(query(User, order: 'foo.desc').order_direction).to be_nil
163
- end
164
-
165
- it 'is nil if "order" param is not specified' do
166
- expect(query(User, search: 'foo').order_direction).to be_nil
167
- end
168
-
169
- end
170
-
171
- describe '#params' do
172
-
173
- it 'returns params specified at initialization' do
174
- expect(query(User, search: 'foo', 'enabled' => true).params).to eq({ 'search' => 'foo', 'enabled' => true })
175
- end
176
-
177
- it 'returns an hash with indifferent access' do
178
- expect(query(User, 'search' => 'bar').params).to be_a(ActiveSupport::HashWithIndifferentAccess)
179
- expect(query(User, 'search' => 'bar').params[:search]).to eq('bar')
180
- expect(query(User, search: 'bar').params['search']).to eq('bar')
181
- end
182
-
183
- it 'can be converted to query string' do
184
- expect(query(User, search: ['foo', 'bar'], 'enabled' => '1').params.to_query).to eq('enabled=true&search%5B%5D=foo&search%5B%5D=bar')
185
- end
186
-
187
- end
188
-
189
- describe '#params=' do
190
-
191
- it 'does not fails if nil is given' do
192
- expect(query(User, nil).params).to eq({})
193
- end
194
-
195
- it 'removes values that are not scopes' do
196
- expect(query(User, foo: 'bar', 'search' => 'foo', enabled: true).params).to eq({ 'search' => 'foo', 'enabled' => true })
197
- end
198
-
199
- it 'is case sensitive' do
200
- expect(query(User, 'Enabled' => true, "SEARCH" => 'bar').params).to be_empty
201
- end
202
-
203
- it 'parse query string' do
204
- expect(query(User, 'search=foo%26baz&latest=true').params).to eq({ 'search' => 'foo&baz', 'latest' => true })
205
- end
206
-
207
- it 'removes blank values from query string' do
208
- expect(query(User, 'search=baz&toto=&bar=%20').params).to eq({ 'search' => 'baz' })
209
- end
210
-
211
- it 'unescapes UTF-8 chars' do
212
- expect(query(User, 'search=%C3%A9').params).to eq({ 'search' => 'é' })
213
- end
214
-
215
- it 'can have multiple values (from hash)' do
216
- expect(query(User, search: ['bar', 'baz']).params).to eq({ 'search' => ['bar', 'baz'] })
217
- end
218
-
219
- it 'can have multiple values (from query string)' do
220
- expect(query(User, 'search=bar&search=baz').params).to eq({ 'search' => ['bar', 'baz'] })
221
- end
222
-
223
- it 'converts value to true (or remove it) if scope takes no argument' do
224
- expect(query(User, latest: 'y').params).to eq({ 'latest' => true })
225
- expect(query(User, latest: 'no').params).to eq({})
226
- end
227
-
228
- it 'converts value to true (or false) if column is a boolean one' do
229
- expect(query(User, admin: 'y').params).to eq({ 'admin' => true })
230
- expect(query(User, admin: 'False').params).to eq({ 'admin' => false })
231
- expect(query(User, admin: 'bar').params).to eq({})
232
- expect(query(User, admin: ['y', false]).params).to eq({})
233
- end
234
-
235
- it 'converts array value to true (or remove it) if scope takes no argument' do
236
- expect(query(User, latest: true).params).to eq({ 'latest' => true })
237
- expect(query(User, latest: ['Yes']).params).to eq({ 'latest' => true })
238
- expect(query(User, latest: ['no', 'yes']).params).to eq({})
239
- expect(query(User, latest: ['no', nil]).params).to eq({})
240
- expect(query(User, latest: ['fo']).params).to eq({})
241
- end
242
-
243
- it 'flats array' do
244
- expect(query(User, search: [nil, ['bar', '', 'foo', ["\n ", 'baz']]]).params).to eq({ 'search' => [nil, 'bar', '', 'foo', "\n ", 'baz'] })
245
- end
246
-
247
- it 'change array with a single value in one value' do
248
- expect(query(User, search: ['bar']).params).to eq({ 'search' => 'bar' })
249
- end
250
-
251
- it 'does not modify given hash' do
252
- hash = { search: 'foo', enabled: '1', bar: 'foo' }
253
- query(User, hash)
254
- expect(hash).to eq({ search: 'foo', enabled: '1', bar: 'foo' })
255
- end
256
-
257
- it 'does not modify given array' do
258
- items = ['bar', 'foo', nil]
259
- query(User, search: items)
260
- expect(items).to eq(['bar', 'foo', nil])
261
- end
262
-
263
- it 'accepts :only option' do
264
- expect(query(User, { search: 'bar', enabled: 'true' }, only: [:search]).params).to eq({ 'search' => 'bar' })
265
- expect(query(User, { search: 'bar', enabled: 'true' }, only: 'search').params).to eq({ 'search' => 'bar' })
266
- expect(query(User, { search: 'bar', firstname: 'Jane', enabled: 'true' }, only: 'search').params).to eq({ 'search' => 'bar' })
267
- expect(query(User, { search: 'bar', firstname: 'Jane', enabled: 'true' }, only: ['search', :firstname]).params).to eq({ 'search' => 'bar', 'firstname' => 'Jane' })
268
- end
269
-
270
- it 'accepts :except option' do
271
- expect(query(User, { search: 'bar', enabled: true }, except: [:search]).params).to eq({ 'enabled' => true })
272
- expect(query(User, { search: 'bar', enabled: true }, except: 'search').params).to eq({ 'enabled' => true })
273
- expect(query(User, { search: 'bar', firstname: 'Jane', enabled: true }, except: 'search').params).to eq({ 'enabled' => true, 'firstname' => 'Jane' })
274
- expect(query(User, { search: 'bar', firstname: 'Jane', enabled: true }, except: ['search', :firstname]).params).to eq({ 'enabled' => true })
275
- end
276
-
277
- it 'accepts a query instance' do
278
- expect(query(User, query(User, search: 'toto')).params).to eq({ 'search' => 'toto' })
279
- end
280
-
281
- it 'preserve blank values' do
282
- expect(query(User, { search: "\n ", 'enabled' => true }).params).to eq({ 'search' => "\n ", 'enabled' => true })
283
- end
284
-
285
- it 'preserve blank values from array' do
286
- expect(query(User, { 'search' => ["\n ", 'toto', 'titi'] }).params).to eq({ 'search' => ["\n ", 'toto', 'titi'] })
287
- expect(query(User, { 'search' => [] }).params).to eq({})
288
- end
289
-
290
- it 'also preserve blank on query string' do
291
- expect(query(User, 'search=%20&enabled=true&search=foo').params).to eq({ 'search' => [' ', 'foo'], 'enabled' => true })
292
- end
293
-
294
- it 'includes column values' do
295
- expect(query(User, 'firstname' => 'Jane', 'foo' => 'bar').params).to eq({ 'firstname' => 'Jane' })
296
- expect(query(User, firstname: 'Jane', 'foo' => 'bar').params).to eq({ 'firstname' => 'Jane' })
297
- end
298
-
299
- it 'exclude column values if :exclude_columns option is specified' do
300
- expect(query(User, { enabled: true, 'firstname' => 'Jane', 'foo' => 'bar' }, exclude_columns: true).params).to eq({ 'enabled' => true })
301
- expect(query(User, { enabled: true, firstname: 'Jane', foo: 'bar' }, exclude_columns: true).params).to eq({ 'enabled' => true })
302
- end
303
-
304
- it 'scopes have priority on columns' do
305
- expect(query(User, enabled: false).params).to eq({})
306
- end
307
-
308
- it 'maps an "order"' do
309
- expect(query(User, { 'order' => 'firstname.asc' }).params).to eq({ 'order' => 'firstname.asc' })
310
- end
311
-
312
- it 'does not map "order" if column is invalid' do
313
- expect(query(User, { 'order' => 'foo.asc' }).params).to eq({})
314
- end
315
-
316
- it 'use "asc" order direction by default' do
317
- expect(query(User, { 'order' => 'firstname' }).params).to eq({ 'order' => 'firstname.asc' })
318
- end
319
-
320
- it 'use "asc" order direction if invalid' do
321
- expect(query(User, { 'order' => 'firstname.bar' }).params).to eq({ 'order' => 'firstname.asc' })
322
- end
323
-
324
- it 'use "desc" order direction if specified' do
325
- expect(query(User, { 'order' => 'firstname.desc' }).params).to eq({ 'order' => 'firstname.desc' })
326
- end
327
-
328
- it 'order direction is case insensitive' do
329
- expect(query(User, { 'order' => 'firstname.Asc' }).params).to eq({ 'order' => 'firstname.asc' })
330
- expect(query(User, { 'order' => 'firstname.DESC' }).params).to eq({ 'order' => 'firstname.desc' })
331
- end
332
-
333
- it 'order can be specified as symbol' do
334
- expect(query(User, { order: 'firstname.desc' }).params).to eq({ 'order' => 'firstname.desc' })
335
- end
336
-
337
- it "order is case sensitive" do
338
- expect(query(User, { 'Order' => 'firstname.desc' }).params).to eq({})
339
- end
340
-
341
- it 'many order can be specified' do
342
- expect(query(User, { 'order' => ['firstname.Asc', 'lastname.DESC'] }).params).to eq({ 'order' => ['firstname.asc', 'lastname.desc'] })
343
- expect(query(User, { 'order' => ['firstname.Asc', 'firstname.desc'] }).params).to eq({ 'order' => 'firstname.asc' })
344
- expect(query(User, { 'order' => ['firstname.Asc', 'lastname.DESC', 'firstname.desc'] }).params).to eq({ 'order' => ['firstname.asc', 'lastname.desc'] })
345
- expect(query(User, { 'order' => ['firstname.Asc', 'foo', 'lastname.DESC', 'firstname.desc'] }).params).to eq({ 'order' => ['firstname.asc', 'lastname.desc'] })
346
- end
347
-
348
- it 'order can be delimited by a space' do
349
- expect(query(User, { 'order' => 'firstname ASC' }).params).to eq({ 'order' => 'firstname.asc' })
350
- end
351
-
352
- it 'order can be delimited by any white space' do
353
- expect(query(User, { 'order' => "firstname\nASC" }).params).to eq({ 'order' => 'firstname.asc' })
354
- expect(query(User, { 'order' => "firstname\t ASC" }).params).to eq({ 'order' => 'firstname.asc' })
355
- end
356
-
357
- it 'order can be delimited by a ":"' do
358
- expect(query(User, { 'order' => "firstname:ASC" }).params).to eq({ 'order' => 'firstname.asc' })
359
- end
360
-
361
- it 'order can be delimited by more than one delimiter' do
362
- expect(query(User, { 'order' => "firstname :. ASC" }).params).to eq({ 'order' => 'firstname.asc' })
363
- end
364
-
365
- end
366
-
367
- describe '#relation' do
368
-
369
- it 'does not execute any query' do
370
- expect(User).not_to receive(:connection)
371
- query(User, enabled: true).relation
372
- end
373
-
374
- it 'works with scopes with a lambda without arguments' do
375
- users(:jane).update_attribute(:created_at, 10.days.ago)
376
- expect(query(User, latest: true).relation).to eq([users(:john)])
377
- expect(query(User, latest: false).relation).to eq([users(:john), users(:jane)])
378
- end
379
-
380
- it 'does not modify relation specified at initialization' do
381
- relation = User.search('foo')
382
- q = query(relation, enabled: true)
383
- expect {
384
- expect {
385
- q.relation
386
- }.not_to change { q.instance_variable_get('@relation') }
387
- }.not_to change { relation }
388
- end
389
-
390
- it 'returns relation specified at construction if params are empty' do
391
- expect(query.relation).not_to eq(User)
392
- expect(query.relation).to eq(User.all)
393
- end
394
-
395
- it 'invokes many times relation if an array is given' do
396
- expect(query(User, search: ['John', 'Doe']).relation).to eq([users(:john)])
397
- expect(query(User, search: ['John', 'Done']).relation).to eq([])
398
- expect(query(User, search: ['John', 'Doe']).params).to eq({ 'search' => ['John', 'Doe'] })
399
- end
400
-
401
- it 'invokes many times relation if given twice (as string & symbol)' do
402
- expect(query(User, search: 'John', 'search' => 'Done').params['search']).to contain_exactly('John', 'Done')
403
- expect(query(User, search: 'John', 'search' => ['Did', 'Done']).params['search']).to contain_exactly('John', 'Did', 'Done')
404
- end
405
-
406
- it 'invokes last order if an array is given' do
407
- create_user(:jane2, firstname: 'Jane', lastname: 'Zoe')
408
-
409
- expect(query(User, order: ['lastname', 'firstname']).relation).to eq([users(:jane), users(:john), users(:jane2)])
410
- expect(query(User, order: ['lastname', 'firstname.desc']).relation).to eq([users(:john), users(:jane), users(:jane2)])
411
- expect(query(User, order: ['firstname', 'lastname.desc']).relation).to eq([users(:jane2), users(:jane), users(:john)])
412
- expect(query(User, order: ['firstname.desc', 'lastname']).relation.order_values.map(&:class)).to eq([Arel::Nodes::Descending, Arel::Nodes::Ascending])
413
- expect(query(User, order: ['firstname.desc', 'lastname']).relation.order_values.map(&:expr).map(&:name)).to eq(['firstname', 'lastname'])
414
- end
415
-
416
- it 'defines #query method on returned relation' do
417
- expect(query(User).relation).to respond_to(:query)
418
- end
419
-
420
- it 'does not define #query method for future relations' do
421
- expect(query(User).relation.query).to be_present
422
- expect(User).not_to respond_to(:query)
423
- expect(User.all).not_to respond_to(:query)
424
- expect(User.enabled).not_to respond_to(:query)
425
- end
426
-
427
- it 'defined #query method returns query' do
428
- q = query(User)
429
- expect(q.relation.query).to be_a(ScopedFrom::Query)
430
- expect(q.relation.query).to be(q)
431
- end
432
-
433
- end
434
-
435
- describe '#true?' do
436
-
437
- it 'is true if true is given' do
438
- expect(query.send(:true?, true)).to be(true)
439
- end
440
-
441
- it 'is true if "true" is given' do
442
- expect(query.send(:true?, 'true')).to be(true)
443
- expect(query.send(:true?, 'True')).to be(true)
444
- end
445
-
446
- it 'is true if "1" is given' do
447
- expect(query.send(:true?, '1')).to be(true)
448
- end
449
-
450
- it 'is true if "on" is given' do
451
- expect(query.send(:true?, 'on')).to be(true)
452
- expect(query.send(:true?, 'ON ')).to be(true)
453
- end
454
-
455
- it 'is true if "yes" is given' do
456
- expect(query.send(:true?, 'yes')).to be(true)
457
- expect(query.send(:true?, ' Yes ')).to be(true)
458
- end
459
-
460
- it 'is true if "y" is given' do
461
- expect(query.send(:true?, 'y')).to be(true)
462
- expect(query.send(:true?, 'Y ')).to be(true)
463
- end
464
-
465
- it 'is false if false is given' do
466
- expect(query.send(:true?, false)).to be(false)
467
- end
468
-
469
- it 'is false if "false" is given' do
470
- expect(query.send(:true?, 'false')).to be(false)
471
- expect(query.send(:true?, 'FsALSE')).to be(false)
472
- end
473
-
474
- it 'is false if "0" is given' do
475
- expect(query.send(:true?, '0')).to be(false)
476
- end
477
-
478
- it 'is false if "off" is given' do
479
- expect(query.send(:true?, "off")).to be(false)
480
- expect(query.send(:true?, "Off")).to be(false)
481
- end
482
-
483
- it 'is false otherwise' do
484
- expect(query.send(:true?, 42)).to be(false)
485
- expect(query.send(:true?, 'bam')).to be(false)
486
- end
487
-
488
- end
489
-
490
- end
@@ -1,20 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ScopedFrom do
4
-
5
- describe '.version' do
6
-
7
- subject { ScopedFrom.version }
8
-
9
- it { should be_a(String) }
10
- it { should match(/^\d+\.\d+(\.\d+)?/) }
11
-
12
- it 'is freezed' do
13
- expect {
14
- ScopedFrom.version.gsub!('.', '#')
15
- }.to raise_error(/can't modify frozen string/i)
16
- end
17
-
18
- end
19
-
20
- end
data/spec/spec_helper.rb DELETED
@@ -1,27 +0,0 @@
1
- ENV["RAILS_ENV"] ||= 'test'
2
-
3
- require File.expand_path("#{__dir__}/../lib/scoped_from")
4
- require 'action_controller'
5
- require 'byebug'
6
-
7
- # Support
8
- Dir["#{__dir__}/support/**/*.rb"].each { |f| require File.expand_path(f) }
9
-
10
- # Mocks
11
- ActiveSupport::Dependencies.autoload_paths << "#{__dir__}/mocks"
12
-
13
- RSpec.configure do |config|
14
- config.raise_errors_for_deprecations!
15
-
16
- config.include(UserMacro)
17
-
18
- config.before(:each) do
19
- Comment.delete_all
20
- Post.delete_all
21
- User.delete_all
22
- Vote.delete_all
23
-
24
- create_user(:john, firstname: 'John', lastname: 'Doe', enabled: true, admin: true)
25
- create_user(:jane, firstname: 'Jane', lastname: 'Doe', enabled: false, admin: false)
26
- end
27
- end
@@ -1,12 +0,0 @@
1
- ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: File.expand_path("#{__dir__}/../../test.sqlite3"), timeout: 5000)
2
-
3
- ActiveRecord::Base.connection.create_table(:comments, force: true)
4
- ActiveRecord::Base.connection.create_table(:posts, force: true)
5
- ActiveRecord::Base.connection.create_table(:users, force: true) do |t|
6
- t.string :firstname, null: false
7
- t.string :lastname, null: false
8
- t.boolean :enabled, null: false, default: false
9
- t.boolean :admin, null: false, default: false
10
- t.timestamps null: false
11
- end
12
- ActiveRecord::Base.connection.create_table(:votes, force: true)
@@ -1,13 +0,0 @@
1
- module UserMacro
2
-
3
- USERS = {}
4
-
5
- def create_user(label, attributes)
6
- USERS[label] = User.create!(attributes)
7
- end
8
-
9
- def users(label)
10
- USERS[label]
11
- end
12
-
13
- end