intel 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b03f995035ea2892df23d4d49479c10d8e2e6fe5
4
- data.tar.gz: 1770eb2f64a96b5751fbafcfce6c87aab2f31225
3
+ metadata.gz: a6afd8d515e1b008debd378f41f709f6a9e59b20
4
+ data.tar.gz: e514f5ffc47f3e45bdb1ab72b68117d50201e981
5
5
  SHA512:
6
- metadata.gz: 8827a71c28cba3c68a2b76dea14573cd8f7420ee4239dc55f8cbc087943153315b2efe8be03b99c647250ed6677e8bcbb72119e0653561b1be92254f082ed9b2
7
- data.tar.gz: 08955ef22b11378624daffc0fec7291cd4778881d2e84daf68b43c9cb6fc793db4eff29ca9461a59869e6536cedd2b5c27e6e39b0c81f19c7ae4843992272d3b
6
+ metadata.gz: ba504e4d707d5bdd3aa542443bb3769418bf4e13aa5d1ddef9cc855f1aeca7e99faea8034c66c12a7f0ba4dd42d57d4aa3696a890408d3d71048c4af3ca2a151
7
+ data.tar.gz: ba7dae63eaa56c1380733f31acde069c9e1a84be927af85dd1109abb44b358c7c1e2aeccbb2823d1c8d6062e0c63fd8dbea92ffdfbce5c5c73efb0231cffc34c
data/README.md CHANGED
@@ -1,10 +1,16 @@
1
1
  # Intel
2
2
 
3
- Search analytics made easy
3
+ :monkey_face: Search analytics made easy
4
4
 
