intel 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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