acts_as_readable 2.2.0 → 2.4.0
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 +4 -4
- data/README.rdoc +16 -1
- data/lib/acts_as_readable/acts_as_readable.rb +25 -21
- data/spec/acts_as_readable_spec.rb +237 -127
- data/spec/spec_helper.rb +12 -1
- metadata +44 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26f1b10303846fe0f6adb4dd943ca37ba592463bfaf57b6dbf8f55008bca9d9f
|
4
|
+
data.tar.gz: c108f52d20a6b6e32f76b57486a87dffcea367b33e2b9d11845761cbde28bb76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2cdf040047e4f4985c51d2bd1a0b3f207f4f8d6ee7c17f3732c5c93a09f89c2a842ec670e970ff5c8cb0f00dc0bf02fdbff9fe04b3d154b3881f4d52db17f209
|
7
|
+
data.tar.gz: 335b0e36faf70e2385bc806a5900a4eddaf66ab0e8fdf18b9c2850a041329408c89b0c8d6107eb29a596bcee7c3217522fc5a2907d625b202fec5ce61d19f0f7
|
data/README.rdoc
CHANGED
@@ -32,4 +32,19 @@ TODO...
|
|
32
32
|
|
33
33
|
bob.readings # => [<Reading 1>]
|
34
34
|
|
35
|
-
|
35
|
+
=== Upgrading from 2.3.x to 2.4.0
|
36
|
+
|
37
|
+
Version 2.4.0 now supports reading and querying against STI subclasses, even when the read and queried subclass don't
|
38
|
+
match. This requires you to migrate the `readings.readable_type` column data to the base class name of the stored class
|
39
|
+
name, as in versions prior to 2.4.0 the column stored the class name of whatever instance was being read, event STI
|
40
|
+
subclasses.
|
41
|
+
|
42
|
+
=== Testing
|
43
|
+
|
44
|
+
There are multiple gemfiles available for testing against different Rails versions. Set `BUNDLE_GEMFILE` to target them, e.g.
|
45
|
+
|
46
|
+
bundle install
|
47
|
+
BUNDLE_GEMFILE=gemfiles/rails7.gemfile bundle exec rspec
|
48
|
+
|
49
|
+
|
50
|
+
Copyright (c) 2024 Culture Code Software Consulting. Released under the MIT license
|
@@ -6,13 +6,13 @@ module ActsAsReadable
|
|
6
6
|
class_attribute :acts_as_readable_options
|
7
7
|
self.acts_as_readable_options = options
|
8
8
|
|
9
|
-
|
9
|
+
has_many :readings, :as => :readable, :dependent => :delete_all
|
10
|
+
has_many :readers, lambda { where :readings => {:state => 'read'} }, :through => :readings, :source => :user
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
scope :
|
15
|
-
scope :unread_by, lambda {|user| ActsAsReadable::HelperMethods.outer_join_readings(all, user).where(ActsAsReadable::HelperMethods.unread_conditions(self, user))}
|
12
|
+
scope :read_by, lambda {|user| ActsAsReadable::HelperMethods.outer_join_readings(all, user).where(ActsAsReadable::HelperMethods.read_conditions(self, user, :created_at))}
|
13
|
+
scope :unread_by, lambda {|user| ActsAsReadable::HelperMethods.outer_join_readings(all, user).where(ActsAsReadable::HelperMethods.unread_conditions(self, user, :created_at))}
|
14
|
+
scope :latest_update_read_by, lambda {|user| ActsAsReadable::HelperMethods.outer_join_readings(all, user).where(ActsAsReadable::HelperMethods.read_conditions(self, user, :updated_at))}
|
15
|
+
scope :latest_update_unread_by, lambda {|user| ActsAsReadable::HelperMethods.outer_join_readings(all, user).where(ActsAsReadable::HelperMethods.unread_conditions(self, user, :updated_at))}
|
16
16
|
|
17
17
|
extend ActsAsReadable::ClassMethods
|
18
18
|
include ActsAsReadable::InstanceMethods
|
@@ -24,19 +24,19 @@ module ActsAsReadable
|
|
24
24
|
end
|
25
25
|
|
26
26
|
module HelperMethods
|
27
|
-
def self.read_conditions(readable_class, user)
|
28
|
-
["(
|
29
|
-
OR (
|
30
|
-
OR (readings.state = 'read')",
|
31
|
-
:all_read_at => all_read_at(readable_class, user)
|
27
|
+
def self.read_conditions(readable_class, user, timestamp)
|
28
|
+
["(readings.state IS NULL AND COALESCE(#{readable_class.table_name}.#{timestamp} <= :all_read_at, FALSE))
|
29
|
+
OR (readings.state = 'unread' AND COALESCE(readings.updated_at <= :all_read_at, FALSE))
|
30
|
+
OR (readings.state = 'read' AND #{readable_class.table_name}.#{timestamp} <= readings.#{timestamp})",
|
31
|
+
:all_read_at => all_read_at(readable_class, user)]
|
32
32
|
end
|
33
33
|
|
34
|
-
def self.unread_conditions(readable_class, user)
|
34
|
+
def self.unread_conditions(readable_class, user, timestamp)
|
35
35
|
# IF there is no reading and it has been updated since we last read all OR there is an unreading and we haven't read all since then
|
36
|
-
["(readings.state IS NULL AND COALESCE(#{readable_class.table_name}
|
37
|
-
OR (readings.state = 'unread' AND COALESCE(readings.updated_at > :all_read_at,
|
38
|
-
OR (readings.state = 'read' AND
|
39
|
-
:all_read_at => all_read_at(readable_class, user)
|
36
|
+
["(readings.state IS NULL AND COALESCE(#{readable_class.table_name}.#{timestamp} > :all_read_at, TRUE))
|
37
|
+
OR (readings.state = 'unread' AND COALESCE(readings.updated_at > :all_read_at, TRUE))
|
38
|
+
OR (readings.state = 'read' AND #{readable_class.table_name}.#{timestamp} > readings.#{timestamp})",
|
39
|
+
:all_read_at => all_read_at(readable_class, user)]
|
40
40
|
end
|
41
41
|
|
42
42
|
def self.all_read_at(readable_class, user)
|
@@ -44,7 +44,11 @@ module ActsAsReadable
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def self.outer_join_readings(scope, user)
|
47
|
-
scope.joins("LEFT OUTER JOIN readings ON readings.readable_type = '#{scope.model
|
47
|
+
scope.joins("LEFT OUTER JOIN readings ON readings.readable_type = '#{readable_type(scope.model)}' AND readings.readable_id = #{scope.model.table_name}.id AND readings.user_id = #{user.id}")
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.readable_type(readable_class)
|
51
|
+
readable_class.base_class.name
|
48
52
|
end
|
49
53
|
end
|
50
54
|
|
@@ -52,7 +56,7 @@ module ActsAsReadable
|
|
52
56
|
# Find all the readings of the readables by the user in a single SQL query and cache them in the readables for use in the view.
|
53
57
|
def cache_readings_for(readables, user)
|
54
58
|
readings = []
|
55
|
-
Reading.where(:readable_type =>
|
59
|
+
Reading.where(:readable_type => HelperMethods.readable_type(self), :readable_id => readables.collect(&:id), :user_id => user.id).each do |reading|
|
56
60
|
readings[reading.readable_id] = reading
|
57
61
|
end
|
58
62
|
|
@@ -67,7 +71,7 @@ module ActsAsReadable
|
|
67
71
|
# If a :cache option has been set in acts_as_readable, a timestamp will be updated on the user instead of creating individual readings for each record
|
68
72
|
def read_by!(user)
|
69
73
|
if user.has_attribute?(acts_as_readable_options[:cache])
|
70
|
-
Reading.
|
74
|
+
Reading.where(:user_id => user.id, :readable_type => HelperMethods.readable_type(self)).delete_all
|
71
75
|
user.update_column(acts_as_readable_options[:cache], Time.now)
|
72
76
|
else
|
73
77
|
unread_by(user).find_each do |record|
|
@@ -86,7 +90,7 @@ module ActsAsReadable
|
|
86
90
|
|
87
91
|
def read_by!(user)
|
88
92
|
# Find an existing reading and update the record so we can know when the thing was first read, and the last time we read it
|
89
|
-
reading = Reading.find_or_initialize_by(:user_id => user.id, :readable_id => self.id, :readable_type => self.class
|
93
|
+
reading = Reading.find_or_initialize_by(:user_id => user.id, :readable_id => self.id, :readable_type => HelperMethods.readable_type(self.class))
|
90
94
|
reading.updated_at = Time.now # Explicitly set the read time to now in order to force a save in case we haven't changed anything else about the reading
|
91
95
|
reading.state = :read
|
92
96
|
reading.save!
|
@@ -96,7 +100,7 @@ module ActsAsReadable
|
|
96
100
|
end
|
97
101
|
|
98
102
|
def unread_by!(user)
|
99
|
-
reading = Reading.find_or_initialize_by(:user_id => user.id, :readable_id => self.id, :readable_type => self.class
|
103
|
+
reading = Reading.find_or_initialize_by(:user_id => user.id, :readable_id => self.id, :readable_type => HelperMethods.readable_type(self.class))
|
100
104
|
reading.state = :unread
|
101
105
|
reading.save!
|
102
106
|
end
|
@@ -2,140 +2,250 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe 'acts_as_readable' do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
5
|
+
shared_examples_for 'a readable class' do |readable_class, queryable_class|
|
6
|
+
before(:each) do
|
7
|
+
@readable = readable_class.create
|
8
|
+
@queryable = @readable.becomes!(queryable_class)
|
9
|
+
@user = User.create
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "the unread scope" do
|
13
|
+
it "should not return records explicitly marked as read" do
|
14
|
+
@readable.read_by! @user
|
15
|
+
expect(queryable_class.unread_by(@user)).not_to include(@queryable)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return records without readings if the user hasn't 'read all'" do
|
19
|
+
expect(queryable_class.unread_by(@user)).to include(@queryable)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return records explicitly marked as unread if the user hasn't 'read all'" do
|
23
|
+
@readable.unread_by! @user
|
24
|
+
expect(queryable_class.unread_by(@user)).to include(@queryable)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return records explicitly marked as unread if the user has 'read all' before the record was marked unread" do
|
28
|
+
readable_class.read_by! @user
|
29
|
+
@readable.unread_by! @user
|
30
|
+
expect(queryable_class.unread_by(@user)).to include(@queryable)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return records explicitly marked as unread after the user 'read all'" do
|
34
|
+
@readable.read_by! @user
|
35
|
+
readable_class.read_by! @user
|
36
|
+
@readable.unread_by! @user
|
37
|
+
expect(queryable_class.unread_by(@user)).to include(@queryable)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should not return records explicitly marked as unread if the user has 'read all' after the record was marked unread" do
|
41
|
+
@readable.unread_by! @user
|
42
|
+
readable_class.read_by! @user
|
43
|
+
expect(queryable_class.unread_by(@user)).not_to include(@queryable)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should not return records that have been updated since they were last read" do
|
47
|
+
@readable.read_by! @user
|
48
|
+
@readable.touch
|
49
|
+
expect(queryable_class.unread_by(@user)).not_to include(@queryable)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return records that have been updated since they were last unread" do
|
53
|
+
@readable.unread_by! @user
|
54
|
+
@readable.touch
|
55
|
+
expect(queryable_class.unread_by(@user)).to include(@queryable)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "the read scope" do
|
60
|
+
it "should not return records without readings if the user has not 'read all'" do
|
61
|
+
expect(queryable_class.read_by(@user)).not_to include(@queryable)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should return records without readings if the user has 'read all' since the last time the record was updated" do
|
65
|
+
readable_class.read_by! @user
|
66
|
+
expect(queryable_class.read_by(@user)).to include(@queryable)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should return records explicitly marked as read if the user hasn't 'read all'" do
|
70
|
+
@readable.read_by! @user
|
71
|
+
expect(queryable_class.read_by(@user)).to include(@queryable)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should return records explicitly marked as read if the user has 'read all' before the record was marked read" do
|
75
|
+
readable_class.read_by! @user
|
76
|
+
@readable.read_by! @user
|
77
|
+
expect(queryable_class.read_by(@user)).to include(@queryable)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should not return records explicitly marked as unread after the user 'read all'" do
|
81
|
+
@readable.read_by! @user
|
82
|
+
readable_class.read_by! @user
|
83
|
+
@readable.unread_by! @user
|
84
|
+
expect(queryable_class.read_by(@user)).not_to include(@queryable)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should return records explicitly marked as unread if the user has 'read all' after the record was marked unread" do
|
88
|
+
@readable.unread_by! @user
|
89
|
+
readable_class.read_by! @user
|
90
|
+
expect(queryable_class.read_by(@user)).to include(@queryable)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should return records that have been updated since they were last read" do
|
94
|
+
@readable.read_by! @user
|
95
|
+
@readable.touch
|
96
|
+
expect(queryable_class.read_by(@user)).to include(@queryable)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "the latest_update_read_by scope" do
|
101
|
+
it "should return records without readings if the user has 'read all' since the last time the record was updated" do
|
102
|
+
readable_class.read_by! @user
|
103
|
+
expect(queryable_class.latest_update_read_by(@user)).to include(@queryable)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should return records explicitly marked as read if the user hasn't 'read all'" do
|
107
|
+
@readable.read_by! @user
|
108
|
+
expect(queryable_class.latest_update_read_by(@user)).to include(@queryable)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should return records explicitly marked as read if the user has 'read all' before the record was marked unread" do
|
112
|
+
readable_class.read_by! @user
|
113
|
+
@readable.read_by! @user
|
114
|
+
expect(queryable_class.latest_update_read_by(@user)).to include(@queryable)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should return records explicitly marked as unread if the user has 'read all' after the record was marked unread" do
|
118
|
+
@readable.unread_by! @user
|
119
|
+
readable_class.read_by! @user
|
120
|
+
expect(queryable_class.latest_update_read_by(@user)).to include(@queryable)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should not return records that have been updated since they were last read" do
|
124
|
+
@readable.read_by! @user
|
125
|
+
@readable.touch
|
126
|
+
expect(queryable_class.latest_update_read_by(@user)).not_to include(@queryable)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should return records updated after being read after a bulk read_by" do
|
130
|
+
@readable.read_by! @user
|
131
|
+
@readable.touch
|
132
|
+
readable_class.read_by! @user
|
133
|
+
expect(queryable_class.latest_update_read_by(@user)).to include(@queryable)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "the latest_update_unread_by scope" do
|
138
|
+
it "should not return records explicitly marked as read" do
|
139
|
+
@readable.read_by! @user
|
140
|
+
expect(queryable_class.latest_update_unread_by(@user)).not_to include(@queryable)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should return records without readings if the user hasn't 'read all'" do
|
144
|
+
expect(queryable_class.latest_update_unread_by(@user)).to include(@queryable)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should return records explicitly marked as unread if the user hasn't 'read all'" do
|
148
|
+
@readable.unread_by! @user
|
149
|
+
expect(queryable_class.latest_update_unread_by(@user)).to include(@queryable)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should return records explicitly marked as unread if the user has 'read all' before the record was marked unread" do
|
153
|
+
readable_class.read_by! @user
|
154
|
+
@readable.unread_by! @user
|
155
|
+
expect(queryable_class.latest_update_unread_by(@user)).to include(@queryable)
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should not return records explicitly marked as unread if the user has 'read all' after the record was marked unread" do
|
159
|
+
@readable.unread_by! @user
|
160
|
+
readable_class.read_by! @user
|
161
|
+
expect(queryable_class.latest_update_unread_by(@user)).not_to include(@queryable)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should return records that have been updated since they were last read" do
|
165
|
+
@readable.read_by! @user
|
166
|
+
@readable.touch
|
167
|
+
expect(queryable_class.latest_update_unread_by(@user)).to include(@queryable)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe "when checking a specific record for read_by?" do
|
172
|
+
it "should return true if the record hasn't explicitly been read, but the user has 'read all' since the record was created" do
|
173
|
+
readable_class.read_by! @user
|
174
|
+
expect(@queryable.read_by?(@user)).to be_truthy
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should return true if the record hasn't explicitly been read and the user has 'read all' since the record was created but not since it was updated" do
|
178
|
+
readable_class.read_by! @user
|
179
|
+
@readable.touch
|
180
|
+
expect(@queryable.read_by?(@user)).to be_truthy
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should return true if the record has been explicitly marked as read and the user hasn't 'read all'" do
|
184
|
+
@readable.read_by! @user
|
185
|
+
expect(@queryable.read_by?(@user)).to be_truthy
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should return false if the user 'read all' before and then marked the record as unread" do
|
189
|
+
readable_class.read_by! @user
|
190
|
+
@readable.unread_by! @user
|
191
|
+
expect(@queryable.read_by?(@user)).to be_falsey
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should return true if the user has explicitly marked it as unread and then 'reads all'" do
|
195
|
+
@readable.unread_by! @user
|
196
|
+
readable_class.read_by! @user
|
197
|
+
expect(@queryable.read_by?(@user)).to be_truthy
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe "when checking a specific record for latest_update_read_by?" do
|
202
|
+
it "should return true if the record hasn't explicitly been read, but the user has 'read all' since the record was updated" do
|
203
|
+
readable_class.read_by! @user
|
204
|
+
expect(@queryable.latest_update_read_by?(@user)).to be_truthy
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should return false if the record hasn't explicitly been read and the user has 'read all' since the record was created but not since it was updated" do
|
208
|
+
readable_class.read_by! @user
|
209
|
+
@readable.touch
|
210
|
+
expect(@queryable.latest_update_read_by?(@user)).to be_falsey
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should return true if the record has been explicitly marked as read and the user hasn't 'read all'" do
|
214
|
+
@readable.read_by! @user
|
215
|
+
expect(@queryable.latest_update_read_by?(@user)).to be_truthy
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should return false if the user 'read all' before and then marked the record as unread" do
|
219
|
+
readable_class.read_by! @user
|
220
|
+
@readable.unread_by! @user
|
221
|
+
expect(@queryable.latest_update_read_by?(@user)).to be_falsey
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should return true if the user has explicitly marked it as unread and then 'reads all'" do
|
225
|
+
@readable.unread_by! @user
|
226
|
+
readable_class.read_by! @user
|
227
|
+
expect(@queryable.latest_update_read_by?(@user)).to be_truthy
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should return false if the user 'read all' before and then marked the record as unread using cached readings" do
|
231
|
+
readable_class.read_by! @user
|
232
|
+
@readable.unread_by! @user
|
233
|
+
readable_class.cache_readings_for([@readable], @user)
|
234
|
+
expect(@queryable.latest_update_read_by?(@user)).to be_falsey
|
235
|
+
end
|
47
236
|
end
|
48
237
|
end
|
49
238
|
|
50
|
-
|
51
|
-
|
52
|
-
Comment.read_by! @user
|
53
|
-
expect( Comment.read_by(@user) ).to include(@comment)
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should return records explicitly marked as read if the user hasn't 'read all'" do
|
57
|
-
@comment.read_by! @user
|
58
|
-
expect( Comment.read_by(@user) ).to include(@comment)
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should return records explicitly marked as read if the user has 'read all' before the record was marked unread" do
|
62
|
-
Comment.read_by! @user
|
63
|
-
@comment.read_by! @user
|
64
|
-
expect( Comment.read_by(@user) ).to include(@comment)
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should return records explicitly marked as unread if the user has 'read all' after the record was marked unread" do
|
68
|
-
@comment.unread_by! @user
|
69
|
-
Comment.read_by! @user
|
70
|
-
expect( Comment.read_by(@user) ).to include(@comment)
|
71
|
-
end
|
239
|
+
context 'the readable is a base class' do
|
240
|
+
it_behaves_like 'a readable class', Comment, Comment
|
72
241
|
end
|
73
242
|
|
74
|
-
|
75
|
-
|
76
|
-
Comment.read_by! @user
|
77
|
-
expect( @comment.read_by?(@user) ).to be_truthy
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should return true if the record hasn't explicitly been read and the user has 'read all' since the record was created but not since it was updated" do
|
81
|
-
Comment.read_by! @user
|
82
|
-
@comment.touch
|
83
|
-
expect( @comment.read_by?(@user) ).to be_truthy
|
84
|
-
end
|
85
|
-
|
86
|
-
it "should return true if the record has been explicitly marked as read and the user hasn't 'read all'" do
|
87
|
-
@comment.read_by! @user
|
88
|
-
expect( @comment.read_by?(@user) ).to be_truthy
|
89
|
-
end
|
90
|
-
|
91
|
-
it "should return false if the user 'read all' before and then marked the record as unread" do
|
92
|
-
Comment.read_by! @user
|
93
|
-
@comment.unread_by! @user
|
94
|
-
expect( @comment.read_by?(@user) ).to be_falsey
|
95
|
-
end
|
96
|
-
|
97
|
-
it "should return true if the user has explicitly marked it as unread and then 'reads all'" do
|
98
|
-
@comment.unread_by! @user
|
99
|
-
Comment.read_by! @user
|
100
|
-
expect( @comment.read_by?(@user) ).to be_truthy
|
101
|
-
end
|
243
|
+
context 'when reading an STI record' do
|
244
|
+
it_behaves_like 'a readable class', PrivateComment, PrivateComment
|
102
245
|
end
|
103
246
|
|
104
|
-
|
105
|
-
|
106
|
-
Comment.read_by! @user
|
107
|
-
expect( @comment.latest_update_read_by?(@user) ).to be_truthy
|
108
|
-
end
|
109
|
-
|
110
|
-
it "should return false if the record hasn't explicitly been read and the user has 'read all' since the record was created but not since it was updated" do
|
111
|
-
Comment.read_by! @user
|
112
|
-
@comment.touch
|
113
|
-
expect( @comment.latest_update_read_by?(@user) ).to be_falsey
|
114
|
-
end
|
115
|
-
|
116
|
-
it "should return true if the record has been explicitly marked as read and the user hasn't 'read all'" do
|
117
|
-
@comment.read_by! @user
|
118
|
-
expect( @comment.latest_update_read_by?(@user) ).to be_truthy
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should return false if the user 'read all' before and then marked the record as unread" do
|
122
|
-
Comment.read_by! @user
|
123
|
-
@comment.unread_by! @user
|
124
|
-
expect( @comment.latest_update_read_by?(@user) ).to be_falsey
|
125
|
-
end
|
126
|
-
|
127
|
-
it "should return true if the user has explicitly marked it as unread and then 'reads all'" do
|
128
|
-
@comment.unread_by! @user
|
129
|
-
Comment.read_by! @user
|
130
|
-
expect( @comment.latest_update_read_by?(@user) ).to be_truthy
|
131
|
-
end
|
132
|
-
|
133
|
-
it "should return false if the user 'read all' before and then marked the record as unread using cached readings" do
|
134
|
-
Comment.read_by! @user
|
135
|
-
@comment.unread_by! @user
|
136
|
-
Comment.cache_readings_for([@comment], @user)
|
137
|
-
expect( @comment.latest_update_read_by?(@user) ).to be_falsey
|
138
|
-
end
|
247
|
+
context 'when reading an STI record and querying against the base class record' do
|
248
|
+
it_behaves_like 'a readable class', PrivateComment, Comment
|
139
249
|
end
|
140
250
|
end
|
141
251
|
`dropdb acts_as_readable_test`
|
data/spec/spec_helper.rb
CHANGED
@@ -2,7 +2,14 @@ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
|
2
2
|
require 'active_record'
|
3
3
|
require 'acts_as_readable'
|
4
4
|
|
5
|
-
ActiveRecord::Base.establish_connection(
|
5
|
+
ActiveRecord::Base.establish_connection(
|
6
|
+
:adapter => "postgresql",
|
7
|
+
:host => "localhost",
|
8
|
+
:encoding => "unicode",
|
9
|
+
:database => "acts_as_readable_test",
|
10
|
+
:username => ENV["POSTGRES_USER"],
|
11
|
+
:password => ENV["POSTGRES_PASSWORD"]
|
12
|
+
)
|
6
13
|
|
7
14
|
ActiveRecord::Schema.define(:version => 0) do
|
8
15
|
create_table :users, :force => true do |t|
|
@@ -10,6 +17,7 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
10
17
|
end
|
11
18
|
|
12
19
|
create_table :comments, :force => true do |t|
|
20
|
+
t.string :type
|
13
21
|
t.timestamps
|
14
22
|
end
|
15
23
|
|
@@ -28,6 +36,9 @@ class Comment < ActiveRecord::Base
|
|
28
36
|
acts_as_readable :cache => :comments_read_at
|
29
37
|
end
|
30
38
|
|
39
|
+
class PrivateComment < Comment
|
40
|
+
end
|
41
|
+
|
31
42
|
|
32
43
|
def debug_queries
|
33
44
|
logger = ActiveRecord::Base.logger
|
metadata
CHANGED
@@ -1,31 +1,65 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_readable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicholas Jakobsen
|
8
8
|
- Ryan Wallace
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-03-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - "
|
18
|
+
- - ">"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '5'
|
21
|
+
- - "<"
|
19
22
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
23
|
+
version: '8'
|
21
24
|
type: :runtime
|
22
25
|
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- - ">"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '5'
|
31
|
+
- - "<"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '8'
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: pg
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
type: :development
|
42
|
+
prerelease: false
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rspec-rails
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
23
57
|
version_requirements: !ruby/object:Gem::Requirement
|
24
58
|
requirements:
|
25
59
|
- - "~>"
|
26
60
|
- !ruby/object:Gem::Version
|
27
|
-
version: '4
|
28
|
-
description:
|
61
|
+
version: '4'
|
62
|
+
description:
|
29
63
|
email: contact@culturecode.ca
|
30
64
|
executables: []
|
31
65
|
extensions: []
|
@@ -42,7 +76,7 @@ files:
|
|
42
76
|
homepage: http://github.com/culturecode/acts_as_readable
|
43
77
|
licenses: []
|
44
78
|
metadata: {}
|
45
|
-
post_install_message:
|
79
|
+
post_install_message:
|
46
80
|
rdoc_options: []
|
47
81
|
require_paths:
|
48
82
|
- lib
|
@@ -57,8 +91,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
91
|
- !ruby/object:Gem::Version
|
58
92
|
version: '0'
|
59
93
|
requirements: []
|
60
|
-
rubygems_version: 3.
|
61
|
-
signing_key:
|
94
|
+
rubygems_version: 3.3.23
|
95
|
+
signing_key:
|
62
96
|
specification_version: 4
|
63
97
|
summary: Allows records to be marked as readable. Optimized for bulk, 'mark all as
|
64
98
|
read' operations
|