acts_as_readable 2.2.0 → 2.3.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 +8 -0
- data/lib/acts_as_readable/acts_as_readable.rb +17 -15
- data/spec/acts_as_readable_spec.rb +98 -3
- data/spec/spec_helper.rb +8 -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: 28febc32aaf17802d8db7b624fc3dce68bf6620d438b8a2bab8c7aa2cc8620ca
|
4
|
+
data.tar.gz: 6ad32b0cf210c6806c90611e6cc2575a5d710b87e65bd8d0d08ef35bde28627b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42f65a6d0f3071710fa9cbdb4b65c507f0a753dc299294989d5c908148512e3443514f4f500555be7fa01fcf3ccb618435a9a8a5197398668f3319d8d0b0daaf
|
7
|
+
data.tar.gz: cbd81ccf4ea4d53f58ea46c67cf5d625daa83909476d84597eb4caf6c0ceae4f826579543240cee80bad5d231de4038072a3f59f5809d7c219117355418556a6
|
data/README.rdoc
CHANGED
@@ -32,4 +32,12 @@ TODO...
|
|
32
32
|
|
33
33
|
bob.readings # => [<Reading 1>]
|
34
34
|
|
35
|
+
=== Testing
|
36
|
+
|
37
|
+
There are multiple gemfiles available for testing against different Rails versions. Set `BUNDLE_GEMFILE` to target them, e.g.
|
38
|
+
|
39
|
+
bundle install
|
40
|
+
BUNDLE_GEMFILE=gemfiles/rails7.gemfile bundle exec rspec
|
41
|
+
|
42
|
+
|
35
43
|
Copyright (c) 2012 Culture Code Software Consulting. Released under the MIT license
|
@@ -8,11 +8,13 @@ module ActsAsReadable
|
|
8
8
|
|
9
9
|
User.has_many :readings, :dependent => :delete_all
|
10
10
|
|
11
|
-
has_many :readings,
|
12
|
-
has_many :readers,
|
11
|
+
has_many :readings, :as => :readable, :dependent => :delete_all
|
12
|
+
has_many :readers, lambda { where :readings => {:state => 'read'} }, :through => :readings, :source => :user
|
13
13
|
|
14
|
-
scope :read_by,
|
15
|
-
scope :unread_by,
|
14
|
+
scope :read_by, lambda {|user| ActsAsReadable::HelperMethods.outer_join_readings(all, user).where(ActsAsReadable::HelperMethods.read_conditions(self, user, :created_at))}
|
15
|
+
scope :unread_by, lambda {|user| ActsAsReadable::HelperMethods.outer_join_readings(all, user).where(ActsAsReadable::HelperMethods.unread_conditions(self, user, :created_at))}
|
16
|
+
scope :latest_update_read_by, lambda {|user| ActsAsReadable::HelperMethods.outer_join_readings(all, user).where(ActsAsReadable::HelperMethods.read_conditions(self, user, :updated_at))}
|
17
|
+
scope :latest_update_unread_by, lambda {|user| ActsAsReadable::HelperMethods.outer_join_readings(all, user).where(ActsAsReadable::HelperMethods.unread_conditions(self, user, :updated_at))}
|
16
18
|
|
17
19
|
extend ActsAsReadable::ClassMethods
|
18
20
|
include ActsAsReadable::InstanceMethods
|
@@ -24,19 +26,19 @@ module ActsAsReadable
|
|
24
26
|
end
|
25
27
|
|
26
28
|
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)
|
29
|
+
def self.read_conditions(readable_class, user, timestamp)
|
30
|
+
["(readings.state IS NULL AND COALESCE(#{readable_class.table_name}.#{timestamp} <= :all_read_at, FALSE))
|
31
|
+
OR (readings.state = 'unread' AND COALESCE(readings.updated_at <= :all_read_at, FALSE))
|
32
|
+
OR (readings.state = 'read' AND #{readable_class.table_name}.#{timestamp} <= readings.#{timestamp})",
|
33
|
+
:all_read_at => all_read_at(readable_class, user)]
|
32
34
|
end
|
33
35
|
|
34
|
-
def self.unread_conditions(readable_class, user)
|
36
|
+
def self.unread_conditions(readable_class, user, timestamp)
|
35
37
|
# 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)
|
38
|
+
["(readings.state IS NULL AND COALESCE(#{readable_class.table_name}.#{timestamp} > :all_read_at, TRUE))
|
39
|
+
OR (readings.state = 'unread' AND COALESCE(readings.updated_at > :all_read_at, TRUE))
|
40
|
+
OR (readings.state = 'read' AND #{readable_class.table_name}.#{timestamp} > readings.#{timestamp})",
|
41
|
+
:all_read_at => all_read_at(readable_class, user)]
|
40
42
|
end
|
41
43
|
|
42
44
|
def self.all_read_at(readable_class, user)
|
@@ -67,7 +69,7 @@ module ActsAsReadable
|
|
67
69
|
# 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
70
|
def read_by!(user)
|
69
71
|
if user.has_attribute?(acts_as_readable_options[:cache])
|
70
|
-
Reading.
|
72
|
+
Reading.where(:user_id => user.id, :readable_type => name).delete_all
|
71
73
|
user.update_column(acts_as_readable_options[:cache], Time.now)
|
72
74
|
else
|
73
75
|
unread_by(user).find_each do |record|
|
@@ -28,16 +28,23 @@ describe 'acts_as_readable' do
|
|
28
28
|
expect( Comment.unread_by(@user) ).to include(@comment)
|
29
29
|
end
|
30
30
|
|
31
|
+
it "should return records explicitly marked as unread after the user 'read all'" do
|
32
|
+
@comment.read_by! @user
|
33
|
+
Comment.read_by! @user
|
34
|
+
@comment.unread_by! @user
|
35
|
+
expect( Comment.unread_by(@user) ).to include(@comment)
|
36
|
+
end
|
37
|
+
|
31
38
|
it "should not return records explicitly marked as unread if the user has 'read all' after the record was marked unread" do
|
32
39
|
@comment.unread_by! @user
|
33
40
|
Comment.read_by! @user
|
34
41
|
expect( Comment.unread_by(@user) ).not_to include(@comment)
|
35
42
|
end
|
36
43
|
|
37
|
-
it "should return records that have been updated since they were last read" do
|
44
|
+
it "should not return records that have been updated since they were last read" do
|
38
45
|
@comment.read_by! @user
|
39
46
|
@comment.touch
|
40
|
-
expect( Comment.unread_by(@user) ).
|
47
|
+
expect( Comment.unread_by(@user) ).not_to include(@comment)
|
41
48
|
end
|
42
49
|
|
43
50
|
it "should return records that have been updated since they were last unread" do
|
@@ -48,6 +55,10 @@ describe 'acts_as_readable' do
|
|
48
55
|
end
|
49
56
|
|
50
57
|
describe "the read scope" do
|
58
|
+
it "should not return records without readings if the user has not 'read all'" do
|
59
|
+
expect( Comment.read_by(@user) ).not_to include(@comment)
|
60
|
+
end
|
61
|
+
|
51
62
|
it "should return records without readings if the user has 'read all' since the last time the record was updated" do
|
52
63
|
Comment.read_by! @user
|
53
64
|
expect( Comment.read_by(@user) ).to include(@comment)
|
@@ -58,17 +69,101 @@ describe 'acts_as_readable' do
|
|
58
69
|
expect( Comment.read_by(@user) ).to include(@comment)
|
59
70
|
end
|
60
71
|
|
61
|
-
it "should return records explicitly marked as read if the user has 'read all' before the record was marked
|
72
|
+
it "should return records explicitly marked as read if the user has 'read all' before the record was marked read" do
|
62
73
|
Comment.read_by! @user
|
63
74
|
@comment.read_by! @user
|
64
75
|
expect( Comment.read_by(@user) ).to include(@comment)
|
65
76
|
end
|
66
77
|
|
78
|
+
it "should not return records explicitly marked as unread after the user 'read all'" do
|
79
|
+
@comment.read_by! @user
|
80
|
+
Comment.read_by! @user
|
81
|
+
@comment.unread_by! @user
|
82
|
+
expect( Comment.read_by(@user) ).not_to include(@comment)
|
83
|
+
end
|
84
|
+
|
67
85
|
it "should return records explicitly marked as unread if the user has 'read all' after the record was marked unread" do
|
68
86
|
@comment.unread_by! @user
|
69
87
|
Comment.read_by! @user
|
70
88
|
expect( Comment.read_by(@user) ).to include(@comment)
|
71
89
|
end
|
90
|
+
|
91
|
+
it "should return records that have been updated since they were last read" do
|
92
|
+
@comment.read_by! @user
|
93
|
+
@comment.touch
|
94
|
+
expect( Comment.read_by(@user) ).to include(@comment)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "the latest_update_read_by scope" do
|
99
|
+
it "should return records without readings if the user has 'read all' since the last time the record was updated" do
|
100
|
+
Comment.read_by! @user
|
101
|
+
expect( Comment.latest_update_read_by(@user) ).to include(@comment)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should return records explicitly marked as read if the user hasn't 'read all'" do
|
105
|
+
@comment.read_by! @user
|
106
|
+
expect( Comment.latest_update_read_by(@user) ).to include(@comment)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should return records explicitly marked as read if the user has 'read all' before the record was marked unread" do
|
110
|
+
Comment.read_by! @user
|
111
|
+
@comment.read_by! @user
|
112
|
+
expect( Comment.latest_update_read_by(@user) ).to include(@comment)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should return records explicitly marked as unread if the user has 'read all' after the record was marked unread" do
|
116
|
+
@comment.unread_by! @user
|
117
|
+
Comment.read_by! @user
|
118
|
+
expect( Comment.latest_update_read_by(@user) ).to include(@comment)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should not return records that have been updated since they were last read" do
|
122
|
+
@comment.read_by! @user
|
123
|
+
@comment.touch
|
124
|
+
expect( Comment.latest_update_read_by(@user) ).not_to include(@comment)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should return records updated after being read after a bulk read_by" do
|
128
|
+
@comment.read_by! @user
|
129
|
+
@comment.touch
|
130
|
+
Comment.read_by! @user
|
131
|
+
expect( Comment.latest_update_read_by(@user) ).to include(@comment)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "the latest_update_unread_by scope" do
|
136
|
+
it "should not return records explicitly marked as read" do
|
137
|
+
@comment.read_by! @user
|
138
|
+
expect( Comment.latest_update_unread_by(@user) ).not_to include(@comment)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should return records without readings if the user hasn't 'read all'" do
|
142
|
+
expect( Comment.latest_update_unread_by(@user) ).to include(@comment)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should return records explicitly marked as unread if the user hasn't 'read all'" do
|
146
|
+
@comment.unread_by! @user
|
147
|
+
expect( Comment.latest_update_unread_by(@user) ).to include(@comment)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should return records explicitly marked as unread if the user has 'read all' before the record was marked unread" do
|
151
|
+
Comment.read_by! @user
|
152
|
+
@comment.unread_by! @user
|
153
|
+
expect( Comment.latest_update_unread_by(@user) ).to include(@comment)
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should not return records explicitly marked as unread if the user has 'read all' after the record was marked unread" do
|
157
|
+
@comment.unread_by! @user
|
158
|
+
Comment.read_by! @user
|
159
|
+
expect( Comment.latest_update_unread_by(@user) ).not_to include(@comment)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should return records that have been updated since they were last read" do
|
163
|
+
@comment.read_by! @user
|
164
|
+
@comment.touch
|
165
|
+
expect( Comment.latest_update_unread_by(@user) ).to include(@comment)
|
166
|
+
end
|
72
167
|
end
|
73
168
|
|
74
169
|
describe "when checking a specific record for read_by?" do
|
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|
|
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.3.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-02-22 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
|