scoped_from 1.0.1 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 88f3cb11e67b82da5d005daacea281154d2818ba
4
- data.tar.gz: 981bb72c4e756353749084e3503ab9b03469cfd4
2
+ SHA256:
3
+ metadata.gz: c174dce6961320bbde11d567cc8182fddef4ece108a0e606100dc089884490ae
4
+ data.tar.gz: 040e97a0b3d983fd099d1f3cd306a2d61cd43b2e00b45ab183359b16a86d2bbb
5
5
  SHA512:
6
- metadata.gz: 82a281b707f6eb1d102131e06c9da5dcf7dec0a178d2ecc0b034e84589dc7ec4267362c56be037792011e809c6e1eb2200f2d6f0bce92af0576fc08b2e6378d1
7
- data.tar.gz: 79c0f7e9e6b4ab871aa2243fae328f004a6a1aa8ebb4bb750d1a58903e8e059626dd52f65d0e0fb5e9937f2df67f5513a19262a0a77dc14952c6c1947faa6cf6
6
+ metadata.gz: f66fb8926e1e5d443df1b896540f207951c416b4ef47bb969d7e090ccfc73cae75d36996019f7dd48edaa70f1472b427a35d96268a8d3882a07ecd2cb127e2e1
7
+ data.tar.gz: 9e718bc1814ca6259f8bf62290199a36f026d94afdc5dc49ed615cfec8a5b0f7a12ff41b55514e2f90873e58b501ea412389c8da7a64bd9e521a446c66e84ad1
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.1
1
+ 2.0.0
@@ -27,8 +27,8 @@ module ScopedFrom
27
27
  def relation
28
28
  relation = @relation
29
29
  params.each do |name, value|
30
- [value].flatten.each do |value|
31
- relation = invoke_param(relation, name, value)
30
+ [value].flatten.each do |val|
31
+ relation = invoke_param(relation, name, val)
32
32
  end
33
33
  end
34
34
  decorate_relation(relation)
@@ -83,14 +83,14 @@ module ScopedFrom
83
83
  orders = parse_orders(values).map { |order| "#{order[:column]}.#{order[:direction]}" }
84
84
  @params[name] = (orders.many? ? orders : orders.first) if orders.any?
85
85
  elsif @relation.scope_without_argument?(name)
86
- @params[name] = true if values.all? { |value| true?(value) }
86
+ @params[name] = true if values.all? { |val| true?(val) }
87
87
  elsif @relation.scope_with_one_argument?(name)
88
88
  value = values.many? ? values : values.first
89
89
  @params[name] = @params[name] ? [@params[name], value].flatten : value
90
90
  elsif @options[:exclude_columns].blank? && @relation.column_names.include?(name.to_s)
91
91
  if @relation.columns_hash[name.to_s].type == :boolean
92
- @params[name] = true if values.all? { |value| true?(value) }
93
- @params[name] = false if values.all? { |value| false?(value) }
92
+ @params[name] = true if values.all? { |val| true?(val) }
93
+ @params[name] = false if values.all? { |val| false?(val) }
94
94
  else
95
95
  value = values.many? ? values : values.first
96
96
  @params[name] = @params[name] ? [@params[name], value].flatten : value
@@ -102,17 +102,17 @@ module ScopedFrom
102
102
  end
103
103
 
104
104
  def parse_order(value)
105
- column, direction = value.to_s.split(/[\.:\s]+/, 2)
105
+ column, direction = value.to_s.split(/[.:\s]+/, 2)
106
106
  direction = direction.to_s.downcase
107
107
  direction = ORDER_DIRECTIONS.first unless ORDER_DIRECTIONS.include?(direction)
108
- @relation.column_names.include?(column) ? { column: column, direction: direction } : {}
108
+ @relation.column_names.include?(column) ? { column:, direction: } : {}
109
109
  end
110
110
 
111
111
  def parse_orders(values)
112
112
  [].tap do |orders|
113
113
  values.each do |value|
114
114
  order = parse_order(value)
115
- orders << order if order.present? && !orders.any? { |o| o[:column] == order[:column] }
115
+ orders << order if order.present? && orders.none? { |o| o[:column] == order[:column] }
116
116
  end
117
117
  end
118
118
  end
data/lib/scoped_from.rb CHANGED
@@ -9,7 +9,7 @@ require 'active_support/core_ext/object/to_query'
9
9
  module ScopedFrom
10
10
 
