blacklight_advanced_search 5.3.1 → 6.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 +4 -4
- data/.travis.yml +3 -0
- data/README.md +1 -5
- data/VERSION +1 -1
- data/app/controllers/blacklight_advanced_search/advanced_controller.rb +7 -1
- data/app/views/advanced/_advanced_search_form.html.erb +2 -2
- data/app/views/advanced/_advanced_search_submit_btns.html.erb +3 -3
- data/app/views/advanced/index.html.erb +2 -2
- data/blacklight_advanced_search.gemspec +1 -1
- data/config/routes.rb +2 -2
- data/lib/blacklight_advanced_search.rb +34 -30
- data/lib/blacklight_advanced_search/advanced_search_builder.rb +27 -28
- data/lib/blacklight_advanced_search/controller.rb +1 -16
- data/lib/generators/blacklight_advanced_search/install_generator.rb +15 -3
- data/spec/lib/advanced_search_builder_spec.rb +0 -17
- data/spec/lib/deep_merge_spec.rb +31 -109
- metadata +13 -10
- data/lib/blacklight_advanced_search/parse_basic_q.rb +0 -73
- data/spec/parsing_nesting/parse_basic_q_spec.rb +0 -86
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2ca7a7c57ac86d4f3c0dc385ef79561af1c1737
|
4
|
+
data.tar.gz: ed73c2995b52f221b639d0840ee2caef4f90fbb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8dd353a79541d70fe0d026fb69d12c6957921c2805955533b2b0e181bd426a5ec0ce65f3e1feb06b7a1b9756a10ea364d1481f821127d0e91427ac187aad914
|
7
|
+
data.tar.gz: 17af4c42eb38f9649659c9667150c9a50a7bca920ce077fdaed12d90d7357be0ad3ca1aa0fd560dbd8c2ea695c340cef25d4ae9e2f342088dbb56afa484e4d7e
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -64,11 +64,7 @@ If your application uses a single Solr qt request handler for all its search fie
|
|
64
64
|
|
65
65
|
### Expression parsing in ordinary search
|
66
66
|
|
67
|
-
Turn this feature on by adding to your
|
68
|
-
|
69
|
-
self.search_params_logic << :add_advanced_parse_q_to_solr
|
70
|
-
|
71
|
-
And/or, if you've switched over to configuration in SearchBuilder, then to your ./app/models/search_builder.rb:
|
67
|
+
Turn this feature on by adding to your SearchBuilder definition:
|
72
68
|
|
73
69
|
self.default_processor_chain << :add_advanced_parse_q_to_solr
|
74
70
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
6.0.0
|
@@ -9,11 +9,17 @@ class BlacklightAdvancedSearch::AdvancedController < CatalogController
|
|
9
9
|
end
|
10
10
|
|
11
11
|
protected
|
12
|
+
|
13
|
+
# Override to use the engine routes
|
14
|
+
def search_action_url options = {}
|
15
|
+
blacklight_advanced_search_engine.url_for(options.merge(action: 'index'))
|
16
|
+
end
|
17
|
+
|
12
18
|
def get_advanced_search_facets
|
13
19
|
# We want to find the facets available for the current search, but:
|
14
20
|
# * IGNORING current query (add in facets_for_advanced_search_form filter)
|
15
21
|
# * IGNORING current advanced search facets (remove add_advanced_search_to_solr filter)
|
16
|
-
response, _ = search_results(params
|
22
|
+
response, _ = search_results(params) do |search_builder|
|
17
23
|
search_builder.except(:add_advanced_search_to_solr).append(:facets_for_advanced_search_form)
|
18
24
|
end
|
19
25
|
|
@@ -5,9 +5,9 @@
|
|
5
5
|
</div>
|
6
6
|
<% end %>
|
7
7
|
|
8
|
-
<%= form_tag
|
8
|
+
<%= form_tag search_catalog_path, :class => 'advanced form-horizontal', :method => :get do %>
|
9
9
|
|
10
|
-
<%= render_hash_as_hidden_fields(params_for_search(advanced_search_context
|
10
|
+
<%= render_hash_as_hidden_fields(search_state.params_for_search(advanced_search_context)) %>
|
11
11
|
|
12
12
|
<div class="input-criteria">
|
13
13
|
|
@@ -1,12 +1,12 @@
|
|
1
1
|
<div class="sort-buttons pull-left">
|
2
2
|
<%= label_tag(:sort, t('blacklight_advanced_search.form.sort_label'), :class => "control-label") %>
|
3
3
|
|
4
|
-
<%= select_tag(:sort, options_for_select(sort_fields, h(
|
4
|
+
<%= select_tag(:sort, options_for_select(sort_fields, h(current_sort_field && current_sort_field.key)), :class => "form-control sort-select") %>
|
5
5
|
<%= hidden_field_tag(:search_field, blacklight_config.advanced_search[:url_key]) %>
|
6
6
|
</div>
|
7
7
|
|
8
8
|
<div class="submit-buttons pull-right">
|
9
|
-
<%= link_to t('blacklight_advanced_search.form.start_over'), advanced_search_path, :class =>"btn btn-default advanced-search-start-over" %>
|
9
|
+
<%= link_to t('blacklight_advanced_search.form.start_over'), blacklight_advanced_search_engine.advanced_search_path, :class =>"btn btn-default advanced-search-start-over" %>
|
10
10
|
|
11
11
|
<%= submit_tag t('blacklight_advanced_search.form.search_btn'), :class=>'btn btn-primary advanced-search-submit', :id => "advanced-search-submit" %>
|
12
|
-
</div>
|
12
|
+
</div>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
<h1 class="advanced page-header">
|
6
6
|
<%= t('blacklight_advanced_search.form.title') %>
|
7
|
-
<%= link_to t('blacklight_advanced_search.form.start_over'), advanced_search_path, :class =>"btn btn-default pull-right advanced-search-start-over" %>
|
7
|
+
<%= link_to t('blacklight_advanced_search.form.start_over'), blacklight_advanced_search_engine.advanced_search_path, :class =>"btn btn-default pull-right advanced-search-start-over" %>
|
8
8
|
</h1>
|
9
9
|
|
10
10
|
<div class="row">
|
@@ -18,4 +18,4 @@
|
|
18
18
|
|
19
19
|
</div>
|
20
20
|
|
21
|
-
</div>
|
21
|
+
</div>
|
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
|
20
|
-
s.add_dependency
|
20
|
+
s.add_dependency 'blacklight', '> 6.0.0.pre', '< 7'
|
21
21
|
s.add_dependency "parslet"
|
22
22
|
|
23
23
|
s.add_development_dependency "rails"
|
data/config/routes.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
get 'advanced' => 'advanced#index', :
|
1
|
+
BlacklightAdvancedSearch::Engine.routes.draw do
|
2
|
+
get 'advanced' => 'advanced#index', as: 'advanced_search'
|
3
3
|
end
|
@@ -6,40 +6,44 @@ module BlacklightAdvancedSearch
|
|
6
6
|
autoload :QueryParser, 'blacklight_advanced_search/advanced_query_parser'
|
7
7
|
autoload :ParsingNestingParser, 'blacklight_advanced_search/parsing_nesting_parser'
|
8
8
|
autoload :FilterParser, 'blacklight_advanced_search/filter_parser'
|
9
|
-
autoload :ParseBasicQ, 'blacklight_advanced_search/parse_basic_q'
|
10
9
|
autoload :RedirectLegacyParamsFilter, 'blacklight_advanced_search/redirect_legacy_params_filter'
|
11
10
|
|
12
11
|
require 'blacklight_advanced_search/version'
|
13
12
|
require 'blacklight_advanced_search/engine'
|
14
|
-
|
15
|
-
# Utility method used in our solr search logic.
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# - WILL deduplicate values from arrays after merging them
|
21
|
-
#
|
22
|
-
# @param [Hash|HashWithIndifferentAccess] source_hash
|
23
|
-
# @param [Hash|HashWithIndifferentAccess] new_hash
|
24
|
-
# @return [Hash] the deeply merged hash
|
25
|
-
# @see Rails #deep_merge http://apidock.com/rails/v4.2.1/Hash/deep_merge
|
26
|
-
# @example new_hash = BlacklightAdvancedSearch.deep_merge(h1, h2)
|
27
|
-
def self.deep_merge(source_hash, new_hash)
|
28
|
-
source_hash.deep_merge(new_hash, &method(:merge_conflict_resolution))
|
29
|
-
end
|
30
|
-
|
31
|
-
# this one side-effects the first param
|
32
|
-
# @see #deep_merge
|
33
|
-
# @deprecated use `new_hash = BlacklightAdvancedSearch.deep_merge(h1, h2)` instead
|
13
|
+
|
14
|
+
# Utility method used in our solr search logic.
|
15
|
+
# Merges new_hash into source_hash, but will recursively
|
16
|
+
# merge nested arrays and hashes too; also will NOT merge nil
|
17
|
+
# or blank values from new_hash into source_hash, nil or blank values
|
18
|
+
# in new_hash will not overwrite values in source_hash.
|
34
19
|
def self.deep_merge!(source_hash, new_hash)
|
35
|
-
source_hash.
|
36
|
-
|
20
|
+
# We used to use built-in source_hash.merge() with a block arg
|
21
|
+
# to customize merge behavior, but that was breaking in some
|
22
|
+
# versions of BL/Rails where source_hash was a kind of HashWithIndifferentAccess,
|
23
|
+
# and hwia is unreliable in some versions of Rails. Oh well.
|
24
|
+
# https://github.com/projectblacklight/blacklight/issues/827
|
25
|
+
|
26
|
+
new_hash.each_pair do |key, new_value|
|
27
|
+
old = source_hash.fetch(key, nil)
|
37
28
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
29
|
+
source_hash[key] =
|
30
|
+
if new_value.respond_to?(:blank) && new.blank?
|
31
|
+
old
|
32
|
+
elsif (old.kind_of?(Hash) and new_value.kind_of?(Hash))
|
33
|
+
deep_merge!(old, new_value)
|
34
|
+
old
|
35
|
+
elsif (old.kind_of?(Array) and new_value.kind_of?(Array))
|
36
|
+
old.concat(new_value).uniq
|
37
|
+
elsif new_value.nil?
|
38
|
+
# Allowing nil values to over-write on merge messes things up.
|
39
|
+
# don't set a nil value if you really want to force blank, set
|
40
|
+
# empty string.
|
41
|
+
old
|
42
|
+
else
|
43
|
+
new_value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
source_hash
|
47
|
+
end
|
48
|
+
|
45
49
|
end
|
@@ -9,8 +9,8 @@ module BlacklightAdvancedSearch
|
|
9
9
|
(blacklight_params[:search_field] == self.blacklight_config.advanced_search[:url_key]) || blacklight_params[:f_inclusive]
|
10
10
|
end
|
11
11
|
|
12
|
-
# this method should get added into the
|
13
|
-
#
|
12
|
+
# this method should get added into the processor chain
|
13
|
+
# in a position AFTER normal query handling (:add_query_to_solr),
|
14
14
|
# so it'll overwrite that if and only if it's an advanced search.
|
15
15
|
# adds a 'q' and 'fq's based on advanced search form input.
|
16
16
|
def add_advanced_search_to_solr(solr_parameters)
|
@@ -35,14 +35,14 @@ module BlacklightAdvancedSearch
|
|
35
35
|
|
36
36
|
# Different versions of Parslet raise different exception classes,
|
37
37
|
# need to figure out which one exists to rescue
|
38
|
-
|
38
|
+
@@parslet_failed_exceptions = if defined? Parslet::UnconsumedInput
|
39
39
|
[Parslet::UnconsumedInput]
|
40
40
|
else
|
41
41
|
[Parslet::ParseFailed]
|
42
42
|
end
|
43
43
|
|
44
44
|
|
45
|
-
# This method can be included in
|
45
|
+
# This method can be included in the SearchBuilder to have us
|
46
46
|
# parse an ordinary entered :q for AND/OR/NOT and produce appropriate
|
47
47
|
# Solr query.
|
48
48
|
#
|
@@ -50,31 +50,30 @@ module BlacklightAdvancedSearch
|
|
50
50
|
# parse and send it straight to solr same as if advanced_parse_q
|
51
51
|
# were not being used.
|
52
52
|
def add_advanced_parse_q_to_solr(solr_parameters)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
begin
|
69
|
-
adv_search_params = ParsingNesting::Tree.parse(blacklight_params[:q], blacklight_config.advanced_search[:query_parser]).to_single_query_params(solr_local_params)
|
53
|
+
unless scope.params[:q].blank?
|
54
|
+
field_def = search_field_def_for_key( scope.params[:search_field]) ||
|
55
|
+
default_search_field
|
56
|
+
|
57
|
+
|
58
|
+
# If the individual field has advanced_parse_q suppressed, punt
|
59
|
+
return if field_def[:advanced_parse] == false
|
60
|
+
|
61
|
+
solr_direct_params = field_def[:solr_parameters] || {}
|
62
|
+
solr_local_params = field_def[:solr_local_parameters] || {}
|
63
|
+
|
64
|
+
# See if we can parse it, if we can't, we're going to give up
|
65
|
+
# and just allow basic search, perhaps with a warning.
|
66
|
+
begin
|
67
|
+
adv_search_params = ParsingNesting::Tree.parse(scope.params[:q], blacklight_config.advanced_search[:query_parser]).to_single_query_params( solr_local_params )
|
70
68
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
BlacklightAdvancedSearch.deep_merge!(solr_parameters, solr_direct_params)
|
70
|
+
BlacklightAdvancedSearch.deep_merge!(solr_parameters, adv_search_params)
|
71
|
+
rescue *@@parslet_failed_exceptions => e
|
72
|
+
# do nothing, don't merge our input in, keep basic search
|
73
|
+
# optional TODO, display error message in flash here, but hard to
|
74
|
+
# display a good one.
|
75
|
+
return
|
76
|
+
end
|
78
77
|
end
|
79
78
|
end
|
80
79
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'blacklight_advanced_search/parsing_nesting_parser'
|
2
2
|
|
3
3
|
# This module gets included into CatalogController, or another SearchHelper
|
4
|
-
# includer, to add
|
4
|
+
# includer, to add advanced search behavior
|
5
5
|
module BlacklightAdvancedSearch::Controller
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
@@ -13,21 +13,6 @@ module BlacklightAdvancedSearch::Controller
|
|
13
13
|
blacklight_config.advanced_search[:query_parser] ||= 'dismax'
|
14
14
|
blacklight_config.advanced_search[:form_solr_parameters] ||= {}
|
15
15
|
|
16
|
-
if respond_to? :search_params_logic
|
17
|
-
# Parse app URL params used for adv searches
|
18
|
-
self.search_params_logic += [:add_advanced_search_to_solr]
|
19
|
-
end
|
20
|
-
|
21
|
-
# Silence deprecations that occur when this code is executed before blacklight
|
22
|
-
# has generated a SearchBuilder.
|
23
|
-
Deprecation.silence Blacklight::Configuration do
|
24
|
-
unless blacklight_config.search_builder_class.include? BlacklightAdvancedSearch::AdvancedSearchBuilder
|
25
|
-
blacklight_config.search_builder_class.send(:include,
|
26
|
-
BlacklightAdvancedSearch::AdvancedSearchBuilder
|
27
|
-
)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
16
|
# Display advanced search constraints properly
|
32
17
|
helper BlacklightAdvancedSearch::RenderConstraintsOverride
|
33
18
|
helper BlacklightAdvancedSearch::CatalogHelperOverride
|
@@ -7,15 +7,27 @@ module BlacklightAdvancedSearch
|
|
7
7
|
def inject_asset_requires
|
8
8
|
generate "blacklight_advanced_search:assets"
|
9
9
|
end
|
10
|
-
|
11
|
-
|
10
|
+
|
11
|
+
def inject_search_builder
|
12
|
+
inject_into_file 'app/models/search_builder.rb', after: /include Blacklight::Solr::SearchBuilderBehavior.*$/ do
|
13
|
+
"\n include BlacklightAdvancedSearch::AdvancedSearchBuilder" \
|
14
|
+
"\n self.default_processor_chain += [:add_advanced_parse_q_to_solr, :add_advanced_search_to_solr]"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def inject_routes
|
19
|
+
inject_into_file 'config/routes.rb', after: /mount Blacklight::Engine.*$/ do
|
20
|
+
"\n mount BlacklightAdvancedSearch::Engine => '/'\n"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
12
24
|
def install_localized_search_form
|
13
25
|
if options[:force] or yes?("Install local search form with advanced link? (y/N)", :green)
|
14
26
|
# We're going to copy the search from from actual currently loaded
|
15
27
|
# Blacklight into local app as custom local override -- but add our link at the end too.
|
16
28
|
source_file = File.read(File.join(Blacklight.root, "app/views/catalog/_search_form.html.erb"))
|
17
29
|
|
18
|
-
new_file_contents = source_file + "\n\n<%= link_to 'More options', advanced_search_path(params.except(:controller, :action)), :
|
30
|
+
new_file_contents = source_file + "\n\n<%= link_to 'More options', blacklight_advanced_search_engine.advanced_search_path(params.except(:controller, :action)), class: 'advanced_search'%>"
|
19
31
|
|
20
32
|
create_file("app/views/catalog/_search_form.html.erb", new_file_contents)
|
21
33
|
end
|
@@ -49,23 +49,6 @@ describe BlacklightAdvancedSearch::AdvancedSearchBuilder do
|
|
49
49
|
obj.add_advanced_parse_q_to_solr(solr_params)
|
50
50
|
expect(solr_params[:q]).to eq(unparseable_q)
|
51
51
|
end
|
52
|
-
|
53
|
-
describe 'when parslet fails' do
|
54
|
-
let(:failing_q) { ")(" }
|
55
|
-
let(:params) { double("params", params: { :q => failing_q }) }
|
56
|
-
it 'does not return the query that could not be parsed' do
|
57
|
-
obj.add_advanced_parse_q_to_solr(solr_params)
|
58
|
-
expect(solr_params[:q]).to be_nil
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe 'when `q` is a hash' do
|
63
|
-
let(:params) { double("params", params: { q: { id: ['a'] } }) }
|
64
|
-
it 'does not return the query that could not be parsed' do
|
65
|
-
obj.add_advanced_parse_q_to_solr(solr_params)
|
66
|
-
expect(solr_params[:q]).to be_nil
|
67
|
-
end
|
68
|
-
end
|
69
52
|
end
|
70
53
|
|
71
54
|
context "when advanced_parse is false" do
|
data/spec/lib/deep_merge_spec.rb
CHANGED
@@ -1,123 +1,45 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
{
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
'array2' => [3, 4],
|
10
|
-
'hash1' => { 'a' => 'a', 'array' => [1], 'b' => 'b' },
|
11
|
-
'hash2' => { 'a2' => 'a2', 'array2' => [12], 'b2' => 'b2' }
|
3
|
+
describe "BlacklightAdvancedSearch#deep_merge!" do
|
4
|
+
before do
|
5
|
+
@ahash = {"a" => "a", "b" => "b",
|
6
|
+
"array1" => [1,2], "array2" => [3,4],
|
7
|
+
"hash1" => {"a" => "a", "array" => [1], "b" => "b"},
|
8
|
+
"hash2" => {"a2" => "a2", "array2" => [12], "b2" => "b2"}
|
12
9
|
}
|
13
|
-
end
|
14
|
-
let(:hash_Y) do
|
15
|
-
{
|
16
|
-
'a' => 'NEW A',
|
17
|
-
'c' => 'NEW C',
|
18
|
-
'array1' => [3, 4],
|
19
|
-
'hash1' => { 'array' => [2], 'b' => 'NEW B' }
|
20
|
-
}
|
21
|
-
end
|
22
|
-
let(:ahash) do
|
23
|
-
BlacklightAdvancedSearch.deep_merge(hash_x, hash_y)
|
24
|
-
end
|
25
|
-
|
26
|
-
RSpec.shared_examples 'Mergable Parameters' do # this name referenced below
|
27
|
-
it 'does not modify the param hashes' do
|
28
|
-
dup_x = hash_x.dup
|
29
|
-
dup_y = hash_y.dup
|
30
|
-
expect(ahash).not_to eq hash_x # this was the old behavior
|
31
|
-
expect(dup_x).to eq hash_x
|
32
|
-
expect(dup_y).to eq hash_y
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'leaves un-collided content alone' do
|
36
|
-
expect(ahash['b']).to eq('b')
|
37
|
-
expect(ahash['array2']).to eq([3, 4])
|
38
|
-
expect(ahash['hash2']).to eq('a2' => 'a2', 'array2' => [12], 'b2' => 'b2')
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'adds new content' do
|
42
|
-
expect(ahash['c']).to eq('NEW C')
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'merges a hash, recursive like' do
|
46
|
-
expect(ahash['hash1']).to eq('a' => 'a', 'array' => [1, 2], 'b' => 'NEW B')
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'merges boolean values (false)' do
|
50
|
-
expect(BlacklightAdvancedSearch.deep_merge({ a: false }, a: true)).to eq(a: true)
|
51
|
-
expect(BlacklightAdvancedSearch.deep_merge({ a: true }, a: false)).to eq(a: false)
|
52
|
-
end
|
53
10
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
expect(BlacklightAdvancedSearch.deep_merge({ a: 1 }, a: '')).to eq(a: 1)
|
64
|
-
expect(BlacklightAdvancedSearch.deep_merge({ a: nil }, a: '')).to eq(a: nil)
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'does not merge empty strings when the key is not yet present' do
|
68
|
-
expect(BlacklightAdvancedSearch.deep_merge({}, a: '')).to eq(a: '')
|
69
|
-
end
|
70
|
-
|
71
|
-
context 'Arrays' do
|
72
|
-
it 'merges an array' do
|
73
|
-
expect(ahash['array1']).to eq([1, 2, 3, 4])
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'collapse to uniq values when merging' do
|
77
|
-
expect(BlacklightAdvancedSearch.deep_merge({ a: [1, 1, 2, 1] }, a: [3, 2])).to eq(a: [1, 2, 3])
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'does not collapse to uniq values if not merging' do
|
81
|
-
expect(BlacklightAdvancedSearch.deep_merge({ a: [1, 1, 2, 1] }, a: [])).to eq(a: [1, 1, 2, 1])
|
82
|
-
end
|
83
|
-
end
|
11
|
+
BlacklightAdvancedSearch.deep_merge!(@ahash, {
|
12
|
+
"a" => "NEW A",
|
13
|
+
"array1" => [3, 4],
|
14
|
+
"hash1" => {
|
15
|
+
"array" => [2],
|
16
|
+
"b" => "NEW B"
|
17
|
+
},
|
18
|
+
"c" => "NEW C"
|
19
|
+
})
|
84
20
|
end
|
85
21
|
|
86
|
-
describe Hash do
|
87
|
-
it_behaves_like 'Mergable Parameters' do
|
88
|
-
let(:hash_x) { hash_X }
|
89
|
-
let(:hash_y) { hash_Y }
|
90
|
-
end
|
91
|
-
end
|
92
22
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
23
|
+
it "leaves un-collided content alone" do
|
24
|
+
expect(@ahash["b"]).to eq("b")
|
25
|
+
expect(@ahash["array2"]).to eq([3,4])
|
26
|
+
expect(@ahash["hash2"]).to eq({"a2" => "a2", "array2" => [12], "b2" => "b2"})
|
98
27
|
end
|
99
28
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
let(:hash_y) { hash_Y.with_indifferent_access }
|
104
|
-
end
|
29
|
+
it "adds new content" do
|
30
|
+
expect(@ahash["c"]).to eq("NEW C")
|
31
|
+
end
|
105
32
|
|
106
|
-
|
107
|
-
|
108
|
-
let(:hash_y) { hash_Y }
|
109
|
-
end
|
33
|
+
it "merges an array" do
|
34
|
+
expect(@ahash["array1"]).to eq([1,2,3,4])
|
110
35
|
end
|
111
36
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
expect(h1.deep_merge(h2)).to eq(merged)
|
119
|
-
expect(BlacklightAdvancedSearch.deep_merge(h1, h2)).to eq(merged)
|
120
|
-
end
|
37
|
+
it "merges a hash, recursive like" do
|
38
|
+
expect(@ahash["hash1"]).to eq({
|
39
|
+
"a" => "a",
|
40
|
+
"array" => [1,2],
|
41
|
+
"b" => "NEW B"
|
42
|
+
})
|
121
43
|
end
|
122
44
|
|
123
|
-
end
|
45
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blacklight_advanced_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Rochkind
|
@@ -9,22 +9,28 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-01-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: blacklight
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - "
|
18
|
+
- - ">"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 6.0.0.pre
|
21
|
+
- - "<"
|
19
22
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
23
|
+
version: '7'
|
21
24
|
type: :runtime
|
22
25
|
prerelease: false
|
23
26
|
version_requirements: !ruby/object:Gem::Requirement
|
24
27
|
requirements:
|
25
|
-
- - "
|
28
|
+
- - ">"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 6.0.0.pre
|
31
|
+
- - "<"
|
26
32
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
33
|
+
version: '7'
|
28
34
|
- !ruby/object:Gem::Dependency
|
29
35
|
name: parslet
|
30
36
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,7 +156,6 @@ files:
|
|
150
156
|
- lib/blacklight_advanced_search/controller.rb
|
151
157
|
- lib/blacklight_advanced_search/engine.rb
|
152
158
|
- lib/blacklight_advanced_search/filter_parser.rb
|
153
|
-
- lib/blacklight_advanced_search/parse_basic_q.rb
|
154
159
|
- lib/blacklight_advanced_search/parsing_nesting_parser.rb
|
155
160
|
- lib/blacklight_advanced_search/redirect_legacy_params_filter.rb
|
156
161
|
- lib/blacklight_advanced_search/render_constraints_override.rb
|
@@ -170,7 +175,6 @@ files:
|
|
170
175
|
- spec/lib/filter_parser_spec.rb
|
171
176
|
- spec/parsing_nesting/build_tree_spec.rb
|
172
177
|
- spec/parsing_nesting/consuming_spec.rb
|
173
|
-
- spec/parsing_nesting/parse_basic_q_spec.rb
|
174
178
|
- spec/parsing_nesting/to_solr_spec.rb
|
175
179
|
- spec/rcov.opts
|
176
180
|
- spec/spec.opts
|
@@ -196,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
200
|
version: '0'
|
197
201
|
requirements: []
|
198
202
|
rubyforge_project: blacklight
|
199
|
-
rubygems_version: 2.
|
203
|
+
rubygems_version: 2.4.5.1
|
200
204
|
signing_key:
|
201
205
|
specification_version: 4
|
202
206
|
summary: Blacklight Advanced Search plugin
|
@@ -209,7 +213,6 @@ test_files:
|
|
209
213
|
- spec/lib/filter_parser_spec.rb
|
210
214
|
- spec/parsing_nesting/build_tree_spec.rb
|
211
215
|
- spec/parsing_nesting/consuming_spec.rb
|
212
|
-
- spec/parsing_nesting/parse_basic_q_spec.rb
|
213
216
|
- spec/parsing_nesting/to_solr_spec.rb
|
214
217
|
- spec/rcov.opts
|
215
218
|
- spec/spec.opts
|
@@ -1,73 +0,0 @@
|
|
1
|
-
require 'parslet'
|
2
|
-
require 'parsing_nesting/tree'
|
3
|
-
|
4
|
-
# A solr search logic mix-in to CatalogController.
|
5
|
-
# If mixed-in, adds Advanced Search parsing behavior
|
6
|
-
# to queries entered on basic/standard/simple search
|
7
|
-
# form too, for boolean expressions.
|
8
|
-
#
|
9
|
-
# simply:
|
10
|
-
# include BlacklightAdvancedSearch::ParseBasicQ
|
11
|
-
# in your CatalogController
|
12
|
-
module BlacklightAdvancedSearch::ParseBasicQ
|
13
|
-
extend ActiveSupport::Concern
|
14
|
-
extend Deprecation
|
15
|
-
|
16
|
-
self.deprecation_horizon = 'blacklight_advanced_search 6.0'
|
17
|
-
|
18
|
-
include Blacklight::SearchFields
|
19
|
-
|
20
|
-
included do
|
21
|
-
self.search_params_logic += [:add_advanced_parse_q_to_solr]
|
22
|
-
end
|
23
|
-
|
24
|
-
# Different versions of Parslet raise different exception classes,
|
25
|
-
# need to figure out which one exists to rescue
|
26
|
-
PARSLET_FAILED_EXCEPTIONS = if defined? Parslet::UnconsumedInput
|
27
|
-
[Parslet::UnconsumedInput]
|
28
|
-
else
|
29
|
-
[Parslet::ParseFailed]
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
# This method can be included in search_params_logic to have us
|
34
|
-
# parse an ordinary entered :q for AND/OR/NOT and produce appropriate
|
35
|
-
# Solr query. Note that it is NOT included in search_params_logic
|
36
|
-
# by default when this module is included, because it is optional behavior.
|
37
|
-
# BlacklightAdvancedSearch init code will add it to CatalogController
|
38
|
-
# if it's configured to do so. You can of course add it yourself
|
39
|
-
# manually too.
|
40
|
-
#
|
41
|
-
# Note: For syntactically invalid input, we'll just skip the adv
|
42
|
-
# parse and send it straight to solr same as if advanced_parse_q
|
43
|
-
# were not being used.
|
44
|
-
def add_advanced_parse_q_to_solr(solr_parameters, req_params = params)
|
45
|
-
unless req_params[:q].blank?
|
46
|
-
field_def = search_field_def_for_key( req_params[:search_field]) ||
|
47
|
-
default_search_field
|
48
|
-
|
49
|
-
|
50
|
-
# If the individual field has advanced_parse_q suppressed, punt
|
51
|
-
return if field_def[:advanced_parse] == false
|
52
|
-
|
53
|
-
solr_direct_params = field_def[:solr_parameters] || {}
|
54
|
-
solr_local_params = field_def[:solr_local_parameters] || {}
|
55
|
-
|
56
|
-
# See if we can parse it, if we can't, we're going to give up
|
57
|
-
# and just allow basic search, perhaps with a warning.
|
58
|
-
begin
|
59
|
-
adv_search_params = ParsingNesting::Tree.parse(req_params[:q], blacklight_config.advanced_search[:query_parser]).to_single_query_params( solr_local_params )
|
60
|
-
|
61
|
-
BlacklightAdvancedSearch.deep_merge!(solr_parameters, solr_direct_params)
|
62
|
-
BlacklightAdvancedSearch.deep_merge!(solr_parameters, adv_search_params)
|
63
|
-
rescue *PARSLET_FAILED_EXCEPTIONS => e
|
64
|
-
# do nothing, don't merge our input in, keep basic search
|
65
|
-
# optional TODO, display error message in flash here, but hard to
|
66
|
-
# display a good one.
|
67
|
-
return
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
deprecation_deprecate add_advanced_parse_q_to_solr: "use AdvancedSearchBuilder.add_advanced_parse_q_to_solr"
|
72
|
-
|
73
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
|
3
|
-
describe "NestingParser" do
|
4
|
-
|
5
|
-
# Our ParseBasicQ mixin assumes a SolrHelper context.
|
6
|
-
# SolrHelper is a controller layer mixin, which depends
|
7
|
-
# on being mixed into a class which has #params (from Rails)
|
8
|
-
# and #blacklight_config
|
9
|
-
#
|
10
|
-
# This technique of testing is copied from Blacklight solr_helper_spec.rb
|
11
|
-
#
|
12
|
-
# It gets kind of a mess of dependencies, sorry.
|
13
|
-
class ParseBasicQTestClass
|
14
|
-
cattr_accessor :blacklight_config
|
15
|
-
|
16
|
-
include Blacklight::SearchHelper
|
17
|
-
|
18
|
-
include BlacklightAdvancedSearch::ParseBasicQ
|
19
|
-
|
20
|
-
|
21
|
-
def initialize blacklight_config
|
22
|
-
self.blacklight_config = blacklight_config
|
23
|
-
end
|
24
|
-
|
25
|
-
def params
|
26
|
-
{}
|
27
|
-
end
|
28
|
-
|
29
|
-
def logger
|
30
|
-
Rails.logger
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "basic functionality" do
|
35
|
-
before do
|
36
|
-
@blacklight_config = Blacklight::Configuration.new do |config|
|
37
|
-
config.advanced_search = {
|
38
|
-
|
39
|
-
}
|
40
|
-
|
41
|
-
config.add_search_field "all_fields" do |field|
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
config.add_search_field "special_field" do |field|
|
46
|
-
field.advanced_parse = false
|
47
|
-
end
|
48
|
-
end
|
49
|
-
@obj = ParseBasicQTestClass.new @blacklight_config
|
50
|
-
end
|
51
|
-
|
52
|
-
it "catches a simple example" do
|
53
|
-
expect(Deprecation).to receive(:warn)
|
54
|
-
solr_params = {}
|
55
|
-
@obj.add_advanced_parse_q_to_solr(solr_params, :q => "one two AND three OR four")
|
56
|
-
|
57
|
-
expect(solr_params[:defType]).to eq("lucene")
|
58
|
-
# We're not testing succesful parsing here, just that it's doing
|
59
|
-
# something that looks like we expect with subqueries.
|
60
|
-
expect(solr_params[:q]).to start_with("_query_:")
|
61
|
-
end
|
62
|
-
|
63
|
-
it "passes through an unparseable example" do
|
64
|
-
expect(Deprecation).to receive(:warn)
|
65
|
-
solr_params = {}
|
66
|
-
unparseable_q = "foo bar\'s AND"
|
67
|
-
@obj.add_advanced_parse_q_to_solr(solr_params, :q => unparseable_q)
|
68
|
-
|
69
|
-
expect(solr_params[:q]).to eq(unparseable_q)
|
70
|
-
end
|
71
|
-
|
72
|
-
it "ignores field with advanced_parse=false" do
|
73
|
-
expect(Deprecation).to receive(:warn)
|
74
|
-
solr_params = {}
|
75
|
-
original_q = "one two AND three OR four"
|
76
|
-
@obj.add_advanced_parse_q_to_solr(solr_params,
|
77
|
-
:search_field => "special_field",
|
78
|
-
:q => original_q
|
79
|
-
)
|
80
|
-
|
81
|
-
expect(solr_params).not_to have_key(:q)
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|