Skip to content

Commit 668b589

Browse files
authored
Merge pull request #1453 from projectblacklight/search-state
Update Blacklight::SearchState to play well with Rails 5 AC::Parameters class
2 parents 1b1b6e6 + ac32e38 commit 668b589

File tree

2 files changed

+73
-36
lines changed

2 files changed

+73
-36
lines changed

lib/blacklight/search_state.rb

+10-7
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,25 @@ class SearchState
1010
# @param [ActionController::Parameters] params
1111
# @param [Blacklight::Config] blacklight_config
1212
def initialize(params, blacklight_config)
13-
if params.instance_of? Hash
14-
# This is an ActionView::TestCase workaround. Will be resolved by
15-
# https://github.com/rails/rails/pull/22913 (Rails > 4.2.5)
16-
@params = params.with_indifferent_access
17-
else
13+
if params.respond_to?(:to_unsafe_h)
1814
# This is the typical (not-ActionView::TestCase) code path.
1915
@params = params.to_unsafe_h
2016
# In Rails 5 to_unsafe_h returns a HashWithIndifferentAccess, in Rails 4 it returns Hash
2117
@params = @params.with_indifferent_access if @params.instance_of? Hash
18+
elsif params.is_a? Hash
19+
# This is an ActionView::TestCase workaround for Rails 4.2.
20+
@params = params.dup.with_indifferent_access
21+
else
22+
@params = params.dup.to_h.with_indifferent_access
2223
end
24+
2325
@blacklight_config = blacklight_config
2426
end
2527

26-
def to_h
28+
def to_hash
2729
@params
2830
end
31+
alias to_h to_hash
2932

3033
def reset
3134
Blacklight::SearchState.new(ActionController::Parameters.new, blacklight_config)
@@ -112,7 +115,7 @@ def remove_facet_params(field, item)
112115
# @yield [params] The merged parameters hash before being sanitized
113116
def params_for_search(params_to_merge={}, &block)
114117
# params hash we'll return
115-
my_params = params.dup.merge(params_to_merge.dup)
118+
my_params = params.dup.merge(Blacklight::SearchState.new(params_to_merge, blacklight_config))
116119

117120
if block_given?
118121
yield my_params

spec/lib/blacklight/search_state_spec.rb

+63-29
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,61 @@
99
end
1010

1111
let(:parameter_class) { ActionController::Parameters }
12-
let(:helper) { described_class.new(params, blacklight_config) }
12+
let(:search_state) { described_class.new(params, blacklight_config) }
1313
let(:params) { parameter_class.new }
1414

15+
describe '#to_h' do
16+
let(:data) { { a: '1'} }
17+
let(:params) { parameter_class.new data }
18+
19+
it 'returns a copy of the original parameters' do
20+
expect(search_state.to_h).to eq data.with_indifferent_access
21+
expect(search_state.to_h.object_id).not_to eq params.object_id
22+
end
23+
24+
context 'with AC::Parameters' do
25+
let(:parameter_class) { ActionController::Parameters }
26+
27+
it 'returns the hash data' do
28+
expect(search_state.to_h).to eq data.with_indifferent_access
29+
end
30+
end
31+
32+
context 'with HashWithIndifferentAccess' do
33+
let(:parameter_class) { HashWithIndifferentAccess }
34+
35+
it 'returns the hash data' do
36+
expect(search_state.to_h).to eq data.with_indifferent_access
37+
end
38+
end
39+
40+
context 'with Hash' do
41+
let(:params) { data }
42+
43+
it 'returns the hash data' do
44+
expect(search_state.to_h).to eq data.with_indifferent_access
45+
end
46+
end
47+
end
48+
1549
describe "params_for_search" do
1650
let(:params) { parameter_class.new 'default' => 'params' }
1751

1852
it "takes original params" do
19-
result = helper.params_for_search
53+
result = search_state.params_for_search
2054
expect(result).to eq({ 'default' => 'params' })
2155
expect(params.object_id).to_not eq result.object_id
2256
end
2357

2458
it "accepts params to merge into the controller's params" do
25-
result = helper.params_for_search(q: 'query')
59+
result = search_state.params_for_search(q: 'query')
2660
expect(result).to eq('q' => 'query', 'default' => 'params')
2761
end
2862

2963
context "when params have blacklisted keys" do
3064
let(:params) { parameter_class.new action: 'action', controller: 'controller', id: "id", commit: 'commit' }
3165
it "removes them" do
32-
result = helper.params_for_search
66+
result = search_state.params_for_search
3367
expect(result.keys).to_not include(:action, :controller, :commit, :id)
3468
end
3569
end
@@ -38,31 +72,31 @@
3872
context "and per_page changed" do
3973
let(:params) { parameter_class.new per_page: 20, page: 5 }
4074
it "adjusts the current page" do
41-
result = helper.params_for_search(per_page: 100)
75+
result = search_state.params_for_search(per_page: 100)
4276
expect(result[:page]).to eq 1
4377
end
4478
end
4579

