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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4a505cc9665d3fbc592d8e08c232aecab8c8f955
4
- data.tar.gz: 3ed4a918d476407b1c4186a354bc40903f8017f4
3
+ metadata.gz: 1f23a993cd5ea8af4de3fe027645d22413746d39
4
+ data.tar.gz: f999afb9b8bc45f737658abec73edb706f94ac63
5
5
  SHA512:
6
- metadata.gz: 99ce880aace3ccdcaa1ba0706cdb10ef8c1c428404901f673b81c66c69d088c599d9684bc57b57692a34a7a668e29364403453df010b7276dd4cdff56ecd9926
7
- data.tar.gz: 91b45d17da9f3f8f742e945fa24b058fb462cf5cb84cb2e88dc3b13124d1197488ad55a67c20e4762f056fedc5e8893b05616056459c562c3b89f2c9fd260176
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
- TODO: Write usage instructions here
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.joins(:read_activity_marks).merge(ReadActivityMark.where(reader: reader))
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.where(reader: reader)
35
- mark.exists?
34
+ mark = self.read_activity_marks.exists?(reader: reader)
36
35
  end
37
36
 
38
- def read_by_at(reader)
39
- mark = ReadActivityMark.find_by(readable: self, reader: reader)
40
- return mark.created_at if mark
41
- return nil
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
@@ -9,7 +9,7 @@ module ReadActivity
9
9
 
10
10
  module ClassMethods
11
11
  def find_who_read(readable)
12
- self.joins(:read_activity_marks).merge(ReadActivityMark.where(readable: readable))
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
- # inverse of Readable#read_by_at
44
- def read_at(readable)
45
- readable.read_by_at(self)
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)
@@ -1,3 +1,3 @@
1
1
  module ReadActivity
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -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 user read readables" do
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
@@ -4,6 +4,7 @@ SimpleCov.start
4
4
  require "active_record"
5
5
  require "database_cleaner"
6
6
  require "factory_girl"
7
+ Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
7
8
 
8
9
  require "read_activity"
9
10
 
@@ -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
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-09-18 00:00:00.000000000 Z
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