browsing_history 0.0.3 → 0.0.4

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: 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