unread 0.0.7 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +9 -0
- data/changelog.md +6 -1
- data/lib/app/models/read_mark.rb +1 -0
- data/lib/unread/acts_as_readable.rb +41 -20
- data/lib/unread/version.rb +1 -1
- data/test/unread_test.rb +13 -1
- metadata +5 -5
data/README.md
CHANGED
@@ -71,6 +71,7 @@ Step 2: Add this migration:
|
|
71
71
|
message1 = Message.create!
|
72
72
|
message2 = Message.create!
|
73
73
|
|
74
|
+
## Get unread messages for a given user
|
74
75
|
Message.unread_by(current_user)
|
75
76
|
# => [ message1, message2 ]
|
76
77
|
|
@@ -78,6 +79,14 @@ Step 2: Add this migration:
|
|
78
79
|
Message.unread_by(current_user)
|
79
80
|
# => [ message2 ]
|
80
81
|
|
82
|
+
## Get all messages including the read status for a given user
|
83
|
+
messages = Message.with_read_marks_for(current_user)
|
84
|
+
# => [ message1, message2 ]
|
85
|
+
messages[0].unread?(current_user)
|
86
|
+
# => false
|
87
|
+
messages[1].unread?(current_user)
|
88
|
+
# => true
|
89
|
+
|
81
90
|
Message.mark_as_read! :all, :for => current_user
|
82
91
|
Message.unread_by(current_user)
|
83
92
|
# => [ ]
|
data/changelog.md
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0 - 2012/04/21
|
2
|
+
|
3
|
+
* Added scope "with_read_marks_for"
|
4
|
+
* Fixed #7: Added attr_accessible to all ReadMark attributes (thanks to @negative)
|
5
|
+
|
6
|
+
0.0.7 - 2012/02/29
|
2
7
|
|
3
8
|
* Cleanup files
|
4
9
|
* acts_as_reader: Using inverse_of (available since Rails 2.3.6)
|
data/lib/app/models/read_mark.rb
CHANGED
@@ -14,6 +14,8 @@ module Unread
|
|
14
14
|
klass.mark_as_read! :all, :for => user
|
15
15
|
end
|
16
16
|
end
|
17
|
+
|
18
|
+
include ReaderInstanceMethods
|
17
19
|
end
|
18
20
|
|
19
21
|
def acts_as_readable(options={})
|
@@ -41,18 +43,27 @@ module Unread
|
|
41
43
|
AND read_marks.user_id = #{user.id}
|
42
44
|
AND read_marks.timestamp >= #{self.table_name}.#{readable_options[:on]}",
|
43
45
|
:conditions => 'read_marks.id IS NULL' }
|
44
|
-
if
|
45
|
-
result[:conditions] += " AND #{self.table_name}.#{readable_options[:on]} > '#{
|
46
|
+
if global_time_stamp = user.read_mark_global(self).try(:timestamp)
|
47
|
+
result[:conditions] += " AND #{self.table_name}.#{readable_options[:on]} > '#{global_time_stamp.to_s(:db)}'"
|
46
48
|
end
|
47
49
|
result
|
48
50
|
}
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
+
send scope_method, :with_read_marks_for, lambda { |user|
|
53
|
+
assert_reader(user)
|
54
|
+
|
55
|
+
{ :select => "#{self.table_name}.*, read_marks.id AS read_mark_id",
|
56
|
+
:joins => "LEFT JOIN read_marks ON read_marks.readable_type = '#{self.base_class.name}'
|
57
|
+
AND read_marks.readable_id = #{self.table_name}.id
|
58
|
+
AND read_marks.user_id = #{user.id}
|
59
|
+
AND read_marks.timestamp >= #{self.table_name}.#{readable_options[:on]}" }
|
60
|
+
}
|
61
|
+
extend ReadableClassMethods
|
62
|
+
include ReadableInstanceMethods
|
52
63
|
end
|
53
64
|
end
|
54
65
|
|
55
|
-
module
|
66
|
+
module ReadableClassMethods
|
56
67
|
def mark_as_read!(target, options)
|
57
68
|
raise ArgumentError unless target == :all || target.is_a?(Array)
|
58
69
|
|
@@ -63,8 +74,6 @@ module Unread
|
|
63
74
|
reset_read_marks!(user)
|
64
75
|
elsif target.is_a?(Array)
|
65
76
|
ReadMark.transaction do
|
66
|
-
last = read_timestamp(user)
|
67
|
-
|
68
77
|
target.each do |obj|
|
69
78
|
raise ArgumentError unless obj.is_a?(self)
|
70
79
|
|
@@ -77,17 +86,8 @@ module Unread
|
|
77
86
|
end
|
78
87
|
end
|
79
88
|
|
80
|
-
def read_mark(user)
|
81
|
-
assert_reader(user)
|
82
|
-
user.read_marks.readable_type(self.base_class.name).global.first
|
83
|
-
end
|
84
|
-
|
85
|
-
def read_timestamp(user)
|
86
|
-
read_mark(user).try(:timestamp)
|
87
|
-
end
|
88
|
-
|
89
89
|
def set_read_mark(user, timestamp)
|
90
|
-
rm =
|
90
|
+
rm = user.read_mark_global(self) || user.read_marks.build(:readable_type => self.base_class.name)
|
91
91
|
rm.timestamp = timestamp
|
92
92
|
rm.save!
|
93
93
|
end
|
@@ -156,9 +156,20 @@ module Unread
|
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
159
|
-
module
|
159
|
+
module ReadableInstanceMethods
|
160
160
|
def unread?(user)
|
161
|
-
self.
|
161
|
+
if self.respond_to?(:read_mark_id)
|
162
|
+
# For use with scope "with_read_marks_for"
|
163
|
+
return false if self.read_mark_id
|
164
|
+
|
165
|
+
if global_timestamp = user.read_mark_global(self.class).try(:timestamp)
|
166
|
+
self.send(readable_options[:on]) > global_timestamp
|
167
|
+
else
|
168
|
+
true
|
169
|
+
end
|
170
|
+
else
|
171
|
+
self.class.unread_by(user).exists?(self)
|
172
|
+
end
|
162
173
|
end
|
163
174
|
|
164
175
|
def mark_as_read!(options)
|
@@ -167,7 +178,7 @@ module Unread
|
|
167
178
|
|
168
179
|
ReadMark.transaction do
|
169
180
|
if unread?(user)
|
170
|
-
rm = read_mark(user) || read_marks.build(:
|
181
|
+
rm = read_mark(user) || read_marks.build(:user_id => user.id)
|
171
182
|
rm.timestamp = self.send(readable_options[:on])
|
172
183
|
rm.save!
|
173
184
|
end
|
@@ -178,6 +189,16 @@ module Unread
|
|
178
189
|
read_marks.user(user).first
|
179
190
|
end
|
180
191
|
end
|
192
|
+
|
193
|
+
module ReaderInstanceMethods
|
194
|
+
def read_mark_global(klass)
|
195
|
+
instance_var_name = "@read_mark_global_#{klass.name}"
|
196
|
+
instance_variable_get(instance_var_name) || begin # memoize
|
197
|
+
obj = self.read_marks.readable_type(klass.base_class.name).global.first
|
198
|
+
instance_variable_set(instance_var_name, obj)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
181
202
|
end
|
182
203
|
|
183
204
|
ActiveRecord::Base.send :include, Unread
|
data/lib/unread/version.rb
CHANGED
data/test/unread_test.rb
CHANGED
@@ -40,6 +40,18 @@ class UnreadTest < ActiveSupport::TestCase
|
|
40
40
|
}
|
41
41
|
end
|
42
42
|
|
43
|
+
def test_with_read_marks_for
|
44
|
+
@email1.mark_as_read! :for => @reader
|
45
|
+
|
46
|
+
emails = Email.with_read_marks_for(@reader).all
|
47
|
+
|
48
|
+
assert emails[0].read_mark_id.present?
|
49
|
+
assert emails[1].read_mark_id.nil?
|
50
|
+
|
51
|
+
assert_equal false, emails[0].unread?(@reader)
|
52
|
+
assert_equal true, emails[1].unread?(@reader)
|
53
|
+
end
|
54
|
+
|
43
55
|
def test_scope_after_reset
|
44
56
|
@email1.mark_as_read! :for => @reader
|
45
57
|
|
@@ -105,7 +117,7 @@ class UnreadTest < ActiveSupport::TestCase
|
|
105
117
|
|
106
118
|
def test_mark_all_as_read
|
107
119
|
Email.mark_as_read! :all, :for => @reader
|
108
|
-
assert_equal Time.now.to_s,
|
120
|
+
assert_equal Time.now.to_s, @reader.read_mark_global(Email).try(:timestamp).to_s
|
109
121
|
|
110
122
|
assert_equal [], @reader.read_marks.single
|
111
123
|
assert_equal 0, ReadMark.single.count
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unread
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.7
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Georg Ledermann
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-04-21 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: activerecord
|
@@ -148,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
148
|
requirements: []
|
149
149
|
|
150
150
|
rubyforge_project: unread
|
151
|
-
rubygems_version: 1.8.
|
151
|
+
rubygems_version: 1.8.23
|
152
152
|
signing_key:
|
153
153
|
specification_version: 3
|
154
154
|
summary: Manages read/unread status of ActiveRecord objects
|