mini-smart-box 0.0.1

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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/elasticsearch-rails-8.0.1/CHANGELOG.md +44 -0
  3. data/elasticsearch-rails-8.0.1/Gemfile +38 -0
  4. data/elasticsearch-rails-8.0.1/LICENSE.txt +202 -0
  5. data/elasticsearch-rails-8.0.1/README.md +149 -0
  6. data/elasticsearch-rails-8.0.1/Rakefile +67 -0
  7. data/elasticsearch-rails-8.0.1/elasticsearch-rails.gemspec +67 -0
  8. data/elasticsearch-rails-8.0.1/lib/elasticsearch/rails/instrumentation/controller_runtime.rb +58 -0
  9. data/elasticsearch-rails-8.0.1/lib/elasticsearch/rails/instrumentation/log_subscriber.rb +67 -0
  10. data/elasticsearch-rails-8.0.1/lib/elasticsearch/rails/instrumentation/publishers.rb +53 -0
  11. data/elasticsearch-rails-8.0.1/lib/elasticsearch/rails/instrumentation/railtie.rb +44 -0
  12. data/elasticsearch-rails-8.0.1/lib/elasticsearch/rails/instrumentation.rb +53 -0
  13. data/elasticsearch-rails-8.0.1/lib/elasticsearch/rails/lograge.rb +57 -0
  14. data/elasticsearch-rails-8.0.1/lib/elasticsearch/rails/tasks/import.rb +128 -0
  15. data/elasticsearch-rails-8.0.1/lib/elasticsearch/rails/version.rb +22 -0
  16. data/elasticsearch-rails-8.0.1/lib/elasticsearch/rails.rb +24 -0
  17. data/elasticsearch-rails-8.0.1/lib/rails/templates/01-basic.rb +364 -0
  18. data/elasticsearch-rails-8.0.1/lib/rails/templates/02-pretty.rb +348 -0
  19. data/elasticsearch-rails-8.0.1/lib/rails/templates/03-expert.rb +358 -0
  20. data/elasticsearch-rails-8.0.1/lib/rails/templates/04-dsl.rb +146 -0
  21. data/elasticsearch-rails-8.0.1/lib/rails/templates/05-settings-files.rb +88 -0
  22. data/elasticsearch-rails-8.0.1/lib/rails/templates/articles.yml.gz +0 -0
  23. data/elasticsearch-rails-8.0.1/lib/rails/templates/articles_settings.json +1 -0
  24. data/elasticsearch-rails-8.0.1/lib/rails/templates/index.html.dsl.erb +178 -0
  25. data/elasticsearch-rails-8.0.1/lib/rails/templates/index.html.erb +178 -0
  26. data/elasticsearch-rails-8.0.1/lib/rails/templates/indexer.rb +44 -0
  27. data/elasticsearch-rails-8.0.1/lib/rails/templates/search.css +76 -0
  28. data/elasticsearch-rails-8.0.1/lib/rails/templates/search_controller_test.dsl.rb +148 -0
  29. data/elasticsearch-rails-8.0.1/lib/rails/templates/search_controller_test.rb +148 -0
  30. data/elasticsearch-rails-8.0.1/lib/rails/templates/searchable.dsl.rb +234 -0
  31. data/elasticsearch-rails-8.0.1/lib/rails/templates/searchable.rb +224 -0
  32. data/elasticsearch-rails-8.0.1/lib/rails/templates/seeds.rb +75 -0
  33. data/elasticsearch-rails-8.0.1/spec/instrumentation/log_subscriber_spec.rb +57 -0
  34. data/elasticsearch-rails-8.0.1/spec/instrumentation_spec.rb +103 -0
  35. data/elasticsearch-rails-8.0.1/spec/lograge_spec.rb +52 -0
  36. data/elasticsearch-rails-8.0.1/spec/spec_helper.rb +65 -0
  37. data/mini-smart-box.gemspec +11 -0
  38. metadata +76 -0
