browsing_history 0.0.3 → 0.0.4

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: 44240900447de64eee1d917a42c10dc18b72fe26
4
- data.tar.gz: 3c110cb5e9e00d6e7904bcf8083296297bf0dd2a
3
+ metadata.gz: 9c6749dcc724b60d799405589828bc3d4127426a
4
+ data.tar.gz: 8693a8ab2b98f9507ea1766598c9b66532ef89bd
5
5
  SHA512:
6
- metadata.gz: 2bf2adee9b2b6a105b181e70786952ce483696491b654aad786b594dc8cb453d45b2c16e75ac60b8e30fd6458efb227b8a63dc978b8d176527dec7c3d9f68c9a
7
- data.tar.gz: 890e06144a100e76889787f04834942fcedcc1f231da633e95121aadd8ed52d052c792e3ece8c4ace9bbc21be266108ce794d951c36b6b6de22e4ab3f839e248
6
+ metadata.gz: a12cc8849558b2f85e12efc27edcbeb4eaad0a0127a359b43539d6434d97cda45c4f7cb28e544c9b026fe8fd47289477ce947c50be014114ec424fb98188a2ee
7
+ data.tar.gz: a87326513214ca2cb178c2c23db8113b60e13fb957f695deaf9ae45c8e01cd6c66493a3c5e40d53378d64df59830f2550942a537c7cf45599090198a81b88096
data/README.md CHANGED
@@ -1,2 +1,258 @@
1
- # browsing_history
2
- Record browsing history by browser like users or something more simple and graceful.
1
+ # BrowsingHistory
2
+
3
+ BrowsingHistory is recording browsing history simply.
4
+ it backed by Redis.
5
+
6
+
7
+ ## Compatibility
8
+ The gem has been build and tested Rails 4.2 and Ruby 2.2.3
9
+
10
+
11
+ ## Usage
12
+ At first, you include 2 moudles.
13
+ ```
14
+ class User < ActiveRecord::Base
15
+ include BrowsingHistory::Browser
16
+ end
17
+
18
+ class Article < ActiveRecord::Base
19
+ include BrowsingHistory::Historizable
20
+ end
21
+ ```
22
+
23
+ Then, you can access `browsing_histories` method on a user instance to add a article to the user's browsing history.
24
+ ```
25
+ # create a article
26
+ article = Article.new(title: 'welcome to browsing_history')
27
+
28
+ # add the article to user's browsing history
29
+ user.browsing_histories << article
30
+
31
+ # access user's browsing histories of Article class
32
+ user.browsing_histories.recent(Article)
33
+ # => [#<Article id: 1, title: "welcome to browsing_history", created_at: "2016-04-29 10:13:15", updated_at: "2016-04-29 10:13:15">]
34
+ ```
35
+
36
+ For example,
37
+ if you want add a articls to browsing histoy when a user watch the article page,
38
+ you should add the method on article_controller#show.
39
+
40
+ ```
41
+ # app/controllers/articles_controller
42
+ # GET /articles/:id
43
+ def show
44
+ @user.browsing_histories << @article
45
+ end
46
+ ```
47
+
48
+
49
+ ## How it works
50
+ - recording historizable instances to browser's history on redis
51
+ - getting past historizable instances on browser's browsing history with like activerecord options(limit, between, at)
52
+ - clering browser's browsing history with like activerecord options(limit, between, at)
53
+ - recording above history on some kind of storages(redis, activerecord, mongoid...) by same interface and user creat own interface a storage.
54
+
55
+
56
+ ### Description Elements
57
+ There are 4 elements working on browsing_history.
58
+
59
+ - **BrowsingHistory::Browser(Module)**
60
+ It provide access methods to browsing_history for a browser class included it.
61
+ example: `User, Crawler`
62
+
63
+ - **BrowsingHistory::Historizable(Module)**
64
+ The class included it can be recorded on browsing_history
65
+ example: `Article, Review`
66
+
67
+ - **BrowsingHistory::History(class)**
68
+ It's class based on ActiveModel. It record historizable instance on browser's browsing_history
69
+ and exec some operations for them like add, where, count, clear.
70
+
71
+ - **BrowsingHistory::Storage(Module)**
72
+ It provide abstruct interface of some kind of storages like redis, activerecord, mongoid.
73
+ It is included BrowsingHistory::History and allow it to access above storages by same methods.
74
+
75
+ ### Storages
76
+ There is 1 storage interface
77
+ - **BrowsingHistory::Storages::Redis**
78
+ It's interface of redis for BrowsingHistory::Storage.
79
+ it depends on redis, redis-objects, redis-namespace.
80
+
81
+
82
+ ## Getting Started
83
+
84
+ ### 1. install gem
85
+ add a follow sentence to Gemfile
86
+
87
+ ```
88
+ # Gemfile
89
+ gem 'browsing_history'
90
+ ```
91
+
92
+ ### 2. Configure
93
+ if you want choose storage to save history or modify namespace which is key-prefix on redis,
94
+ add configuration to environments or your own config file.
95
+ but now, you can use :redis only as storage.
96
+ ```
97
+ # config/environments/{your environment} or create config/initializers/browsing_history.rb
98
+
99
+ # It's default configuration
100
+ BrowsingHistory.configure do |config|
101
+ config.storage_types = %i(redis active_record)
102
+ config.storage_type = :redis
103
+ config.namespace = 'browsing_history'
104
+ end
105
+ ```
106
+
107
+
108
+ ### 3. Include modules
109
+ you should include only 2 moudles.
110
+
111
+ ```
112
+ # example models
113
+ class User < ActiveRecord::Base
114
+ include BrowsingHistory::Browser
115
+ end
116
+
117
+ class Article < ActiveRecord::Base
118
+ include BrowsingHistory::Historizable
119
+ end
120
+ ```
121
+
122
+ ### 4. Access browsing history
123
+
124
+ #### BrowsingHistory::Browser#browsing_histories
125
+ you can access to browsing_history by browsing_histories method.
126
+ this method is provided BrowsingHistory::Browser and return BrowsingHistory::Browser::Assosiation
127
+
128
+ BrowsingHistory::Browser::Assosiation is provided following 4 methods.
129
+ 1. recent
130
+ 1. previous
131
+ 1. add
132
+ 1. count
133
+
134
+ and you can give following 2 argumetns for all of the methods.
135
+
136
+ - Target class included historizable or their instance you want to get from history like `Article, article, Review, review,w`
137
+
138
+ ```
139
+ # when browser is user, historizable is Articles
140
+ user = User.first
141
+ articles = user.browsing_histories.recent(Article)
142
+
143
+ # you can give instance instead of class, both return same result.
144
+ user = User.first
145
+ article = Article.first
146
+ articles = user.browsing_histories.recent(article)
147
+
148
+ # when you want mautipul historizable such as article and review
149
+ user = User.first
150
+ articles = user.browsing_histories.recent(article)
151
+ reviews = user.browsing_histories.recent(Review)
152
+ ```
153
+
154
+ - Range option like activerecord for instance `limit, between, at, all....`
155
+
156
+ ```
157
+ # when you want to get recent 20(default) articles on browsing_history
158
+ articles = user.browsing_histories.recent(Article)
159
+
160
+ # when you want to get recent 100 articles on browsing_history
161
+ articles_100 = user.browsing_histories.recent(Article, limit: 100)
162
+ ```
163
+
164
+ #### #### BrowsingHistory::Browser::Assosiation methods
165
+ ```
166
+ # recent
167
+ # get user's browsing histories in order form the new one
168
+ articles = user.browsing_histories.recent(Article)
169
+ articles_100 = user.browsing_histories.recent(Article, limit: 100)
170
+
171
+ # previous
172
+ # getting articles that user browsed between today to 1 day ago and in order form the new one
173
+ articles = user.browsing_histories.previous(Article, Time.zone.now..1.day.ago)
174
+
175
+ # add
176
+ # add the article to user's browsing history
177
+ user.browsing_histories << article
178
+
179
+ # count
180
+
181
+ # count user's browsing history
182
+ number_of_histories = user.browsing_histories.count(Article)
183
+ ```
184
+
185
+ #### BrowsingHistory::History
186
+ you can access browsing_history using also BrowsingHistory::History not only BrowsingHistory::Browser::Assosiation
187
+
188
+ BrowsingHistory::History is provided following 4 methods.
189
+ 1. create
190
+ 1. create!
191
+ 1. where
192
+ 1. clear
193
+ 1. count
194
+
195
+ it's based ActiveModel and its method format is similar ActiveRecord.
196
+ ```
197
+ user = User.create(name: 'browser')
198
+ article = Article.create(title: 'welcome to browsing_history')
199
+
200
+ # add the article to user's browsing_history
201
+ BrowsingHistories::History.create(browser: user, historizable: article)
202
+ ```
203
+
204
+ it is able to conbine some options to access browsing_history so more flexibly than BrowsingHistory::Browser::Assosiation.
205
+ ```
206
+ BrowsingHistories::History.where(
207
+ user: user,
208
+ historizable: review,
209
+ between: 1.day.ago..2.days.ago,
210
+ limit: 50
211
+ )
212
+ ```
213
+
214
+ #### BrowsingHistory::History methods
215
+
216
+ ```
217
+ user = User.first
218
+
219
+ # where
220
+ # get user's browsing histories in order form the new one ≒ user.browsing_history.recent
221
+ articls = BrowsingHistories::History.where(user: user, historizable: Article) # default all
222
+ articls_100 = BrowsingHistories::History.where(user: user, historizable: Article, limit: 100)
223
+
224
+ # get the article 5th from the newest
225
+ article = Article.find(100)
226
+ articls_5th = BrowsingHistories::History.where(user: user, historizable: Article, at: 5)
227
+
228
+ # getting articles that user browsed between 1 day ago to 2 days ago and in order form the new one ≒ user.browsing_history.previous
229
+ articles = BrowsingHistories::History.where(user: user, historizable: review, between: 1.day.ago..2.days.ago)
230
+
231
+ # conbining some options
232
+ # getting articles that user browsed between 1 day ago to 2 days ago and it's limit 50 in order from the new one
233
+ BrowsingHistories::History.where(
234
+ user: user,
235
+ historizable: review,
236
+ between: 1.day.ago..2.days.ago,
237
+ limit: 50
238
+ )
239
+
240
+ # count
241
+ # count user's browsing history ≒ user.browsing_history.count
242
+ articls = BrowsingHistories::History.count(user: user, historizable: Article)
243
+ number_of_histories = BrowsingHistories::History.count(user: user, historizable: Article)
244
+
245
+ # clear
246
+ # clear the article from user's browsing history
247
+ article = Article.first
248
+ BrowsingHistory::History.clear(browseer: user, historizable: article)
249
+
250
+ # clear all user's browsing history
251
+ BrowsingHistory::History.clear(browseer: user, historizable: Article)
252
+ # or
253
+ article = Article.first
254
+ BrowsingHistory::History.clear(browseer: user, historizable: article, all: true)
255
+ ```
256
+
257
+ ## Advanced
258
+
Binary file
@@ -22,7 +22,7 @@ module BrowsingHistory::Browser
22
22
  end