4680
context "and per_page didn't change" do
4781
let(:params) { parameter_class.new per_page: 20, page: 5 }
4882
it "doesn't change the current page" do
49-
result = helper.params_for_search(per_page: 20)
83+
result = search_state.params_for_search(per_page: 20)
5084
expect(result[:page]).to eq 5
5185
end
5286
end
5387

5488
context "and the sort changes" do
5589
let(:params) { parameter_class.new sort: 'field_a', page: 5 }
5690
it "adjusts the current page" do
57-
result = helper.params_for_search(sort: 'field_b')
91+
result = search_state.params_for_search(sort: 'field_b')
5892
expect(result[:page]).to eq 1
5993
end
6094
end
6195

6296
context "and the sort didn't change" do
6397
let(:params) { parameter_class.new sort: 'field_a', page: 5 }
6498
it "doesn't change the current page" do
65-
result = helper.params_for_search(sort: 'field_a')
99+
result = search_state.params_for_search(sort: 'field_a')
66100
expect(result[:page]).to eq 5
67101
end
68102
end
@@ -71,7 +105,7 @@
71105
context "with a block" do
72106
let(:params) { parameter_class.new a: 1, b: 2 }
73107
it "evalutes the block and allow it to add or remove keys" do
74-
result = helper.params_for_search(c: 3) do |params|
108+
result = search_state.params_for_search(c: 3) do |params|
75109
params.extract! :a, :b
76110
params[:d] = 'd'
77111
end
@@ -100,14 +134,14 @@
100134
context "when there are no pre-existing facets" do
101135
let(:params) { params_no_existing_facet }
102136
it "adds facet value" do
103-
result_params = helper.add_facet_params("facet_field", "facet_value")
137+
result_params = search_state.add_facet_params("facet_field", "facet_value")
104138
expect(result_params[:f]).to be_a Hash
105139
expect(result_params[:f]["facet_field"]).to be_a_kind_of(Array)
106140
expect(result_params[:f]["facet_field"]).to eq ["facet_value"]
107141
end
108142

109143
it "leaves non-facet params alone" do
110-
result_params = helper.add_facet_params("facet_field_2", "new_facet_value")
144+
result_params = search_state.add_facet_params("facet_field_2", "new_facet_value")
111145

112146
params.each_pair do |key, value|
113147
next if key == :f
@@ -116,9 +150,9 @@
116150
end
117151

118152
it "uses the facet's key in the url" do
119-
allow(helper).to receive(:facet_configuration_for_field).with('some_field').and_return(double(single: true, field: "a_solr_field", key: "some_key"))
153+
allow(search_state).to receive(:facet_configuration_for_field).with('some_field').and_return(double(single: true, field: "a_solr_field", key: "some_key"))
120154

121-
result_params = helper.add_facet_params('some_field', 'my_value')
155+
result_params = search_state.add_facet_params('some_field', 'my_value')
122156

123157
expect(result_params[:f]['some_key']).to have(1).item
124158
expect(result_params[:f]['some_key'].first).to eq 'my_value'
@@ -128,7 +162,7 @@
128162
context "when there are pre-existing facets" do
129163
let(:params) { params_existing_facets }
130164
it "adds a facet param to existing facet constraints" do
131-
result_params = helper.add_facet_params("facet_field_2", "new_facet_value")
165+
result_params = search_state.add_facet_params("facet_field_2", "new_facet_value")
132166

133167
expect(result_params[:f]).to be_a Hash
134168

@@ -143,7 +177,7 @@
143177
end
144178

145179
it "leaves non-facet params alone" do
146-
result_params = helper.add_facet_params("facet_field_2", "new_facet_value")
180+
result_params = search_state.add_facet_params("facet_field_2", "new_facet_value")
147181

148182
params.each_pair do |key, value|
149183
next if key == 'f'
@@ -155,29 +189,29 @@
155189
context "with a facet selected in the params" do
156190
let(:params) { parameter_class.new f: { 'single_value_facet_field' => 'other_value' } }
157191
it "replaces facets configured as single" do
158-
allow(helper).to receive(:facet_configuration_for_field).with('single_value_facet_field').and_return(double(single: true, key: "single_value_facet_field"))
159-
result_params = helper.add_facet_params('single_value_facet_field', 'my_value')
192+
allow(search_state).to receive(:facet_configuration_for_field).with('single_value_facet_field').and_return(double(single: true, key: "single_value_facet_field"))
193+
result_params = search_state.add_facet_params('single_value_facet_field', 'my_value')
160194

161195
expect(result_params[:f]['single_value_facet_field']).to have(1).item
162196
expect(result_params[:f]['single_value_facet_field'].first).to eq 'my_value'
163197
end
164198
end
165199

