rack-reducer 2.0.0 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89560b1f9fb58a56452e6e9cbba2a9dd5e0159b938c804628750549da310c543
4
- data.tar.gz: f7e9667193f0e4e6e5b413ceec8506919f784604d5be97746239688f3074ab8b
3
+ metadata.gz: c069005f0502425e332cd99bb9b27d11ab257baa937be74ce96b120e6af1cb70
4
+ data.tar.gz: 7c818a942e2d5b6fe50aa6832c74d11592d76e16d6cd92d31aeb4bc608092a3e
5
5
  SHA512:
6
- metadata.gz: fa641c8d24f2bd6a52f523e447c43d1714c92db33175750b4728512bcdca9f5668a018a4be1b5a504fb3ad0188ace6e5e3911503c6a06d48cbf3d9a64aecf489
7
- data.tar.gz: d60cbdae9d7d225024680262be9be5b8b92a923ad224452dfd7e383410e75d5ee717ac3842b9f0ed95ebb8b3789ef36bc3880794b62577f1162a6d67816df77b
6
+ metadata.gz: 3db32664cc591ecb2efa31d9bb39a4c3efb321e21a8fcabd5355416b7fca771ef9c2c90be57913f9b44bad100c95900e0ca8e2b14fcf3931f32cad8d70cd62e8
7
+ data.tar.gz: fc199821f33b07ae4f3684dd2f56367d89415bd16385ae6bb383df220e4266564ca8d6092443dea1bafbb50378660d173caceef36dd3f3c17d4afe52f7da81fa
data/README.md CHANGED
@@ -161,7 +161,7 @@ class Artist < ApplicationRecord
161
161
  ->(name:) { by_name(name) },
162
162
  ->(genre:) { where(genre: genre) },
163
163
  ->(sort:) { order(sort.to_sym) }
164
- ]
164
+ )
165
165
 
166
166
  scope :by_name, lambda { |name|
167
167
  where('lower(name) like ?', "%#{name.downcase}%")
@@ -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 @dataset if @default_filters.empty?
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(@dataset) do |data, filter|
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rack
4
4
  class Reducer
5
- VERSION = '2.0.0'
5
+ VERSION = '2.0.2'
6
6
  end
7
7
  end
@@ -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 = Fixtures::ArtistReducer.apply(params)
44
+ @artists = RailsReducer.apply(params)
22
45
  render json: @artists
23
46
  end
24
47
 
25
48
  def query
26
- @artists = Fixtures::ArtistReducer.apply(request.query_parameters)
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 'does not load ActiveSupport into global scope b/c of this spec' do
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
@@ -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.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-02 00:00:00.000000000 Z
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: '1'
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: '1'
194
+ version: 1.3.6
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: yard
183
197
  requirement: !ruby/object:Gem::Requirement