23
23
 
24
24
  def browser_instance?
25
- !instance_of?(Object)
25
+ self.class != Class
26
26
  end
27
27
  end
28
28
 
@@ -1,4 +1,7 @@
1
1
  module BrowsingHistory::Configuration
2
+ class BrowsingHistory::InvalidStorageType < BrowsingHistory::Error; end
3
+ class BrowsingHistory::StorageNotSet < BrowsingHistory::Error; end
4
+
2
5
  # storage type
3
6
  attr_writer :storage_types
4
7
 
@@ -17,6 +20,11 @@ module BrowsingHistory::Configuration
17
20
  @storage_types ||= %i(redis active_record)
18
21
  end
19
22
 
23
+ def storage_types=(types)
24
+ raise BrowsingHistory::StoragesNotSet if types.empty?
25
+ @storage_types = types
26
+ end
27
+
20
28
  # BrowsingHistory storage
21
29
  #
22
30
  # @return the BrowsingHistory storage. default of :redis if not set.
@@ -25,7 +33,7 @@ module BrowsingHistory::Configuration
25
33
  end
26
34
 
27
35
  def storage_type=(type)
28
- return false unless storage_types.incude?(type)
36
+ raise BrowsingHistory::InvalidStorageType unless storage_types.include?(type)
29
37
  @storage_type = type