@@ -0,0 +1,178 @@
1
+ <%#
2
+ # Licensed to Elasticsearch B.V. under one or more contributor
3
+ # license agreements. See the NOTICE file distributed with
4
+ # this work for additional information regarding copyright
5
+ # ownership. Elasticsearch B.V. licenses this file to you under
6
+ # the Apache License, Version 2.0 (the "License"); you may
7
+ # not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ %>
19
+ <div class="col-md-12">
20
+ <h1 class="text-right"><%= link_to 'Search New York Times articles', root_path %></h1>
21
+
22
+ <%= form_tag search_path, method: 'get', role: 'search' do %>
23
+ <div class="input-group">
24
+ <%= text_field_tag :q, params[:q], class: 'form-control', placeholder: 'Search...' %>
25
+
26
+ <span class="input-group-btn">
27
+ <button type="submit" class="btn btn-default">
28
+ <span class="glyphicon glyphicon-search"></span>
29
+ </button>
30
+ </span>
31
+ </div>
32
+
33
+ <div id="form-options" class="clearfix">
34
+ <div class="btn-group pull-left">
35
+ <label class="checkbox-inline">
36
+ <%= check_box_tag 'comments', 'y', params[:comments] == 'y', onclick: "$(this).closest('form').submit()" %>
37
+ Search in comments?
38
+ </label>
39
+ <% params.slice(:a, :c, :s).each do |name, value| %>
40
+ <%= hidden_field_tag name, value %>
41
+ <% end %>
42
+ </div>
43
+
44
+ <div class="btn-group pull-right">
45
+ <p style="float: left; margin: 0.1em 0 0 0"><small>Displaying <%= (params[:page] || 1).to_i.ordinalize %> page with <%= @articles.size %> articles
46
+ of <strong>total <%= @articles.total %></strong></small></p>
47
+
48
+ <button class="btn btn-default btn-xs dropdown-toggle" type="button" data-toggle="dropdown" style="margin-left: 0.5em">
49
+ <% sort = case
50
+ when params[:s] then params[:s]
51
+ when params[:q].blank? then 'published_on'
52
+ else 'relevancy'
53
+ end
54
+ %>
55
+ sorted by <%= sort.humanize.downcase %> <span class="caret"></span>
56
+ </button>
57
+ <ul class="dropdown-menu" role="menu">
58
+ <li><%= link_to "Sort by published on", search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(s: 'published_on')), class: 'btn-xs' %></li>
59
+ <li><%= link_to "Sort by relevancy", search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(s: nil)), class: 'btn-xs' unless params[:q].blank? %></li>
60
+ </ul>
61
+ </div>
62
+ </div>
63
+ <% end %>
64
+
65
+ <hr>
66
+ </div>
67
+
68
+ <% if @articles.size < 1 && @articles.response.suggestions.present? %>
69
+ <div class="col-md-12">
70
+ <p class="alert alert-warning">
71
+ No documents have been found.
72
+ <% if @articles.response.suggestions.terms.present? %>
73
+ Maybe you mean
74
+ <%= @articles.response.suggestions.terms.map do |term|
75
+ link_to term, search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge q: term)
76
+ end.to_sentence(last_word_connector: ' or ').html_safe %>?
77
+ <% end %>
78
+ </p>
79
+ </div>
80
+ <% end %>
81
+
82
+ <div id="facets" class="col-md-3">
83
+ <% unless @articles.size < 1 %>
84
+
85
+ <div class="categories panel panel-default">
86
+ <p class="panel-heading"><%= link_to 'All Sections &rarr;'.html_safe, search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(c: nil))%></p>
87
+
88
+ <div class="list-group">
89
+ <% @articles.response.response['aggregations']['categories']['categories']['buckets'].each do |c| %>
90
+ <%=
91
+ link_to search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(c: c['key'])),
92
+ class: "list-group-item#{' active' if params[:c] == c['key']}" do
93
+ c['key'].titleize.html_safe + content_tag(:small, c['doc_count'], class: 'badge').html_safe
94
+ end
95
+ %>
96
+ <% end %>
97
+ </div>
98
+ </div>
99
+
100
+ <div class="authors panel panel-default">
101
+ <p class="panel-heading"><%= link_to 'All Authors &rarr;'.html_safe, search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(a: nil))%></p>
102
+
103
+ <div class="list-group">
104
+ <% @articles.response.response['aggregations']['authors']['authors']['buckets'].each do |a| %>
105
+ <%=
106
+ link_to search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(a: a['key'])),
107
+ class: "list-group-item#{' active' if params[:a] == a['key']}" do
108
+ a['key'].titleize.html_safe + content_tag(:small, a['doc_count'], class: 'badge').html_safe
109
+ end
110
+ %>
111
+ <% end %>
112
+ </div>
113
+ </div>
114
+
115
+ <div class="authors panel panel-default">
116
+ <p class="panel-heading"><%= link_to 'Any Date &rarr;'.html_safe, search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(w: nil))%></p>
117
+
118
+ <div class="list-group">
119
+ <% @articles.response.response['aggregations']['published']['published']['buckets'].each do |w| %>
120
+ <%=
121
+ __start = Time.at(w['key']/1000)
122
+ __end = __start.end_of_week
123
+ __date = __start.to_date.to_s(:iso)
124
+
125
+ link_to search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(w: __date)),
126
+ class: "list-group-item#{' active' if params[:w] == __date}" do
127
+ "#{__start.to_date.to_s(:short)} &mdash; #{__end.to_date.to_s(:short)}".html_safe + \
128
+ content_tag(:small, w['doc_count'], class: 'badge').html_safe
129
+ end
130
+ %>
131
+ <% end %>
132
+ </div>
133
+ </div>
134
+ <% end %>
135
+ </div>
136
+
137
+ <div class="col-md-9">
138
+ <div id="results">
139
+ <% @articles.each do |article| %>
140
+ <div class="result">
141
+ <h3 class="title">
142
+ <%= (article.try(:highlight).try(:title) ? article.highlight.title.join.html_safe : article.title) %>
143
+ <small class="category"> | <%= article.categories.to_sentence %></small>
144
+ </h3>
145
+
146
+ <p class="body">
147
+ <% if article.try(:highlight).try(:abstract) %>
148
+ <%= article.highlight.abstract.join.html_safe %>
149
+ <% else %>
150
+ <%= article.try(:highlight).try(:content) ? article.highlight.content.join('&hellip;').html_safe : article.abstract %>
151
+ <% end %>
152
+ </p>
153
+
154
+ <% if comments = article.try(:highlight) && article.highlight['comments.body'] %>
155
+ <p class="comments">
156
+ Comments: <%= comments.join('&hellip;').html_safe %>
157
+ </p>
158
+ <% end %>
159
+
160
+ <p class="text-muted">
161
+ <small>Authors: <%= article.authors.map(&:full_name).to_sentence %></small> |
162
+ <small>Published: <%= article.published_on %></small> |
163
+ <small>Score: <%= article._score %></small>
164
+ </p>
165
+ </div>
166
+ <% end %>
167
+ </div>
168
+
169
+ <ul class="pager">
170
+ <li class="previous"><%= link_to_previous_page @articles, 'Previous Page', params: params.slice(:q, :c, :a, :comments) %></li>
171
+ <li class="next"><%= link_to_next_page @articles, 'Next Page', params: params.slice(:q, :c, :a, :comments) %></li>
172
+ </ul>
173
+
174
+ </div>
175
+
176
+ <div class="footer <%= @articles.size < 1 ? 'col-md-12' : 'col-md-9 col-md-offset-3' %>">
177
+ <p><small>Content provided by <a href="http://nytimes.com"><em>The New York Times</em></a>.</small></p>
178
+ </div>
@@ -0,0 +1,178 @@
1
+ <%#
2
+ # Licensed to Elasticsearch B.V. under one or more contributor
3
+ # license agreements. See the NOTICE file distributed with
4
+ # this work for additional information regarding copyright
5
+ # ownership. Elasticsearch B.V. licenses this file to you under
6
+ # the Apache License, Version 2.0 (the "License"); you may
7
+ # not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ %>
19
+ <div class="col-md-12">
20
+ <h1 class="text-right"><%= link_to 'Search New York Times articles', root_path %></h1>
21
+
22
+ <%= form_tag search_path, method: 'get', role: 'search' do %>
23
+ <div class="input-group">
24
+ <%= text_field_tag :q, params[:q], class: 'form-control', placeholder: 'Search...' %>
25
+
26
+ <span class="input-group-btn">
27
+ <button type="submit" class="btn btn-default">
28
+ <span class="glyphicon glyphicon-search"></span>
29
+ </button>
30
+ </span>
31
+ </div>
32
+
33
+ <div id="form-options" class="clearfix">
34
+ <div class="btn-group pull-left">
35
+ <label class="checkbox-inline">
36
+ <%= check_box_tag 'comments', 'y', params[:comments] == 'y', onclick: "$(this).closest('form').submit()" %>
37
+ Search in comments?
38
+ </label>
39
+ <% params.slice(:a, :c, :s).each do |name, value| %>
40
+ <%= hidden_field_tag name, value %>
41
+ <% end %>
42
+ </div>
43
+
44
+ <div class="btn-group pull-right">
45
+ <p style="float: left; margin: 0.1em 0 0 0"><small>Displaying <%= (params[:page] || 1).to_i.ordinalize %> page with <%= @articles.size %> articles
46
+ of <strong>total <%= @articles.total %></strong></small></p>
47
+
48
+ <button class="btn btn-default btn-xs dropdown-toggle" type="button" data-toggle="dropdown" style="margin-left: 0.5em">
49
+ <% sort = case
50
+ when params[:s] then params[:s]
51
+ when params[:q].blank? then 'published_on'
52
+ else 'relevancy'
53
+ end
54
+ %>
55
+ sorted by <%= sort.humanize.downcase %> <span class="caret"></span>
56
+ </button>
57
+ <ul class="dropdown-menu" role="menu">
58
+ <li><%= link_to "Sort by published on", search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(s: 'published_on')), class: 'btn-xs' %></li>
59
+ <li><%= link_to "Sort by relevancy", search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(s: nil)), class: 'btn-xs' unless params[:q].blank? %></li>
60
+ </ul>
61
+ </div>
62
+ </div>
63
+ <% end %>
64
+
65
+ <hr>
66
+ </div>
67
+
68
+ <% if @articles.size < 1 && @articles.response.suggestions.present? %>
69
+ <div class="col-md-12">
70
+ <p class="alert alert-warning">
71
+ No documents have been found.
72
+ <% if @articles.response.suggestions['suggest_title'].present? || @articles.response.suggestions['suggest_body'].present? %>
73
+ Maybe you mean
74
+ <%= @articles.response.suggestions.map { |k,v| v.first['options'] }.flatten.map {|v| v['text']}.uniq.map do |term|
75
+ link_to term, search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge q: term)
76
+ end.to_sentence(last_word_connector: ' or ').html_safe %>?
77
+ <% end %>
78
+ </p>
79
+ </div>
80
+ <% end %>
81
+
82
+ <div id="facets" class="col-md-3">
83
+ <% unless @articles.size < 1 %>
84
+
85
+ <div class="categories panel panel-default">
86
+ <p class="panel-heading"><%= link_to 'All Sections &rarr;'.html_safe, search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(c: nil))%></p>
87
+
88
+ <div class="list-group">
89
+ <% @articles.response.response['aggregations']['categories']['categories']['buckets'].each do |c| %>
90
+ <%=
91
+ link_to search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(c: c['key'])),
92
+ class: "list-group-item#{' active' if params[:c] == c['key']}" do
93
+ c['key'].titleize.html_safe + content_tag(:small, c['doc_count'], class: 'badge').html_safe
94
+ end
95
+ %>
96
+ <% end %>
97
+ </div>
98
+ </div>
99
+
100
+ <div class="authors panel panel-default">
101
+ <p class="panel-heading"><%= link_to 'All Authors &rarr;'.html_safe, search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(a: nil))%></p>
102
+
103
+ <div class="list-group">
104
+ <% @articles.response.response['aggregations']['authors']['authors']['buckets'].each do |a| %>
105
+ <%=
106
+ link_to search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(a: a['key'])),
107
+ class: "list-group-item#{' active' if params[:a] == a['key']}" do
108
+ a['key'].titleize.html_safe + content_tag(:small, a['doc_count'], class: 'badge').html_safe
109
+ end
110
+ %>
111
+ <% end %>
112
+ </div>
113
+ </div>
114
+
115
+ <div class="authors panel panel-default">
116
+ <p class="panel-heading"><%= link_to 'Any Date &rarr;'.html_safe, search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(w: nil))%></p>
117
+
118
+ <div class="list-group">
119
+ <% @articles.response.response['aggregations']['published']['published']['buckets'].each do |w| %>
120
+ <%=
121
+ __start = Time.at(w['key']/1000)
122
+ __end = __start.end_of_week
123
+ __date = __start.to_date.to_s(:iso)
124
+
125
+ link_to search_path(params.permit(:q, :a, :c, :s, :w, :comments).merge(w: __date)),
126
+ class: "list-group-item#{' active' if params[:w] == __date}" do
127
+ "#{__start.to_date.to_s(:short)} &mdash; #{__end.to_date.to_s(:short)}".html_safe + \
128
+ content_tag(:small, w['doc_count'], class: 'badge').html_safe
129
+ end
130
+ %>
131
+ <% end %>
132
+ </div>
133
+ </div>
134
+ <% end %>
135
+ </div>
136
+
137
+ <div class="col-md-9">
138
+ <div id="results">
139
+ <% @articles.each do |article| %>
140
+ <div class="result">
141
+ <h3 class="title">
142
+ <%= (article.try(:highlight).try(:title) ? article.highlight.title.join.html_safe : article.title) %>
143
+ <small class="category"> | <%= article.categories.to_sentence %></small>
144
+ </h3>
145
+
146
+ <p class="body">
147
+ <% if article.try(:highlight).try(:abstract) %>
148
+ <%= article.highlight.abstract.join.html_safe %>
149
+ <% else %>
150
+ <%= article.try(:highlight).try(:content) ? article.highlight.content.join('&hellip;').html_safe : article.abstract %>
151
+ <% end %>
152
+ </p>
153
+
154
+ <% if comments = article.try(:highlight) && article.highlight['comments.body'] %>
155
+ <p class="comments">
156
+ Comments: <%= comments.join('&hellip;').html_safe %>
157
+ </p>
158
+ <% end %>
159
+
160
+ <p class="text-muted">
161
+ <small>Authors: <%= article.authors.map(&:full_name).to_sentence %></small> |
162
+ <small>Published: <%= article.published_on %></small> |
163
+ <small>Score: <%= article._score %></small>
164
+ </p>
165
+ </div>
166
+ <% end %>
167
+ </div>
168
+
169
+ <ul class="pager">
170
+ <li class="previous"><%= link_to_previous_page @articles, 'Previous Page', params: params.slice(:q, :c, :a, :comments) %></li>
171
+ <li class="next"><%= link_to_next_page @articles, 'Next Page', params: params.slice(:q, :c, :a, :comments) %></li>
172
+ </ul>
173
+
174
+ </div>
175
+
176
+ <div class="footer <%= @articles.size < 1 ? 'col-md-12' : 'col-md-9 col-md-offset-3' %>">
177
+ <p><small>Content provided by <a href="http://nytimes.com"><em>The New York Times</em></a>.</small></p>
178
+ </div>
@@ -0,0 +1,44 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # Indexer class for <http://sidekiq.org>
19
+ #
20
+ # Run me with:
21
+ #
22
+ # $ bundle exec sidekiq --queue elasticsearch --verbose
23
+ #
24
+ class Indexer
25
+ include Sidekiq::Worker
26
+ sidekiq_options queue: 'elasticsearch', retry: false, backtrace: true
27
+
28
+ Logger = Sidekiq.logger.level == Logger::DEBUG ? Sidekiq.logger : nil
29
+ Client = Elasticsearch::Client.new host: (ENV['ELASTICSEARCH_URL'] || 'http://localhost:9200'), logger: Logger
30
+
31
+ def perform(operation, klass, record_id, options={})
32
+ logger.debug [operation, "#{klass}##{record_id} #{options.inspect}"]
33
+
34
+ case operation.to_s
35
+ when /index|update/
36
+ record = klass.constantize.find(record_id)
37
+ record.__elasticsearch__.client = Client
38
+ record.__elasticsearch__.__send__ "#{operation}_document"
39
+ when /delete/
40
+ Client.delete index: klass.constantize.index_name, id: record_id
41
+ else raise ArgumentError, "Unknown operation '#{operation}'"
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,76 @@
1
+ h1 {
2
+ font-size: 28px !important;
3
+ color: #a3a3a3 !important;
4
+ text-transform: uppercase;
5
+ letter-spacing: -2px;
6
+ }
7
+
8
+ .label-highlight {
9
+ background: #f6fbfc !important;
10
+ box-shadow: 0px 1px 0px rgba(0,0,0,0.15);
11
+ padding: 0.2em 0.4em 0.2em 0.4em !important;
12
+ }
13
+
14
+ h3 .label-highlight {
15
+ background: transparent !important;
16
+ padding: 0.1em 0.4em 0px 0.4em !important;
17
+ border-bottom: 1px solid #999;
18
+ box-shadow: 0px 2px 1px rgba(0,0,0,0.15);
19
+ border-radius: 0;
20
+ }
21
+
22
+ .comments .label-highlight {
23
+ background: #fcfdf0 !important;
24
+ }
25
+
26
+ small.badge {
27
+ font-size: 80% !important;
28
+ font-weight: normal !important;
29
+ display: inline-block;
30
+ float: right;
31
+ }
32
+
33
+ form #form-options {
34
+ color: #666;
35
+ font-size: 95%;
36
+ margin-top: 1.5em;
37
+ padding: 0 0.25em;
38
+ }
39
+ form #form-options input {
40
+ margin-top: 0.25em;
41
+ }
42
+
43
+ #facets .panel-heading {
44
+ margin-bottom: 0;
45
+ }
46
+
47
+ .result {
48
+ border-bottom: 1px solid #ccc;
49
+ margin: 2em 0 0 0;
50
+ padding: 0 0 1em 0;
51
+ }
52
+ .result:first-child {
53
+ margin-top: 0.25em;
54
+ }
55
+
56
+ .result h3.title {
57
+ font-size: 180% !important;
58
+ font-family: 'Rokkitt', sans-serif;
59
+ margin-top: 0;
60
+ }
61
+ .result h3.title small {
62
+ font-size: 75% !important;
63
+ }
64
+
65
+ .result .body {
66
+ font-family: Georgia, serif;
67
+ }
68
+
69
+ .result .category {
70
+ font-family: 'Rokkitt', sans-serif;
71
+ }
72
+
73
+ .result .comments {
74
+ color: #666666;
75
+ font-size: 80%;
76
+ }
@@ -0,0 +1,148 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ require 'test_helper'
19
+ require 'sidekiq/api'
20
+
21
+ class SearchControllerTest < ActionController::TestCase
22
+ setup do
23
+ travel_to Time.new(2015, 03, 16, 10, 00, 00, 0)
24
+
25
+ Article.delete_all
26
+
27
+ articles = [
28
+ { title: 'Article One', abstract: 'One', content: 'One', published_on: 1.day.ago, category_title: 'One', author_first_name: 'John', author_last_name: 'Smith' },
29
+ { title: 'Article One Another', abstract: '', content: '', published_on: 2.days.ago, category_title: 'One', author_first_name: 'John', author_last_name: 'Smith' },
30
+ { title: 'Article One Two', abstract: '', content: '', published_on: 10.days.ago, category_title: 'Two', author_first_name: 'Mary', author_last_name: 'Smith' },
31
+ { title: 'Article Two', abstract: '', content: '', published_on: 12.days.ago, category_title: 'Two', author_first_name: 'Mary', author_last_name: 'Smith' },
32
+ { title: 'Article Three', abstract: '', content: '', published_on: 12.days.ago, category_title: 'Three', author_first_name: 'Alice', author_last_name: 'Smith' }
33
+ ]
34
+
35
+ articles.each do |a|
36
+ article = Article.create! \
37
+ title: a[:title],
38
+ abstract: a[:abstract],
39
+ content: a[:content],
40
+ published_on: a[:published_on]
41
+
42
+ article.categories << Category.find_or_create_by!(title: a[:category_title])
43
+
44
+ article.authors << Author.find_or_create_by!(first_name: a[:author_first_name], last_name: a[:author_last_name])
45
+
46
+ article.save!
47
+ end
48
+
49
+ Article.find_by_title('Article Three').comments.create body: 'One'
50
+
51
+ Sidekiq::Queue.new("elasticsearch").clear
52
+
53
+ Article.__elasticsearch__.import force: true
54
+ Article.__elasticsearch__.refresh_index!
55
+ end
56
+
57
+ test "should return search results" do
58
+ get :index, params: { q: 'one' }
59
+ assert_response :success
60
+ assert_equal 3, assigns(:articles).size
61
+ end
62
+
63
+ test "should return search results in comments" do
64
+ get :index, params: { q: 'one', comments: 'y' }
65
+ assert_response :success
66
+ assert_equal 4, assigns(:articles).size
67
+ end
68
+
69
+ test "should return highlighted snippets" do
70
+ get :index, params: { q: 'one' }
71
+ assert_response :success
72
+ assert_match %r{<em class="label label-highlight">One</em>}, assigns(:articles).first.highlight.title.first
73
+ end
74
+
75
+ test "should return suggestions" do
76
+ get :index, params: { q: 'one' }
77
+ assert_response :success
78
+
79
+ suggestions = assigns(:articles).response.suggestions
80
+
81
+ assert_equal 'one', suggestions['suggest_title'][0]['text']
82
+ end
83
+
84
+ test "should return aggregations" do
85
+ get :index, params: { q: 'one' }
86
+ assert_response :success
87
+
88
+ aggregations = assigns(:articles).response.response['aggregations']
89
+
90
+ assert_equal 2, aggregations['categories']['categories']['buckets'].size
91
+ assert_equal 2, aggregations['authors']['authors']['buckets'].size
92
+ assert_equal 2, aggregations['published']['published']['buckets'].size
93
+
94
+ assert_equal 'John Smith', aggregations['authors']['authors']['buckets'][0]['key']
95
+ assert_equal 'One', aggregations['categories']['categories']['buckets'][0]['key']
96
+ assert_equal '2015-03-02T00:00:00.000Z', aggregations['published']['published']['buckets'][0]['key_as_string']
97
+ end
98
+
99
+ test "should sort on the published date" do
100
+ get :index, params: { q: 'one', s: 'published_on' }
101
+ assert_response :success
102
+
103
+ assert_equal 3, assigns(:articles).size
104
+ assert_equal '2015-03-15', assigns(:articles)[0].published_on
105
+ assert_equal '2015-03-14', assigns(:articles)[1].published_on
106
+ assert_equal '2015-03-06', assigns(:articles)[2].published_on
107
+ end
108
+
109
+ test "should sort on the published date when no query is provided" do
110
+ get :index, params: { q: '' }
111
+ assert_response :success
112
+
113
+ assert_equal 5, assigns(:articles).size
114
+ assert_equal '2015-03-15', assigns(:articles)[0].published_on
115
+ assert_equal '2015-03-14', assigns(:articles)[1].published_on
116
+ assert_equal '2015-03-06', assigns(:articles)[2].published_on
117
+ end
118
+
119
+ test "should filter search results and the author and published date facets when user selects a category" do
120
+ get :index, params: { q: 'one', c: 'One' }
121
+ assert_response :success
122
+
123
+ assert_equal 2, assigns(:articles).size
124
+
125
+ aggregations = assigns(:articles).response.response['aggregations']
126
+
127
+ assert_equal 1, aggregations['authors']['authors']['buckets'].size
128
+ assert_equal 1, aggregations['published']['published']['buckets'].size
129
+
130
+ # Do NOT filter the category facet
131
+ assert_equal 2, aggregations['categories']['categories']['buckets'].size
132
+ end
133
+
134
+ test "should filter search results and the category and published date facets when user selects a category" do
135
+ get :index, params: { q: 'one', a: 'Mary Smith' }
136
+ assert_response :success
137
+
138
+ assert_equal 1, assigns(:articles).size
139
+
140
+ aggregations = assigns(:articles).response.response['aggregations']
141
+
142
+ assert_equal 1, aggregations['categories']['categories']['buckets'].size
143
+ assert_equal 1, aggregations['published']['published']['buckets'].size
144
+
145
+ # Do NOT filter the authors facet
146
+ assert_equal 2, aggregations['authors']['authors']['buckets'].size
147
+ end
148
+ end