rack-reducer 2.0.0 → 2.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 +4 -4
- data/README.md +1 -1
- data/lib/rack/reducer.rb +9 -2
- data/lib/rack/reducer/version.rb +1 -1
- data/spec/rails_spec.rb +41 -3
- data/spec/reducer_spec.rb +26 -7
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c069005f0502425e332cd99bb9b27d11ab257baa937be74ce96b120e6af1cb70
|
4
|
+
data.tar.gz: 7c818a942e2d5b6fe50aa6832c74d11592d76e16d6cd92d31aeb4bc608092a3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3db32664cc591ecb2efa31d9bb39a4c3efb321e21a8fcabd5355416b7fca771ef9c2c90be57913f9b44bad100c95900e0ca8e2b14fcf3931f32cad8d70cd62e8
|
7
|
+
data.tar.gz: fc199821f33b07ae4f3684dd2f56367d89415bd16385ae6bb383df220e4266564ca8d6092443dea1bafbb50378660d173caceef36dd3f3c17d4afe52f7da81fa
|
data/README.md
CHANGED
data/lib/rack/reducer.rb
CHANGED
@@ -51,7 +51,7 @@ module Rack
|
|
51
51
|
def apply(url_params)
|
52
52
|
if url_params.empty?
|
53
53
|
# Return early with the unfiltered dataset if no default filters exist
|
54
|
-
return
|
54
|
+
return fresh_dataset if @default_filters.empty?
|
55
55
|
|
56
56
|
# Run only the default filters
|
57
57
|
filters, params = @default_filters, EMPTY_PARAMS
|
@@ -66,7 +66,7 @@ module Rack
|
|
66
66
|
private
|
67
67
|
|
68
68
|
def reduce(params, filters)
|
69
|
-
filters.reduce(
|
69
|
+
filters.reduce(fresh_dataset) do |data, filter|
|
70
70
|
next data unless filter.satisfies?(params)
|
71
71
|
|
72
72
|
data.instance_exec(
|
@@ -76,6 +76,13 @@ module Rack
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
+
# Rails +Model.all+ relations get query-cached by default, which has caused
|
80
|
+
# filterless requests to load stale data. This method busts the query cache.
|
81
|
+
# See https://github.com/chrisfrank/rack-reducer/issues/11
|
82
|
+
def fresh_dataset
|
83
|
+
@dataset.clone
|
84
|
+
end
|
85
|
+
|
79
86
|
EMPTY_PARAMS = {}.freeze
|
80
87
|
private_constant :EMPTY_PARAMS
|
81
88
|
end
|
data/lib/rack/reducer/version.rb
CHANGED
data/spec/rails_spec.rb
CHANGED
@@ -2,9 +2,13 @@ require 'spec_helper'
|
|
2
2
|
require_relative 'fixtures'
|
3
3
|
|
4
4
|
Process.respond_to?(:fork) && RSpec.describe('in a Rails app') do
|
5
|
+
using SpecRefinements
|
5
6
|
BuildRailsApp = lambda do
|
6
7
|
require 'action_controller/railtie'
|
8
|
+
require 'active_record'
|
7
9
|
require 'securerandom'
|
10
|
+
require 'sqlite3'
|
11
|
+
|
8
12
|
app = Class.new(Rails::Application) do
|
9
13
|
routes.append do
|
10
14
|
get "/", to: "artists#index"
|
@@ -16,14 +20,33 @@ Process.respond_to?(:fork) && RSpec.describe('in a Rails app') do
|
|
16
20
|
config.secret_key_base = SecureRandom.hex(64)
|
17
21
|
end
|
18
22
|
|
23
|
+
ActiveRecord::Base.establish_connection("sqlite3::memory:")
|
24
|
+
ActiveRecord::Schema.define do
|
25
|
+
create_table :artists do |t|
|
26
|
+
t.string :name
|
27
|
+
t.string :genre
|
28
|
+
t.integer :release_count
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Artist = Class.new(ActiveRecord::Base)
|
33
|
+
|
34
|
+
Fixtures::DB[:artists].each { |row| Artist.create(row) }
|
35
|
+
|
19
36
|
ArtistsController = Class.new(ActionController::API) do
|
37
|
+
RailsReducer = Rack::Reducer.new(
|
38
|
+
Artist.all,
|
39
|
+
->(name:) { where('lower(name) like ?', "%#{name.downcase}%") },
|
40
|
+
->(genre:) { where(genre: genre) },
|
41
|
+
)
|
42
|
+
|
20
43
|
def index
|
21
|
-
@artists =
|
44
|
+
@artists = RailsReducer.apply(params)
|
22
45
|
render json: @artists
|
23
46
|
end
|
24
47
|
|
25
48
|
def query
|
26
|
-
@artists =
|
49
|
+
@artists = RailsReducer.apply(request.query_parameters)
|
27
50
|
render json: @artists
|
28
51
|
end
|
29
52
|
end
|
@@ -47,7 +70,22 @@ Process.respond_to?(:fork) && RSpec.describe('in a Rails app') do
|
|
47
70
|
Process.wait(pid)
|
48
71
|
end
|
49
72
|
|
50
|
-
it '
|
73
|
+
it 'tracks updates to the backend between requests' do
|
74
|
+
pid = Process.fork do
|
75
|
+
get("/") { |res| expect(res.json.count).to eq(6) }
|
76
|
+
|
77
|
+
Artist.create!(name: "RZA")
|
78
|
+
|
79
|
+
get("/") { |res| expect(res.json.count).to eq(7) }
|
80
|
+
|
81
|
+
Artist.find_by(name: "RZA").destroy
|
82
|
+
|
83
|
+
get("/") { |res| expect(res.json.count).to eq(6) }
|
84
|
+
end
|
85
|
+
Process.wait(pid)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'does not pollute the global Ruby scope' do
|
51
89
|
expect { ''.blank? }.to raise_error(NoMethodError)
|
52
90
|
end
|
53
91
|
end
|
data/spec/reducer_spec.rb
CHANGED
@@ -26,13 +26,6 @@ RSpec.describe 'Rack::Reducer' do
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
it 'resets state between requests' do
|
30
|
-
get('/artists?name=Blake')
|
31
|
-
get('/artists') do |res|
|
32
|
-
expect(res.json.count).to eq(Fixtures::DB[:artists].count)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
29
|
it 'filters by a single param, e.g. genre' do
|
37
30
|
get('/artists?genre=electronic') do |response|
|
38
31
|
expect(response.body).to include('Björk')
|
@@ -64,6 +57,32 @@ RSpec.describe 'Rack::Reducer' do
|
|
64
57
|
expect(Fixtures::ArtistReducer.apply(nil)).to be_truthy
|
65
58
|
end
|
66
59
|
|
60
|
+
describe 'between requests' do
|
61
|
+
original_count = Fixtures::DB[:artists].count
|
62
|
+
|
63
|
+
it 'resets filter state' do
|
64
|
+
get('/artists?name=Blake')
|
65
|
+
get('/artists') do |res|
|
66
|
+
expect(res.json.count).to eq(Fixtures::DB[:artists].count)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'tracks updates to the backend' do
|
71
|
+
get('/artists')
|
72
|
+
|
73
|
+
Fixtures::DB[:artists][0][:name] = "Lizzo"
|
74
|
+
Fixtures::DB[:artists] << { name: 'New Artist' }
|
75
|
+
|
76
|
+
get('/artists') do |response|
|
77
|
+
expect(response.json.count).to eq(original_count + 1)
|
78
|
+
expect(response.json.dig(0, 'name')).to eq('Lizzo')
|
79
|
+
end
|
80
|
+
|
81
|
+
Fixtures::DB[:artists].pop
|
82
|
+
Fixtures::DB[:artists][0][:name] = "Blake Mills"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
67
86
|
describe 'with default filters' do
|
68
87
|
let(:app) do
|
69
88
|
sort = ->(sort: 'name') { sort_by { |item| item[sort.to_sym] } }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-reducer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Frank
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-05
|
11
|
+
date: 2019-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '5.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.2'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.2'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: benchmark-ips
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -170,14 +184,14 @@ dependencies:
|
|
170
184
|
requirements:
|
171
185
|
- - "~>"
|
172
186
|
- !ruby/object:Gem::Version
|
173
|
-
version:
|
187
|
+
version: 1.3.6
|
174
188
|
type: :development
|
175
189
|
prerelease: false
|
176
190
|
version_requirements: !ruby/object:Gem::Requirement
|
177
191
|
requirements:
|
178
192
|
- - "~>"
|
179
193
|
- !ruby/object:Gem::Version
|
180
|
-
version:
|
194
|
+
version: 1.3.6
|
181
195
|
- !ruby/object:Gem::Dependency
|
182
196
|
name: yard
|
183
197
|
requirement: !ruby/object:Gem::Requirement
|