30
38
  end
31
39
 
@@ -20,7 +20,7 @@ module BrowsingHistory::Historizable
20
20
  end
21
21
 
22
22
  def historizable_instance?
23
- !instance_of?(Object)
23
+ self.class != Class
24
24
  end
25
25
  end
26
26
  end
@@ -51,8 +51,15 @@ class BrowsingHistory::History
51
51
 
52
52
  def count(browser: nil, historizable: nil)
53
53
  return 0 if !browser && !historizable
54
+
54
55
  current_storage.count(browser, historizable)
55
56
  end
57
+
58
+ def clear(browser: nil, historizable: nil, **opts)
59
+ return 0 if !browser && !historizable
60
+
61
+ current_storage.clear(browser, historizable, **opts)
62
+ end
56
63
  end
57
64
 
58
65
  private
@@ -1,8 +1,6 @@
1
1
  require 'browsing_history/storages/base'
2
2
 
3
3
  module BrowsingHistory::Storage
4
- class InvalidStorage < BrowsingHistory::Error; end
5
- class StoragesNotSet < BrowsingHistory::Error; end
6
4
 
7
5
  def self.included(klass)
8
6
  klass.extend ConfigureMethods
@@ -27,7 +25,7 @@ module BrowsingHistory::Storage
27
25
  storage.connect(opts)