11
11
  def self.version
12
- @@version ||= File.read(File.expand_path("#{__dir__}/../VERSION")).strip.freeze
12
+ @version ||= File.read(File.expand_path("#{__dir__}/../VERSION")).strip.freeze
13
13
  end
14
14
 
15
15
  end
@@ -19,4 +19,4 @@ lib_path = "#{__dir__}/scoped_from"
19
19
  require "#{lib_path}/active_record"
20
20
  require "#{lib_path}/query"
21
21
 
22
- ActiveRecord::Base.send(:include, ScopedFrom::ActiveRecord)
22
+ ActiveRecord::Base.include(ScopedFrom::ActiveRecord)
data/scoped_from.gemspec CHANGED
@@ -9,19 +9,21 @@ 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")
16
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ s.files = %x(git ls-files | grep -vE '^(spec/|test/|\\.|Gemfile|Rakefile)').split("\n")
13
+ s.executables = %x(git ls-files -- bin/*).split("\n").map { |f| File.basename(f) }
17
14
  s.require_paths = ['lib']
18
15
 
19
- s.add_dependency 'activerecord', '>= 5.0.0', '< 5.1.0'
20
- s.add_dependency 'activesupport', '>= 5.0.0', '< 5.1.0'
16
+ s.required_ruby_version = '>= 3.1.0'
17
+
18
+ s.add_dependency 'activerecord', '>= 7.0.0', '< 8.0.0'
19
+ s.add_dependency 'activesupport', '>= 7.0.0', '< 8.0.0'
21
20
 
22
- s.add_development_dependency 'actionpack', '>= 5.0.0', '< 5.1.0'
23
- s.add_development_dependency 'byebug', '>= 3.2.0', '< 10.0.0'
24
- s.add_development_dependency 'rake', '>= 10.3.0', '< 12.0.0'
25
- s.add_development_dependency 'rspec', '>= 3.1.0', '< 3.6.0'
21
+ s.add_development_dependency 'actionpack', '>= 7.0.0', '< 8.0.0'
22
+ s.add_development_dependency 'byebug', '>= 3.2.0', '< 12.0.0'
23
+ s.add_development_dependency 'rake', '>= 10.3.0', '< 14.0.0'
24
+ s.add_development_dependency 'rspec', '>= 3.1.0', '< 3.11.0'
25
+ s.add_development_dependency 'rubocop', '>= 1.25.0', '< 2.0.0'
26
+ s.add_development_dependency 'rubocop-rake', '>= 0.6.0', '< 1.0.0'
27
+ s.add_development_dependency 'rubocop-rspec', '>= 2.8.0', '< 3.0.0'
26
28
  s.add_development_dependency 'sqlite3-ruby', '>= 1.3.0', '< 1.4.0'
27
29
  end
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: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexis Toulotte
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-22 00:00:00.000000000 Z
11
+ date: 2022-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,60 +16,60 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 5.0.0
19
+ version: 7.0.0
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 5.1.0
22
+ version: 8.0.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 5.0.0
29
+ version: 7.0.0
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 5.1.0
32
+ version: 8.0.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: activesupport
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: 5.0.0
39
+ version: 7.0.0
40
40
  - - "<"
41
41
  - !ruby/object:Gem::Version
42
- version: 5.1.0
42
+ version: 8.0.0
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 5.0.0
49
+ version: 7.0.0
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
- version: 5.1.0
52
+ version: 8.0.0
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: actionpack
55
55
  requirement: !ruby/object:Gem::Requirement
56
56
  requirements:
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: 5.0.0
59
+ version: 7.0.0
60
60
  - - "<"
61
61
  - !ruby/object:Gem::Version
62
- version: 5.1.0
62
+ version: 8.0.0
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: 5.0.0
69
+ version: 7.0.0
70
70
  - - "<"
71
71
  - !ruby/object:Gem::Version
72
- version: 5.1.0
72
+ version: 8.0.0
73
73
  - !ruby/object:Gem::Dependency
74
74
  name: byebug
75
75
  requirement: !ruby/object:Gem::Requirement
@@ -79,7 +79,7 @@ dependencies:
79
79
  version: 3.2.0
80
80
  - - "<"
81
81
  - !ruby/object:Gem::Version
82
- version: 10.0.0
82
+ version: 12.0.0
83
83
  type: :development
84
84
  prerelease: false
85
85
  version_requirements: !ruby/object:Gem::Requirement
@@ -89,7 +89,7 @@ dependencies:
89
89
  version: 3.2.0
90
90
  - - "<"
91
91
  - !ruby/object:Gem::Version
92
- version: 10.0.0
92
+ version: 12.0.0
93
93
  - !ruby/object:Gem::Dependency
94
94
  name: rake
95
95
  requirement: !ruby/object:Gem::Requirement
@@ -99,7 +99,7 @@ dependencies:
99
99
  version: 10.3.0
100
100
  - - "<"
101
101
  - !ruby/object:Gem::Version
102
- version: 12.0.0
102
+ version: 14.0.0
103
103
  type: :development
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
@@ -109,7 +109,7 @@ dependencies:
109
109
  version: 10.3.0
110
110
  - - "<"
111
111
  - !ruby/object:Gem::Version
112
- version: 12.0.0
112
+ version: 14.0.0
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: rspec
115
115
  requirement: !ruby/object:Gem::Requirement
@@ -119,7 +119,7 @@ dependencies:
119
119
  version: 3.1.0
120
120
  - - "<"
121
121
  - !ruby/object:Gem::Version
122
- version: 3.6.0
122
+ version: 3.11.0
123
123
  type: :development
124
124
  prerelease: false
125
125
  version_requirements: !ruby/object:Gem::Requirement
@@ -129,7 +129,67 @@ dependencies:
129
129
  version: 3.1.0
130
130
  - - "<"
131
131
  - !ruby/object:Gem::Version
132
- version: 3.6.0
132
+ version: 3.11.0
133
+ - !ruby/object:Gem::Dependency
134
+ name: rubocop
135
+ requirement: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: 1.25.0
140
+ - - "<"
141
+ - !ruby/object:Gem::Version
142
+ version: 2.0.0
143
+ type: :development
144
+ prerelease: false
145
+ version_requirements: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: 1.25.0
150
+ - - "<"
151
+ - !ruby/object:Gem::Version
152
+ version: 2.0.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-rake
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: 0.6.0
160
+ - - "<"
161
+ - !ruby/object:Gem::Version
162
+ version: 1.0.0
163
+ type: :development
164
+ prerelease: false
165
+ version_requirements: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ version: 0.6.0
170
+ - - "<"
171
+ - !ruby/object:Gem::Version
172
+ version: 1.0.0
173
+ - !ruby/object:Gem::Dependency
174
+ name: rubocop-rspec
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: 2.8.0
180
+ - - "<"
181
+ - !ruby/object:Gem::Version
182
+ version: 3.0.0
183
+ type: :development
184
+ prerelease: false
185
+ version_requirements: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: 2.8.0
190
+ - - "<"
191
+ - !ruby/object:Gem::Version
192
+ version: 3.0.0
133
193
  - !ruby/object:Gem::Dependency
134
194
  name: sqlite3-ruby
135
195
  requirement: !ruby/object:Gem::Requirement
@@ -157,35 +217,18 @@ executables: []
157
217
  extensions: []
158
218
  extra_rdoc_files: []
159
219
  files:
160
- - ".gitignore"
161
- - ".rspec"
162
- - Gemfile
163
220
  - MIT-LICENSE
164
221
  - README.mdown
165
- - Rakefile
166
222
  - VERSION
167
223
  - lib/scoped_from.rb
168
224
  - lib/scoped_from/active_record.rb
169
225
  - lib/scoped_from/query.rb
170
226
  - 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
227
  homepage: https://github.com/alexistoulotte/scoped_from
185
228
  licenses:
186
229
  - MIT
187
230
  metadata: {}
188
- post_install_message:
231
+ post_install_message:
189
232
  rdoc_options: []
190
233
  require_paths:
191
234
  - lib
@@ -193,16 +236,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
193
236
  requirements:
194
237
  - - ">="
195
238
  - !ruby/object:Gem::Version
196
- version: '0'
239
+ version: 3.1.0
197
240
  required_rubygems_version: !ruby/object:Gem::Requirement
198
241
  requirements:
199
242
  - - ">="
200
243
  - !ruby/object:Gem::Version
201
244
  version: '0'
202
245
  requirements: []
203
- rubyforge_project: scoped_from
204
- rubygems_version: 2.5.1
205
- signing_key:
246
+ rubygems_version: 3.3.3
247
+ signing_key:
206
248
  specification_version: 4
207
249
  summary: Mapping between scopes and parameters for Rails
208
250
  test_files: []
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