read_activity 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +44 -2
- data/lib/generators/read_activity/templates/create_read_activity_marks.rb +2 -2
- data/lib/read_activity/readable.rb +18 -7
- data/lib/read_activity/reader.rb +17 -4
- data/lib/read_activity/version.rb +1 -1
- data/spec/read_activity/readable_spec.rb +12 -2
- data/spec/read_activity/reader_spec.rb +19 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/support/matchers/under_query_limit.rb +19 -0
- data/spec/support/query_counter.rb +18 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f23a993cd5ea8af4de3fe027645d22413746d39
|
4
|
+
data.tar.gz: f999afb9b8bc45f737658abec73edb706f94ac63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8b52e2215b02a37524e4576c1a4f0a7abbbfe15e13f853c07d5b520fc1a0134e120f4b9f92eba57ad527fe863fdfb8b480248bc7fdd7ea4eda046b4f6d29660
|
7
|
+
data.tar.gz: 2ed81496b4533bb17b1b840d10b38e62736d882e8bf3a6c23baee8ce93db9821951d7754cfd6b97c047b1eaa74b1c41dad50a0fcc8bec63775bc1b8d0d5ed65e
|
data/README.md
CHANGED
@@ -20,9 +20,51 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
$ gem install read_activity
|
22
22
|
|
23
|
-
## Usage
|
23
|
+
## Usage example
|
24
24
|
|
25
|
-
|
25
|
+
```ruby
|
26
|
+
|
27
|
+
class User < ActiveRecord::Base
|
28
|
+
acts_as_reader
|
29
|
+
end
|
30
|
+
|
31
|
+
class Article < ActiveRecord::Base
|
32
|
+
acts_as_readable
|
33
|
+
end
|
34
|
+
|
35
|
+
user = User.create!
|
36
|
+
article = Article.create!
|
37
|
+
|
38
|
+
user.read!(article)
|
39
|
+
# or article.read_by!(user)
|
40
|
+
|
41
|
+
user.read?(article) # == true
|
42
|
+
# or article.read_by?(user) == true
|
43
|
+
|
44
|
+
user.read_at(article)
|
45
|
+
# or article.read_by_at(user)
|
46
|
+
|
47
|
+
article.readers # == [user]
|
48
|
+
# or user.read_articles == [article]
|
49
|
+
# user.read_#{reader_table_name} (the plural form)
|
50
|
+
|
51
|
+
article.unreaders # == []
|
52
|
+
# or user.unread_articles == []
|
53
|
+
# user.unread_#{readable_table_name} (the plural form)
|
54
|
+
|
55
|
+
reader = article.readers.first
|
56
|
+
reader.read_at # no required params when you have fetched readers using #readers
|
57
|
+
|
58
|
+
read_article = user.read_articles.first
|
59
|
+
read_article.read_by_at
|
60
|
+
|
61
|
+
User.find_who_read(article)
|
62
|
+
User.find_who_unread(article)
|
63
|
+
|
64
|
+
Article.find_read_by(user)
|
65
|
+
Article.find_unread_by(user)
|
66
|
+
|
67
|
+
```
|
26
68
|
|
27
69
|
## Contributing
|
28
70
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class CreateReadActivityMarks < ActiveRecord::Migration
|
2
2
|
def change
|
3
3
|
create_table :read_activity_marks do |t|
|
4
|
-
t.references :reader, null: false
|
5
|
-
t.references :readable, polymorphic: true
|
4
|
+
t.references :reader, null: false, index: true
|
5
|
+
t.references :readable, polymorphic: true, index: true
|
6
6
|
t.integer :mark, default: 0
|
7
7
|
|
8
8
|
t.timestamps
|
@@ -10,7 +10,7 @@ module ReadActivity
|
|
10
10
|
|
11
11
|
module ClassMethods
|
12
12
|
def find_read_by(reader)
|
13
|
-
self.
|
13
|
+
self.includes(:read_activity_marks).merge(ReadActivityMark.where(reader: reader)).references(:read_activity_marks)
|
14
14
|
end
|
15
15
|
|
16
16
|
def find_unread_by(reader)
|
@@ -31,14 +31,25 @@ module ReadActivity
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def read_by?(reader)
|
34
|
-
mark = self.read_activity_marks.
|
35
|
-
mark.exists?
|
34
|
+
mark = self.read_activity_marks.exists?(reader: reader)
|
36
35
|
end
|
37
36
|
|
38
|
-
def read_by_at(reader)
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
def read_by_at(reader = nil)
|
38
|
+
read_by_at = nil
|
39
|
+
|
40
|
+
if self.read_activity_marks.loaded?
|
41
|
+
read_by_at = self.read_activity_marks.first.try(:created_at)
|
42
|
+
end
|
43
|
+
|
44
|
+
if read_by_at.nil? && reader
|
45
|
+
if reader.read_activity_marks.loaded?
|
46
|
+
read_by_at = reader.read_activity_marks.first.try(:created_at)
|
47
|
+
else
|
48
|
+
read_by_at = self.read_activity_marks.where(reader: reader).first.try(:created_at)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
return read_by_at
|
42
53
|
end
|
43
54
|
|
44
55
|
def readers
|
data/lib/read_activity/reader.rb
CHANGED
@@ -9,7 +9,7 @@ module ReadActivity
|
|
9
9
|
|
10
10
|
module ClassMethods
|
11
11
|
def find_who_read(readable)
|
12
|
-
self.
|
12
|
+
self.includes(:read_activity_marks).merge(ReadActivityMark.where(readable: readable)).references(:read_activity_marks)
|
13
13
|
end
|
14
14
|
|
15
15
|
def find_who_unread(readable)
|
@@ -40,9 +40,22 @@ module ReadActivity
|
|
40
40
|
klass.send(:find_unread_by, self)
|
41
41
|
end
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
def read_at(readable = nil)
|
44
|
+
read_at = nil
|
45
|
+
|
46
|
+
if self.read_activity_marks.loaded?
|
47
|
+
read_at = self.read_activity_marks.first.try(:created_at)
|
48
|
+
end
|
49
|
+
|
50
|
+
if read_at.nil? && readable
|
51
|
+
if readable.read_activity_marks.loaded?
|
52
|
+
read_at = readable.read_activity_marks.first.try(:created_at)
|
53
|
+
else
|
54
|
+
read_at = self.read_activity_marks.where(readable: readable).first.try(:created_at)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
return read_at
|
46
59
|
end
|
47
60
|
|
48
61
|
def method_missing(method, *arguments, &block)
|
@@ -39,7 +39,7 @@ RSpec.describe ReadActivity::Readable do
|
|
39
39
|
expect(mark.reader).to eq(user)
|
40
40
|
expect(mark.readable).to eq(article)
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
it "should create only ReadActivityMark for specific readable" do
|
44
44
|
user = FactoryGirl.create(:user)
|
45
45
|
article = FactoryGirl.create(:article)
|
@@ -87,7 +87,7 @@ RSpec.describe ReadActivity::Readable do
|
|
87
87
|
end
|
88
88
|
|
89
89
|
describe "#read_by_at" do
|
90
|
-
it "should return when
|
90
|
+
it "should return when users read readables" do
|
91
91
|
user = FactoryGirl.create(:user)
|
92
92
|
article = FactoryGirl.create(:article)
|
93
93
|
|
@@ -96,5 +96,15 @@ RSpec.describe ReadActivity::Readable do
|
|
96
96
|
|
97
97
|
expect(article.read_by_at(user)).to eq(user.read_activity_marks.take.created_at)
|
98
98
|
end
|
99
|
+
|
100
|
+
it "should return when readers read readables" do
|
101
|
+
user = FactoryGirl.create(:user)
|
102
|
+
article = FactoryGirl.create(:article)
|
103
|
+
|
104
|
+
article.read_by!(user)
|
105
|
+
|
106
|
+
articles = user.read_articles
|
107
|
+
expect(articles.first.read_by_at).to eq(user.read_activity_marks.take.created_at)
|
108
|
+
end
|
99
109
|
end
|
100
110
|
end
|
@@ -132,10 +132,28 @@ RSpec.describe ReadActivity::Reader do
|
|
132
132
|
user = FactoryGirl.create(:user)
|
133
133
|
article = FactoryGirl.create(:article)
|
134
134
|
|
135
|
-
expect(user.read_at(article)).to eq(nil)
|
136
135
|
user.read!(article)
|
137
136
|
|
138
137
|
expect(user.read_at(article)).to eq(user.read_activity_marks.take.created_at)
|
139
138
|
end
|
139
|
+
|
140
|
+
it "should return when readers read readables" do
|
141
|
+
user = FactoryGirl.create(:user)
|
142
|
+
article = FactoryGirl.create(:article)
|
143
|
+
|
144
|
+
user.read!(article)
|
145
|
+
|
146
|
+
readers = article.readers
|
147
|
+
expect(readers.first.read_at).to eq(user.read_activity_marks.take.created_at)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should be optimized" do
|
151
|
+
users = FactoryGirl.create_list(:user, 3)
|
152
|
+
article = FactoryGirl.create(:article)
|
153
|
+
|
154
|
+
users.each { |user| user.read!(article) }
|
155
|
+
|
156
|
+
expect { article.readers.each{ |user| user.read_at } }.to under_query_limit(1)
|
157
|
+
end
|
140
158
|
end
|
141
159
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# https://gist.github.com/rsutphin/af06c9e3dadf658d2293
|
2
|
+
# Derived from http://stackoverflow.com/a/13423584/153896. Updated for RSpec 3.
|
3
|
+
RSpec::Matchers.define :under_query_limit do |expected|
|
4
|
+
supports_block_expectations
|
5
|
+
|
6
|
+
match do |block|
|
7
|
+
query_count(&block) <= expected
|
8
|
+
end
|
9
|
+
|
10
|
+
failure_message do |actual|
|
11
|
+
"Expected to run maximum #{expected} queries, got #{@counter.query_count}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def query_count(&block)
|
15
|
+
@counter = ActiveRecord::QueryCounter.new
|
16
|
+
ActiveSupport::Notifications.subscribed(@counter.to_proc, 'sql.active_record', &block)
|
17
|
+
@counter.query_count
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Derived from http://stackoverflow.com/a/13423584/153896
|
2
|
+
module ActiveRecord
|
3
|
+
class QueryCounter
|
4
|
+
attr_reader :query_count
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@query_count = 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_proc
|
11
|
+
lambda(&method(:callback))
|
12
|
+
end
|
13
|
+
|
14
|
+
def callback(name, start, finish, message_id, values)
|
15
|
+
@query_count += 1 unless %w(CACHE SCHEMA).include?(values[:name])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: read_activity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hong ChulJu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -169,6 +169,8 @@ files:
|
|
169
169
|
- spec/read_activity/reader_spec.rb
|
170
170
|
- spec/schema.rb
|
171
171
|
- spec/spec_helper.rb
|
172
|
+
- spec/support/matchers/under_query_limit.rb
|
173
|
+
- spec/support/query_counter.rb
|
172
174
|
homepage: https://github.com/FeGs/read_activity
|
173
175
|
licenses:
|
174
176
|
- MIT
|
@@ -202,3 +204,5 @@ test_files:
|
|
202
204
|
- spec/read_activity/reader_spec.rb
|
203
205
|
- spec/schema.rb
|
204
206
|
- spec/spec_helper.rb
|
207
|
+
- spec/support/matchers/under_query_limit.rb
|
208
|
+
- spec/support/query_counter.rb
|