28
26
  @current_storage_type = storage_type
29
27
  else
30
- raise InvalidStorage
28
+ raise BrowsingHistory::InvalidStorageType
31
29
  end
32
30
  end
33
31
 
@@ -37,7 +35,7 @@ module BrowsingHistory::Storage
37
35
  "BrowsingHistory::Storages::#{key.to_s.camelize}".constantize
38
36
  end
39
37
 
40
- raise StoragesNotSet if storages.empty?
38
+ raise BrowsingHistory::StoragesNotSet if storages.empty?
41
39
  attach_storage(storages.keys.first)
42
40
  end
43
41
  end
@@ -10,6 +10,7 @@ class BrowsingHistory::Storages::Redis < BrowsingHistory::Storages::Base
10
10
  history.at(opts[:at])
11
11
  else
12
12
  limit = opts[:limit].try(:-, 1) || opts.delete(:end)
13
+
13
14
  history.revrange(opts.delete(:start), limit, **opts)
14
15
  end
15
16
  end
@@ -26,8 +27,10 @@ class BrowsingHistory::Storages::Redis < BrowsingHistory::Storages::Base
26
27
  clear_expiration(opts)
27
28
  elsif opts[:all]
28
29
  clear_all
29
- else
30
+ elsif historizable.historizable_instance?
30
31
  history.delete(historizable)
32
+ else
33
+ clear_all
31
34
  end
32
35
  end
33
36
 
@@ -1,3 +1,3 @@
1
1
  module BrowsingHistory
2
- VERSION = '0.0.3'.freeze
2
+ VERSION = '0.0.4'.freeze
3
3
  end
@@ -19,6 +19,11 @@ describe BrowsingHistory::Browser do
19
19
  it { is_expected.to respond_to(:browser_type) }
20
20
  it { is_expected.to respond_to(:browser_class) }
21
21
  it { is_expected.to respond_to(:browser_instance?) }
22
+
23
+ it { expect(user.browser_id).to eql(user.id) }
24
+ it { expect(user.browser_type).to eql(user.class.to_s) }
25
+ it { expect(user.browser_class).to eql(user.class) }
26
+ it { expect(user.browser_instance?).to be(true) }
22
27
  end
23
28
 
24
29
  context 'singleton' do
@@ -28,6 +33,12 @@ describe BrowsingHistory::Browser do
28
33
  it { is_expected.to respond_to(:browser_type) }
29
34
  it { is_expected.to respond_to(:browser_class) }
30
35
  it { is_expected.to respond_to(:browser_instance?) }
36
+
37
+ let(:klass) { User }
38
+ it { expect(klass.browser_id).to eql(nil) }
39
+ it { expect(klass.browser_type).to eql(klass.to_s) }
40
+ it { expect(klass.browser_class).to eql(klass) }
41
+ it { expect(klass.browser_instance?).to be(false) }
31
42
  end
32
43
  end