166200
it "accepts a FacetItem instead of a plain facet value" do
167-
result_params = helper.add_facet_params('facet_field_1', double(value: 123))
201+
result_params = search_state.add_facet_params('facet_field_1', double(value: 123))
168202

169203
expect(result_params[:f]['facet_field_1']).to include(123)
170204
end
171205

172206
it "defers to the field set on a FacetItem" do
173-
result_params = helper.add_facet_params('facet_field_1', double(:field => 'facet_field_2', :value => 123))
207+
result_params = search_state.add_facet_params('facet_field_1', double(:field => 'facet_field_2', :value => 123))
174208

175209
expect(result_params[:f]['facet_field_1']).to be_blank
176210
expect(result_params[:f]['facet_field_2']).to include(123)
177211
end
178212

179213
it "adds any extra fq parameters from the FacetItem" do
180-
result_params = helper.add_facet_params('facet_field_1', double(:value => 123, fq: { 'facet_field_2' => 'abc' }))
214+
result_params = search_state.add_facet_params('facet_field_1', double(:value => 123, fq: { 'facet_field_2' => 'abc' }))
181215

182216
expect(result_params[:f]['facet_field_1']).to include(123)
183217
expect(result_params[:f]['facet_field_2']).to include('abc')
@@ -197,7 +231,7 @@
197231
}
198232

199233
it "does not include request parameters used by the facet paginator" do
200-
params = helper.add_facet_params_and_redirect("facet_field_2", "facet_value")
234+
params = search_state.add_facet_params_and_redirect("facet_field_2", "facet_value")
201235

202236
bad_keys = Blacklight::Solr::FacetPaginator.request_keys.values + [:id]
203237
bad_keys.each do |paginator_key|
@@ -206,13 +240,13 @@
206240
end
207241

208242
it 'removes :page request key' do
209-
params = helper.add_facet_params_and_redirect("facet_field_2", "facet_value")
243+
params = search_state.add_facet_params_and_redirect("facet_field_2", "facet_value")
210244
expect(params).to_not have_key(:page)
211245
end
212246

213247
it "otherwise does the same thing as add_facet_params" do
214-
added_facet_params = helper.add_facet_params("facet_field_2", "facet_value")
215-
added_facet_params_from_facet_action = helper.add_facet_params_and_redirect("facet_field_2", "facet_value")
248+
added_facet_params = search_state.add_facet_params("facet_field_2", "facet_value")
249+
added_facet_params_from_facet_action = search_state.add_facet_params_and_redirect("facet_field_2", "facet_value")
216250

217251
expect(added_facet_params_from_facet_action).to eq added_facet_params.except(Blacklight::Solr::FacetPaginator.request_keys[:page], Blacklight::Solr::FacetPaginator.request_keys[:sort])
218252
end
@@ -225,21 +259,21 @@
225259
let(:facet_params) { { 'some_field' => ['some_value', 'another_value'] } }
226260

227261
it "removes the facet / value tuple from the query parameters" do
228-
params = helper.remove_facet_params('some_field', 'some_value')
262+
params = search_state.remove_facet_params('some_field', 'some_value')
229263
expect(params[:f]['some_field']).not_to include 'some_value'
230264
expect(params[:f]['some_field']).to include 'another_value'
231265
end
232266
end
233267

234268
context "when the facet has configuration" do
235269
before do
236-
allow(helper).to receive(:facet_configuration_for_field).with('some_field').and_return(
270+
allow(search_state).to receive(:facet_configuration_for_field).with('some_field').and_return(
237271
double(single: true, field: "a_solr_field", key: "some_key"))
238272
end
239273
let(:facet_params) { { 'some_key' => ['some_value', 'another_value'] } }
240274

241275
it "uses the facet's key configuration" do
242-
params = helper.remove_facet_params('some_field', 'some_value')
276+
params = search_state.remove_facet_params('some_field', 'some_value')
243277
expect(params[:f]['some_key']).not_to eq 'some_value'
244278
expect(params[:f]['some_key']).to include 'another_value'
245279
end
@@ -249,15 +283,15 @@
249283
facet_params['another_field'] = ['some_value']
250284
facet_params['some_field'] = ['some_value']
251285

252-
params = helper.remove_facet_params('some_field', 'some_value')
286+
params = search_state.remove_facet_params('some_field', 'some_value')
253287

254288
expect(params[:f]).not_to have_key 'some_field'
255289
end
256290

257291
it "removes the 'f' parameter entirely when no facets remain" do
258292
facet_params['some_field'] = ['some_value']
259293

260-
params = helper.remove_facet_params('some_field', 'some_value')
294+
params = search_state.remove_facet_params('some_field', 'some_value')
261295

262296
expect(params).not_to have_key :f
263297
end

0 commit comments

Comments
 (0)