5
- - track searches and conversions
6
- - watch searches in real-time [coming soon]
7
- - view searches with low conversions or no results [coming soon]
5
+ [See it in action](http://intel-demo.herokuapp.com/)
6
+
7
+ - view searches in real-time
8
+ - track conversions week over week
9
+ - monitor the performance of top searches
10
+
11
+ :cupid: An amazing companion to [Searchkick](https://github.com/ankane/searchkick)
12
+
13
+ Works with Rails 3.1+ and any search engine, including Elasticsearch, Sphinx, and Solr
8
14
 
9
15
  ## Get Started
10
16
 
@@ -14,43 +20,136 @@ Add this line to your application’s Gemfile:
14
20
  gem "intel"
15
21
  ```
16
22
 
17
- Create a table to keep track of searches.
23
+ And run the generator. This creates a migration to store searches.
18
24
 
19
25
  ```sh
20
26
  rails generate intel:install
21
27
  rake db:migrate
22
28
  ```
23
29
 
24
- Use the `track` option to track searches.
30
+ Next, add the dashboard to your `config/routes.rb`.
31
+
32
+ ```ruby
33
+ mount Intel::Engine, at: "admin/intel"
34
+ ```
35
+
36
+ Be sure to protect the endpoint in production - see the [Authentication](#authentication) section for ways to do this.
37
+
38
+ ### Track Searches
39
+
40
+ Track searches by creating a record in the database.
41
+
42
+ ```ruby
43
+ Intel::Search.create(
44
+ search_type: "Item", # typically the model name
45
+ query: "apple",
46
+ results_count: 12
47
+ )
48
+ ```
49
+
50
+ With [Searchkick](https://github.com/ankane/searchkick), you can use the `track` option to do this automatically.
25
51
 
26
52
  ```ruby
27
53
  Item.search "apple", track: true
28
54
  ```
29
55
 
30
- Want to track more attributes? Just add them to the `searches` table with migrations and pass the values to the `track` option.
56
+ If you want to track more attributes, add them to the `intel_searches` table. Then, pass the values to the `track` option.
57
+
58
+ ```ruby
59
+ Item.search "apple", track: {user_id: 1, source: "web"}
60
+ ```
61
+
62
+ It’s that easy.
63
+
64
+ ### Track Conversions
65
+
66
+ Tracking conversions is super important.
67
+
68
+ First, define your conversion metric. This is specific to your application.
69
+
70
+ Next, when a user searches, keep track of the search id.
71
+
72
+ ```ruby
73
+ @items = Item.search "apple", track: true
74
+ @items.search.id # returns search id
75
+ ```
76
+
77
+ When a user converts, mark it.
31
78
 
32
79
  ```ruby
33
- Item.search "apple", track: {user_id: true, source: "web"}
80
+ search = Intel::Search.find params[:search_id]
81
+ search.converted_at = Time.now
82
+ search.save
34
83
  ```
35
84
 
36
- It’s that easy!
85
+ Better yet, record the result that converted.
37
86
 
38
- ## View the Data [coming soon]
87
+ ```ruby
88
+ item = Item.find params[:item_id]
89
+ search.convertable = item
90
+ search.save
91
+ ```
92
+
93
+ The item will appear in the live stream. Add the `intel_name` method to your model to change what is displayed.
94
+
95
+ ```ruby
96
+ class Item < ActiveRecord::Base
97
+ def intel_name
98
+ title # use the title method
99
+ end
100
+ end
101
+ ```
102
+
103
+ ### Authentication
104
+
105
+ Don’t forget to protect the dashboard in production.
106
+
107
+ #### Basic Authentication
108
+
109
+ Set the following variables in your environment or an initializer.
110
+
111
+ ```ruby
112
+ ENV["INTEL_USERNAME"] = "andrew"
113
+ ENV["INTEL_PASSWORD"] = "secret"
114
+ ```
39
115
 
40
- Add the dashboards to your `config/routes.rb`.
116
+ #### Devise
41
117
 
42
118
  ```ruby
43
- mount Intel::Engine => "searches"
119
+ authenticate :user, lambda{|user| user.admin? } do
120
+ mount Intel::Engine, at: "admin/intel"
121
+ end
44
122
  ```
45
123
 
46
- Be sure to protect the endpoint in production.
124
+ ### Customize
47
125
 
48
- [show example]
126
+ #### Time Zone
127
+
128
+ To change the time zone, create an initializer `config/initializers/intel.rb` with:
129
+
130
+ ```ruby
131
+ Intel.time_zone = "Pacific Time (US & Canada)" # defaults to Time.zone
132
+ ```
133
+
134
+ #### Top Searches
135
+
136
+ Change the number of top searches shown with:
137
+
138
+ ```ruby
139
+ Intel.top_searches = 500 # defaults to 100
140
+ ```
141
+
142
+ ## TODO
143
+
144
+ - customize views
145
+ - group similar queries
146
+ - track pagination, facets, sorting, etc
49
147
 
50
148
  ## Contributing
51
149
 
52
- 1. Fork it
53
- 2. Create your feature branch (`git checkout -b my-new-feature`)
54
- 3. Commit your changes (`git commit -am 'Add some feature'`)
55
- 4. Push to the branch (`git push origin my-new-feature`)
56
- 5. Create new Pull Request
150
+ Everyone is encouraged to help improve this project. Here are a few ways you can help:
151
+
152
+ - [Report bugs](https://github.com/ankane/intel/issues)
153
+ - Fix bugs and [submit pull requests](https://github.com/ankane/intel/pulls)
154
+ - Write, clarify, or fix documentation
155
+ - Suggest or add new feature
@@ -0,0 +1,72 @@
1
+ module Intel
2
+ class SearchesController < ActionController::Base
3
+ layout "intel/application"
4
+
5
+ http_basic_authenticate_with name: ENV["INTEL_USERNAME"], password: ENV["INTEL_PASSWORD"] if ENV["INTEL_PASSWORD"]
6
+
7
+ before_filter :set_time_zone
8
+ before_filter :set_search_types
9
+ before_filter :set_search_type, only: [:index, :overview]
10
+ before_filter :set_time_range, only: [:index, :overview]
11
+ before_filter :set_searches, only: [:index, :overview]
12
+
13
+ def index
14
+ if params[:sort] == "conversion_rate"
15
+ @searches.sort_by!{|s| [s["conversion_rate"].to_f, s["query"]] }
16
+ end
17
+ end
18
+
19
+ def overview
20
+ relation = Intel::Search.where(search_type: params[:search_type])
21
+ @searches_by_week = relation.group_by_week(:created_at, Time.zone, @time_range).count
22
+ @conversions_by_week = relation.where("converted_at is not null").group_by_week(:created_at, Time.zone, @time_range).count
23
+ @top_searches = @searches.first(5)
24
+ @bad_conversion_rate = @searches.sort_by{|s| [s["conversion_rate"].to_f, s["query"]] }.first(5).select{|s| s["conversion_rate"] < 50 }
25
+ @conversion_rate_by_week = {}
26
+ @searches_by_week.each do |week, searches_count|
27
+ @conversion_rate_by_week[week] = searches_count > 0 ? (100.0 * @conversions_by_week[week] / searches_count).round : 0
28
+ end
29
+ end
30
+
31
+ def stream
32
+ end
33
+
34
+ # suspiciously similar to bootstrap 3
35
+ COLORS = %w[5bc0de d9534f 5cb85c f0ad4e]
36
+
37
+ def recent
38
+ @searches = Intel::Search.order("created_at desc").limit(10)
39
+ @color = {}
40
+ @search_types.each_with_index do |search_type, i|
41
+ @color[search_type] = COLORS[i % COLORS.size]
42
+ end
43
+ render layout: false
44
+ end
45
+
46
+ protected
47
+
48
+ def set_search_types
49
+ @search_types = Intel::Search.uniq.pluck(:search_type).sort
50
+ end
51
+
52
+ def set_search_type
53
+ @search_type = params[:search_type].to_s
54
+ end
55
+
56
+ def set_time_zone
57
+ @time_zone = Intel.time_zone
58
+ end
59
+
60
+ def set_time_range
61
+ @time_range = 8.weeks.ago.in_time_zone(@time_zone).beginning_of_week(:sunday)..Time.now
62
+ end
63
+
64
+ def set_searches
65
+ @limit = params[:limit] || Intel.top_searches
66
+ @searches = Intel::Search.connection.select_all(Intel::Search.select("normalized_query, COUNT(*) as searches_count, COUNT(converted_at) as conversions_count, AVG(results_count) as avg_results_count").where(created_at: @time_range, search_type: @search_type).group("normalized_query").order("searches_count desc, normalized_query asc").limit(@limit).to_sql).to_a
67
+ @searches.each do |search|
68
+ search["conversion_rate"] = 100 * search["conversions_count"].to_i / search["searches_count"].to_f
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,27 @@
1
+ <h1>
2
+ <%= @search_type %> Searches
3
+ <small style="color: #999; font-weight: normal;">Top <%= @limit %></small>
4
+ </h1>
5
+
6
+ <table>
7
+ <thead>
8
+ <tr>
9
+ <th>Query</th>
10
+ <th class="num" style="width: 20%;"><%= link_to "Searches", params.except(:sort), class: ("active" if params[:sort] != "conversion_rate") %></th>
11
+ <th class="num" style="width: 20%;">Conversions</th>
12
+ <th class="num" style="width: 20%;"><%= link_to "%", params.merge(sort: "conversion_rate"), class: ("active" if params[:sort] == "conversion_rate") %></th>
13
+ <th class="num" style="width: 20%;">Avg Results</th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <% @searches.each do |search| %>
18
+ <tr>
19
+ <td><%= search["normalized_query"] %></td>
20
+ <td class="num"><%= search["searches_count"] %></td>
21
+ <td class="num"><%= search["conversions_count"] %></td>
22
+ <td class="num"><%= number_to_percentage search["conversion_rate"].to_f, precision: 0 %></td>
23
+ <td class="num"><%= search["avg_results_count"].to_f.round %></td>
24
+ </tr>
25
+ <% end %>
26
+ </tbody>
27
+ </table>
@@ -0,0 +1,48 @@
1
+ <h1><%= @search_type %> Overview</h1>
2
+
3
+ <div class="grid">
4
+ <div class="col-1-2">
5
+ <table>
6
+ <thead>
7
+ <tr>
8
+ <th>Top Searches</th>
9
+ <th class="num"><%= link_to "View all", intel.searches_path(search_type: params[:search_type]) %></th>
10
+ </tr>
11
+ </thead>
12
+ <tbody>
13
+ <% @top_searches.each do |row| %>
14
+ <tr>
15
+ <td><%= row["normalized_query"] %></td>
16
+ <td class="num"><%= row["searches_count"] %></td>
17
+ </tr>
18
+ <% end %>
19
+ </tbody>
20
+ </table>
21
+ </div>
22
+ <div class="col-1-2">
23
+ <table>
24
+ <thead>
25
+ <tr>
26
+ <th>Low Conversions</th>
27
+ <th class="num"><%= link_to "View all", intel.searches_path(search_type: params[:search_type], sort: "conversion_rate") %></th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <% @bad_conversion_rate.each do |row| %>
32
+ <tr>
33
+ <td><%= row["normalized_query"] %></td>
34
+ <td class="num"><%= number_to_percentage row["conversion_rate"], precision: 0 %></td>
35
+ </tr>
36
+ <% end %>
37
+ </tbody>
38
+ </table>
39
+ </div>
40
+ </div>
41
+
42
+ <h2>Conversion Rate</h2>
43
+
44
+ <%= line_chart @conversion_rate_by_week %>
45
+
46
+ <h2>Volume</h2>
47
+
48
+ <%= line_chart [{name: "Searches", data: @searches_by_week}, {name: "Conversions", data: @conversions_by_week}] %>
@@ -0,0 +1,20 @@
1
+ <% @searches.each do |search| %>
2
+ <tr>
3
+ <td style="width: 15%;">
4
+ <%= link_to search.search_type, intel.overview_searches_path(search_type: search.search_type), class: "type-link", style: "background-color: ##{@color[search.search_type]};" %>
5
+ </td>
6
+ <td><%= search.query %></td>
7
+ <td style="width: 35%;">
8
+ <% if search.converted_at %>
9
+ <span style="color: #5cb85c;">
10
+ <span style="font-weight: bold;">✓</span>
11
+ <%= search.convertable ? (search.convertable.respond_to?(:intel_name) ? search.convertable.intel_name : "#{search.convertable_type} #{search.convertable_id}") : "Converted" %>
12
+ </span>
13
+ <% end %>
14
+ </td>
15
+ <td style="width: 20%;" class="num">
16
+ <%= time_ago_in_words search.created_at %> ago
17
+ <div style="color: #999;"><%= pluralize search.results_count, "result" %></div>
18
+ </td>
19
+ </tr>
20
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <h1>Live Stream</h1>
2
+
3
+ <table id="stream"></table>
4
+
5
+ <script>
6
+ function fetchRecentSearches() {
7
+ $("#stream").load("<%= intel.searches_recent_path %>");
8
+ setTimeout(fetchRecentSearches, 5 * 1000);
9
+ }
10
+ $( function() {
11
+ fetchRecentSearches();
12
+ });
13
+ </script>
@@ -0,0 +1,291 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Intel</title>
5
+
6
+ <meta charset="utf-8" />
7
+
8
+ <style>
9
+ body {
10
+ font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
11
+ margin: 0;
12
+ padding: 20px;
13
+ font-size: 14px;
14
+ line-height: 1.4;
15
+ color: #333;
16
+ }
17
+
18
+ a, a:visited, a:active {
19
+ color: #428bca;
20
+ text-decoration: none;
21
+ }
22
+
23
+ a:hover {
24
+ text-decoration: underline;
25
+ }
26
+
27
+ table {
28
+ width: 100%;
29
+ border-collapse: collapse;
30
+ border-spacing: 0;
31
+ margin-bottom: 20px;
32
+ }
33
+
34
+ th {
35
+ text-align: left;
36
+ border-bottom: solid 2px #ddd;
37
+ }
38
+
39
+ h1 {
40
+ font-size: 20px;
41
+ }
42
+
43
+ h2 {
44
+ font-size: 16px;
45
+ }
46
+
47
+ ul {
48
+ list-style-type: none;
49
+ padding: 0;
50
+ }
51
+
52
+ table td, table th {
53
+ padding: 8px;
54
+ }
55
+
56
+ td {
57
+ border-top: solid 1px #ddd;
58
+ }
59
+
60
+ #brand {
61
+ font-size: 18px;
62
+ line-height: 20px;
63
+ font-weight: bold;
64
+ color: #999;
65
+ }
66
+
67
+ a.active {
68
+ color: #5cb85c;
69
+ }
70
+
71
+ a.type-link {
72
+ color: #fff;
73
+ padding: 8px;
74
+ border-radius: 4px;
75
+ }
76
+
77
+ a.type-link:hover {
78
+ text-decoration: none;
79
+ }
80
+
81
+ #header {
82
+ border-bottom: solid 1px #ddd;
83
+ padding-bottom: 20px;
84
+ }
85
+
86
+ .nav, .nav li {
87
+ display: inline;
88
+ }
89
+
90
+ .nav li {
91
+ margin-right: 20px;
92
+ }
93
+
94
+ #stream {
95
+ border-bottom: solid 1px #ddd;
96
+ }
97
+
98
+ .num {
99
+ text-align: right;
100
+ }
101
+
102
+ .container {
103
+ max-width: 800px;
104
+ margin-left: auto;
105
+ margin-right: auto;
106
+ }
107
+
108
+ /*
109
+ Simple Grid
110
+ Learn More - http://dallasbass.com/simple-grid-a-lightweight-responsive-css-grid/
111
+ Project Page - http://thisisdallas.github.com/Simple-Grid/
112
+ Author - Dallas Bass
113
+ Site - dallasbass.com
114
+ */
115
+
116
+ *, *:after, *:before {
117
+ -webkit-box-sizing: border-box;
118
+ -moz-box-sizing: border-box;
119
+ box-sizing: border-box;
120
+ }
121
+
122
+ body {
123
+ margin: 0px;
124
+ }
125
+
126
+ [class*='col-'] {
127
+ float: left;
128
+ padding-right: 20px;
129
+ }
130
+
131
+ [class*='col-']:last-of-type {
132
+ padding-right: 0px;
133
+ }
134
+
135
+ .grid {
136
+ width: 100%;
137
+
138
+ margin: 0 auto;
139
+ overflow: hidden;
140
+ }
141
+
142
+ .grid:after {
143
+ content: "";
144
+ display: table;
145
+ clear: both;
146
+ }
147
+
148
+ .grid-pad {
149
+ padding: 20px 0 0px 20px;
150
+ }
151
+
152
+ .grid-pad > [class*='col-']:last-of-type {
153
+ padding-right: 20px;
154
+ }
155
+
156
+ .push-right {
157
+ float: right;
158
+ }
159
+
160
+ /* Content Columns */
161
+
162
+ .col-1-1 {
163
+ width: 100%;
164
+ }
165
+ .col-2-3, .col-8-12 {
166
+ width: 66.66%;
167
+ }
168
+
169
+ .col-1-2, .col-6-12 {
170
+ width: 50%;
171
+ }
172
+
173
+ .col-1-3, .col-4-12 {
174
+ width: 33.33%;
175
+ }
176
+
177
+ .col-1-4, .col-3-12 {
178
+ width: 25%;
179
+ }
180
+
181
+ .col-1-5 {
182
+ width: 20%;
183
+ }
184
+
185
+ .col-1-6, .col-2-12 {
186
+ width: 16.667%;
187
+ }
188
+
189
+ .col-1-7 {
190
+ width: 14.28%;
191
+ }
192
+
193
+ .col-1-8 {
194
+ width: 12.5%;
195
+ }
196
+
197
+ .col-1-9 {
198
+ width: 11.1%;
199
+ }
200
+
201
+ .col-1-10 {
202
+ width: 10%;
203
+ }
204
+
205
+ .col-1-11 {
206
+ width: 9.09%;
207
+ }
208
+
209
+ .col-1-12 {
210
+ width: 8.33%
211
+ }
212
+
213
+ /* Layout Columns */
214
+
215
+ .col-11-12 {
216
+ width: 91.66%
217
+ }
218
+
219
+ .col-10-12 {
220
+ width: 83.333%;
221
+ }
222
+
223
+ .col-9-12 {
224
+ width: 75%;
225
+ }
226
+
227
+ .col-5-12 {
228
+ width: 41.66%;
229
+ }
230
+
231
+ .col-7-12 {
232
+ width: 58.33%
233
+ }
234
+
235
+ @media handheld, only screen and (max-width: 767px) {
236
+
237
+
238
+ .grid {
239
+ width: 100%;
240
+ min-width: 0;
241
+ margin-left: 0px;
242
+ margin-right: 0px;
243
+ padding-left: 0px;
244
+ padding-right: 0px;
245
+ }
246
+
247
+ [class*='col-'] {
248
+ width: auto;
249
+ float: none;
250
+ margin-left: 0px;
251
+ margin-right: 0px;
252
+ margin-top: 10px;
253
+ margin-bottom: 10px;
254
+ padding-right: 0px;
255
+ padding-left: 0px;
256
+ }
257
+ }
258
+ </style>
259
+
260
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
261
+ <%= javascript_include_tag "//www.google.com/jsapi", "chartkick" %>
262
+ </head>
263
+ <body>
264
+ <div class="container">
265
+ <% if !@skip_header %>
266
+ <div id="header">
267
+ <div class="grid">
268
+ <div class="col-1-2">
269
+ <ul class="nav">
270
+ <li id="brand">Intel</li>
271
+ <li><%= link_to "Live Stream", intel.root_path, class: ("active" if !@search_type) %></li>
272
+ <% @search_types.each do |search_type| %>
273
+ <li><%= link_to search_type, intel.overview_searches_path(search_type: search_type), class: ("active" if @search_type == search_type) %></li>
274
+ <% end %>
275
+ </ul>
276
+ </div>
277
+
278
+ <div class="col-1-2" style="text-align: right;">
279
+ <% if %w[overview index].include?(params[:action]) and @time_range %>
280
+ <%= @time_range.first.strftime("%b %-e, %Y") %> to <%= @time_range.last.strftime("%b %-e, %Y") %>
281
+ <span style="color: #999;"><%= @time_zone.name.sub(" (US & Canada)", "") %></span>
282
+ <% end %>
283
+ </div>
284
+ </div>
285
+ </div>
286
+ <% end %>
287
+
288
+ <%= yield %>
289
+ </div>
290
+ </body>
291
+ </html>
@@ -0,0 +1,7 @@
1
+ Intel::Engine.routes.draw do
2
+ resources :searches, only: [:index] do
3
+ get "overview", on: :collection
4
+ end
5
+ get "searches/recent"
6
+ root to: "searches#stream"
7
+ end
@@ -18,7 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "searchkick"
21
+ spec.add_dependency "chartkick"
22
+ spec.add_dependency "groupdate"
22
23
 
23
24
  spec.add_development_dependency "bundler", "~> 1.3"
24
25
  spec.add_development_dependency "rake"
@@ -1,10 +1,19 @@
1
1
  class <%= migration_class_name %> < ActiveRecord::Migration
2
2
  def change
3
- create_table :searches do |t|
4
- t.string :searchable_type
3
+ create_table :intel_searches do |t|
4
+ t.string :search_type
5
5
  t.string :query
6
+ t.string :normalized_query
6
7
  t.integer :results_count
7
8
  t.timestamp :created_at
9
+ t.integer :convertable_id
10
+ t.string :convertable_type
11
+ t.timestamp :converted_at
8
12
  end
13
+
14
+ add_index :intel_searches, [:created_at]
15
+ add_index :intel_searches, [:search_type, :created_at]
16
+ add_index :intel_searches, [:search_type, :normalized_query, :created_at], name: "index_intel_searches_on_search_type_and_normalized_query_and_cr" # autogenerated name is too long
17
+ add_index :intel_searches, [:convertable_id, :convertable_type]
9
18
  end
10
19
  end
@@ -1,14 +1,34 @@
1
- require "searchkick"
2
1
  require "intel/search"
3
2
  require "intel/track"
4
3
  require "intel/engine"
5
4
  require "intel/version"
6
5
 
7
- module Searchkick
8
- module Search
9
- include Intel::Track
6
+ require "chartkick"
7
+ require "groupdate"
10
8
 
11
- alias_method :search_without_track, :search
12
- alias_method :search, :search_with_track
9
+ module Intel
10
+ # time zone
11
+ mattr_reader :time_zone
12
+ def self.time_zone=(time_zone)
13
+ @@time_zone = time_zone.is_a?(String) ? ActiveSupport::TimeZone.new(time_zone) : time_zone
14
+ end
15
+
16
+ # top searches
17
+ mattr_accessor :top_searches
18
+ self.top_searches = 100
19
+ end
20
+
21
+ if defined?(Searchkick)
22
+ module Searchkick
23
+ module Search
24
+ include Intel::Track
25
+
26
+ alias_method :search_without_track, :search
27
+ alias_method :search, :search_with_track
28
+ end
29
+
30
+ class Results
31
+ attr_accessor :search
32
+ end
13
33
  end
14
34
  end
@@ -1,4 +1,5 @@
1
1
  module Intel
2
2
  class Engine < ::Rails::Engine
3
+ isolate_namespace Intel
3
4
  end
4
5
  end
@@ -1,4 +1,18 @@
1
1
  module Intel
2
2
  class Search < ActiveRecord::Base
3
+ belongs_to :convertable, polymorphic: true
4
+
5
+ before_save :set_normalized_query
6
+
7
+ def converted?
8
+ converted_at.present?
9
+ end
10
+
11
+ protected
12
+
13
+ def set_normalized_query
14
+ self.normalized_query = query.downcase if query
15
+ end
16
+
3
17
  end
4
18
  end
@@ -6,7 +6,7 @@ module Intel
6
6
 
7
7
  if options[:track]
8
8
  attributes = options[:track] == true ? {} : options[:track]
9
- Intel::Search.create({searchable_type: self.name, query: term, results_count: results.total_count}.merge(attributes))
9
+ results.search = Intel::Search.create({search_type: self.name, query: term, results_count: results.total_count}.merge(attributes))
10
10
  end
11
11
 
12
12
  results
@@ -1,3 +1,3 @@
1
1
  module Intel
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,17 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: intel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-24 00:00:00.000000000 Z
11
+ date: 2013-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: searchkick
14
+ name: chartkick
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: groupdate
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - '>='
@@ -64,6 +78,13 @@ files:
64
78
  - LICENSE.txt
65
79
  - README.md
66
80
  - Rakefile
81
+ - app/controllers/intel/searches_controller.rb
82
+ - app/views/intel/searches/index.html.erb
83
+ - app/views/intel/searches/overview.html.erb
84
+ - app/views/intel/searches/recent.html.erb
85
+ - app/views/intel/searches/stream.html.erb
86
+ - app/views/layouts/intel/application.html.erb
87
+ - config/routes.rb
67
88
  - intel.gemspec
68
89
  - lib/generators/intel/install_generator.rb
69
90
  - lib/generators/intel/templates/install.rb