33
44
 
@@ -12,5 +12,22 @@ describe BrowsingHistory::Configuration do
12
12
  expect(configuration.namespace).to eql('browsing_history')
13
13
  end
14
14
  end
15
+
16
+ it 'should raise error' do
17
+ expect do
18
+ BrowsingHistory.configure do |configuration|
19
+ configuration.storage_type = :invalid
20
+ end
21
+ end.to raise_error(BrowsingHistory::InvalidStorageType)
22
+ end
23
+
24
+ # it 'should not raise error when include original storage' do
25
+ # expect do
26
+ # BrowsingHistory.configure do |configuration|
27
+ # configuration.storage_types = %i(original)
28
+ # configuration.storage_type = :original
29
+ # end
30
+ # end.not_to raise_error
31
+ # end
15
32
  end
16
33
  end
@@ -200,7 +200,7 @@ describe BrowsingHistory::History do
200
200
  describe '.where' do
201
201
  it 'should default empty' do
202
202
  expect(
203
- BrowsingHistory::History.where(
203
+ described_class.where(
204
204
  browser: user,
205
205
  historizable: article
206
206
  )
@@ -269,4 +269,68 @@ describe BrowsingHistory::History do
269
269
  it { expect(historizables_unhit.size).to eq(0) }
270
270
  end
271
271
  end
272
+
273
+ describe '.clear' do
274
+ context 'default' do
275
+ before(:each) do
276
+ articles.each do |article|
277
+ described_class.create(browser: user, historizable: article)
278
+ end
279
+ end
280
+
281
+ let(:historizables) do
282
+ described_class.where(browser: user, historizable: article)
283
+ end
284
+
285
+ it 'should clear target historizable' do
286
+ described_class.clear(browser: user, historizable: articles[2])
287
+
288
+ expect(historizables.size).to eql(articles.size - 1)
289
+ expect(historizables.map(&:id)).not_to include(2)
290
+ end
291
+
292
+ it 'should clear target historizable' do
293
+ described_class.clear(browser: user, historizable: Article)
294
+
295
+ expect(historizables).to be_empty
296
+ end
297
+ end
298
+
299
+ context 'with all option' do
300
+ before(:each) do
301
+ articles.each do |article|
302
+ described_class.create(browser: user, historizable: article)
303
+ end
304
+
305
+ described_class.clear(browser: user, historizable: article, all: true)
306
+ end
307
+
308
+ subject { described_class.where(browser: user, historizable: article) }
309
+ it { is_expected.to be_empty }
310
+ end
311
+
312
+ context 'with expiration option' do
313
+ before(:each) do
314
+ Timecop.travel(1.day.ago) do
315
+ articles.each do |article|
316
+ described_class.create(browser: user, historizable: article)
317
+ end
318
+ end
319
+
320
+ described_class.create(browser: user, historizable: article)
321
+ end
322
+
323
+ it do
324
+ described_class.clear(
325
+ browser: user,
326
+ historizable: article,
327
+ expiration: 23.hours.ago
328
+ )
329
+
330
+ expect(
331
+ described_class.count(browser: user, historizable: article)
332
+ ).to eql(1)
333
+ end
334
+ end
335
+ end
272
336
  end
@@ -38,7 +38,7 @@ describe BrowsingHistory::Storage do
38
38
  it 'should raise error' do
39
39
  expect do
40
40
  include_class_invalid_storage
41
- end.to raise_error(BrowsingHistory::Storage::InvalidStorage)
41
+ end.to raise_error(BrowsingHistory::InvalidStorageType)
42
42
  end
43
43
  end
44
44
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: browsing_history
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - tkclimb
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-29 00:00:00.000000000 Z
11
+ date: 2016-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -185,8 +185,8 @@ files:
185
185
  - README.md
186
186
  - README.rdoc
187
187
  - Rakefile
188
+ - browsing_history-demo.gif
188
189
  - browsing_history.gemspec
189
- - dump.rdb
190
190
  - lib/browsing_history.rb
191
191
  - lib/browsing_history/browser.rb
192
192
  - lib/browsing_history/configuration.rb
data/dump.rdb DELETED
@@ -1 +0,0 @@
1
- REDIS0006�ܳC�Z��V