effective_search 0.7.0 → 0.8.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/app/controllers/effective/search_controller.rb +13 -7
- data/app/helpers/effective_search_helper.rb +32 -0
- data/app/models/concerns/effective_search_search.rb +20 -6
- data/app/views/effective/search/_search.html.haml +4 -6
- data/db/migrate/102_upgrade_effective_search_zero_eight.rb +38 -0
- data/lib/effective_search/action_text_search_index.rb +33 -0
- data/lib/effective_search/engine.rb +6 -0
- data/lib/effective_search/version.rb +1 -1
- data/lib/effective_search.rb +1 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 83d826d688fa3d81c054904cb345337677d2be1ba45d16114c774be17c4d7034
|
|
4
|
+
data.tar.gz: 51895c70ac58d0d5972e44e0cd97491924b8f537cbb32320ffec60705f3fc7cb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2c5a18018ad7a3501a00316107ddfb27d5d518081021e927b2a853ccc7cac7091f09b7401981284c2deb054e1131a2ab4e91e8a93a1085f14b1c9217ebbfa737
|
|
7
|
+
data.tar.gz: b4257f2cd361ba2a71d78966ec7cb779bfbcd2f24d7d599f9f42a47aff406df2dea3c63d2757538c7016a3d7a3b4f7e2b04c280fa44b59ff54779a0a046afef1
|
|
@@ -14,15 +14,21 @@ module Effective
|
|
|
14
14
|
@search.search!
|
|
15
15
|
|
|
16
16
|
if @search.present?
|
|
17
|
-
@
|
|
17
|
+
@search_page = EffectiveResources.normalize_page(params[:page])
|
|
18
|
+
raise ActiveRecord::RecordNotFound, "Page #{params[:page].inspect} is invalid" unless @search_page
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
results = @search.results(page: @search_page)
|
|
21
|
+
.limit(@search.per_page + 1)
|
|
22
|
+
.with_pg_search_highlight
|
|
23
|
+
.load
|
|
24
|
+
.to_a
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
raise ActiveRecord::RecordNotFound, "Page #{@search_page} does not exist" if @search_page > 1 && results.empty?
|
|
27
|
+
|
|
28
|
+
@search_has_next_page = (results.length > @search.per_page)
|
|
29
|
+
@search_results = results.first(@search.per_page)
|
|
30
|
+
|
|
31
|
+
@page_title = "Search results for ‘#{@search}’"
|
|
26
32
|
else
|
|
27
33
|
@page_title = "Search"
|
|
28
34
|
end
|
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
module EffectiveSearchHelper
|
|
2
2
|
|
|
3
|
+
def effective_search_paginate(page:, has_next_page:, url: nil)
|
|
4
|
+
return unless page > 1 || has_next_page
|
|
5
|
+
|
|
6
|
+
uri = URI(url || request.fullpath)
|
|
7
|
+
query = Rack::Utils.parse_nested_query(uri.query)
|
|
8
|
+
path = uri.path + '?'
|
|
9
|
+
|
|
10
|
+
previous = content_tag(:li, class: ['page-item', ('disabled' if page <= 1)].compact.join(' ')) do
|
|
11
|
+
if page > 1
|
|
12
|
+
link_to('Previous', path + query.merge('page' => page - 1).to_query,
|
|
13
|
+
class: 'page-link', 'aria-label': 'Previous', title: 'Previous', rel: 'prev'
|
|
14
|
+
)
|
|
15
|
+
else
|
|
16
|
+
content_tag(:span, 'Previous', class: 'page-link', 'aria-disabled': 'true')
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
following = content_tag(:li, class: ['page-item', ('disabled' unless has_next_page)].compact.join(' ')) do
|
|
21
|
+
if has_next_page
|
|
22
|
+
link_to('Next', path + query.merge('page' => page + 1).to_query,
|
|
23
|
+
class: 'page-link', 'aria-label': 'Next', title: 'Next', rel: 'next'
|
|
24
|
+
)
|
|
25
|
+
else
|
|
26
|
+
content_tag(:span, 'Next', class: 'page-link', 'aria-disabled': 'true')
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
content_tag(:nav, class: 'd-flex justify-content-center', 'aria-label': 'Search results pages') do
|
|
31
|
+
content_tag(:ul, safe_join([previous, following]), class: 'pagination')
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
3
35
|
def effective_search_nav_item
|
|
4
36
|
if EffectiveResources.authorized?(self, :index, EffectiveSearch.Search)
|
|
5
37
|
render('effective/search/form_nav_item')
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
module EffectiveSearchSearch
|
|
7
7
|
extend ActiveSupport::Concern
|
|
8
8
|
|
|
9
|
+
MAX_LENGTH = 200
|
|
10
|
+
|
|
9
11
|
module ClassMethods
|
|
10
12
|
def effective_search_search?; true; end
|
|
11
13
|
end
|
|
@@ -15,9 +17,22 @@ module EffectiveSearchSearch
|
|
|
15
17
|
|
|
16
18
|
attr_accessor :current_user
|
|
17
19
|
attr_accessor :view_context
|
|
18
|
-
|
|
19
20
|
attr_accessor :term
|
|
20
|
-
|
|
21
|
+
|
|
22
|
+
validate do
|
|
23
|
+
value = term.to_s
|
|
24
|
+
|
|
25
|
+
unless value.valid_encoding?
|
|
26
|
+
errors.add(:term, 'must use UTF-8 encoding')
|
|
27
|
+
next
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
next if value.blank?
|
|
31
|
+
|
|
32
|
+
errors.add(:term, 'contains an invalid null byte') if value.include?("\0")
|
|
33
|
+
errors.add(:term, :too_short, count: 3) if value.length < 3
|
|
34
|
+
errors.add(:term, :too_long, count: MAX_LENGTH) if value.length > MAX_LENGTH
|
|
35
|
+
end
|
|
21
36
|
end
|
|
22
37
|
|
|
23
38
|
def to_s
|
|
@@ -40,15 +55,14 @@ module EffectiveSearchSearch
|
|
|
40
55
|
end
|
|
41
56
|
|
|
42
57
|
def present?
|
|
43
|
-
term.present?
|
|
58
|
+
valid? && term.to_s.present?
|
|
44
59
|
end
|
|
45
60
|
|
|
46
61
|
# Search and assigns the collection
|
|
47
62
|
# Assigns the entire collection() if there are no search terms
|
|
48
63
|
# Otherwise validate the search terms
|
|
49
64
|
def search!
|
|
50
|
-
@search_results = build_collection()
|
|
51
|
-
@search_results = @search_results.none if present? && !valid?
|
|
65
|
+
@search_results = valid? ? build_collection() : PgSearch::Document.none
|
|
52
66
|
@search_results
|
|
53
67
|
end
|
|
54
68
|
|
|
@@ -120,7 +134,7 @@ module EffectiveSearchSearch
|
|
|
120
134
|
|
|
121
135
|
protected
|
|
122
136
|
|
|
123
|
-
# Returns an ActiveRecord collection of PgSearch::Document
|
|
137
|
+
# Returns an ActiveRecord collection of PgSearch::Document
|
|
124
138
|
def build_collection
|
|
125
139
|
raise('expected pg_search gem') unless defined?(PgSearch)
|
|
126
140
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
= render('effective/search/form', search: search)
|
|
3
3
|
|
|
4
4
|
- if search.present?
|
|
5
|
-
- results = search.results(page: @search_page)
|
|
6
5
|
- search_contents = search.search_contents.select { |resource| search.authorized?(resource) }
|
|
7
6
|
- permalinks = search.permalinks.select { |resource| search.authorized?(resource) }
|
|
8
7
|
|
|
@@ -20,12 +19,11 @@
|
|
|
20
19
|
|
|
21
20
|
-# Search results
|
|
22
21
|
%div{class: (permalinks.present? ? 'col-xl-8 col-lg-7' : 'col')}
|
|
23
|
-
- if
|
|
22
|
+
- if @search_results.empty?
|
|
24
23
|
.alert.alert-info There are no results for your search. Please try again.
|
|
25
24
|
|
|
26
|
-
- if
|
|
27
|
-
- collection =
|
|
25
|
+
- if @search_results.any?
|
|
26
|
+
- collection = @search_results.select { |result| search.authorized?(result) }
|
|
28
27
|
= render(collection: collection, partial: 'effective/search/result', locals: { search: search })
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
= bootstrap_paginate(results, per_page: search.per_page, collection_count: @search_count)
|
|
29
|
+
= effective_search_paginate(page: @search_page, has_next_page: @search_has_next_page)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
class UpgradeEffectiveSearchZeroEight < ActiveRecord::Migration[7.0]
|
|
2
|
+
disable_ddl_transaction!
|
|
3
|
+
|
|
4
|
+
def up
|
|
5
|
+
return unless connection.adapter_name == 'PostgreSQL'
|
|
6
|
+
|
|
7
|
+
unless column_exists?(:pg_search_documents, :search_vector)
|
|
8
|
+
execute(<<~SQL.squish)
|
|
9
|
+
ALTER TABLE pg_search_documents
|
|
10
|
+
ADD COLUMN search_vector tsvector
|
|
11
|
+
GENERATED ALWAYS AS (
|
|
12
|
+
to_tsvector('simple'::regconfig, coalesce(content, ''::text))
|
|
13
|
+
) STORED
|
|
14
|
+
SQL
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
add_index(
|
|
18
|
+
:pg_search_documents,
|
|
19
|
+
:search_vector,
|
|
20
|
+
using: :gin,
|
|
21
|
+
algorithm: :concurrently,
|
|
22
|
+
if_not_exists: true
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def down
|
|
27
|
+
return unless connection.adapter_name == 'PostgreSQL'
|
|
28
|
+
|
|
29
|
+
remove_index(
|
|
30
|
+
:pg_search_documents,
|
|
31
|
+
:search_vector,
|
|
32
|
+
algorithm: :concurrently,
|
|
33
|
+
if_exists: true
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
remove_column(:pg_search_documents, :search_vector) if column_exists?(:pg_search_documents, :search_vector)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EffectiveSearch
|
|
4
|
+
module ActionTextSearchIndex
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
after_commit :refresh_pg_search_document, on: [:create, :update, :destroy]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def refresh_pg_search_document
|
|
14
|
+
searchable = record
|
|
15
|
+
return unless searchable&.persisted?
|
|
16
|
+
return unless searchable.respond_to?(:update_pg_search_document)
|
|
17
|
+
|
|
18
|
+
options = searchable.class.try(:pg_search_multisearchable_options)
|
|
19
|
+
return unless Array(options.try(:[], :against)).map(&:to_s).include?(name.to_s)
|
|
20
|
+
return if persisted? && previous_changes.exclude?('body')
|
|
21
|
+
|
|
22
|
+
association_name = "rich_text_#{name}"
|
|
23
|
+
|
|
24
|
+
if searchable.class.reflect_on_association(association_name)
|
|
25
|
+
searchable.association(association_name).reset
|
|
26
|
+
elsif searchable.class.reflect_on_association(:rich_texts)
|
|
27
|
+
searchable.association(:rich_texts).reset
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
searchable.update_pg_search_document
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -7,5 +7,11 @@ module EffectiveSearch
|
|
|
7
7
|
eval File.read("#{config.root}/config/effective_search.rb")
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
initializer 'effective_search.action_text' do
|
|
11
|
+
ActiveSupport.on_load(:action_text_rich_text) do
|
|
12
|
+
include EffectiveSearch::ActionTextSearchIndex
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
10
16
|
end
|
|
11
17
|
end
|
data/lib/effective_search.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: effective_search
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Code and Effect
|
|
@@ -57,14 +57,14 @@ dependencies:
|
|
|
57
57
|
requirements:
|
|
58
58
|
- - ">="
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version:
|
|
60
|
+
version: 2.42.0
|
|
61
61
|
type: :runtime
|
|
62
62
|
prerelease: false
|
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
65
|
- - ">="
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version:
|
|
67
|
+
version: 2.42.0
|
|
68
68
|
- !ruby/object:Gem::Dependency
|
|
69
69
|
name: sqlite3
|
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -229,8 +229,10 @@ files:
|
|
|
229
229
|
- config/effective_search.rb
|
|
230
230
|
- config/routes.rb
|
|
231
231
|
- db/migrate/101_create_effective_search.rb
|
|
232
|
+
- db/migrate/102_upgrade_effective_search_zero_eight.rb
|
|
232
233
|
- db/seeds.rb
|
|
233
234
|
- lib/effective_search.rb
|
|
235
|
+
- lib/effective_search/action_text_search_index.rb
|
|
234
236
|
- lib/effective_search/engine.rb
|
|
235
237
|
- lib/effective_search/version.rb
|
|
236
238
|
- lib/generators/effective_search/install_generator.rb
|