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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2eb3570785a65d3e80567534270dae5825eceb07fdeec498764c2065f129892
4
- data.tar.gz: c9bacbe67acb169365404c423640fd4f25d9536315228d014bea8c6e7e100987
3
+ metadata.gz: 28febc32aaf17802d8db7b624fc3dce68bf6620d438b8a2bab8c7aa2cc8620ca
4
+ data.tar.gz: 6ad32b0cf210c6806c90611e6cc2575a5d710b87e65bd8d0d08ef35bde28627b
5
5
  SHA512:
6
- metadata.gz: c7ddc495d6010d7748b134c731908c1a2e71b88b4cc86b8f694729e4bc1c83659e10bf0b0547801012124f1f946d871397ef9ac53c1ff9798a5753bddbf40f5d
7
- data.tar.gz: 97cdf31a2684e938da9462d8f6d8f20ca0d6bd7170da449ef7e4eafa7c21633f452bcf6227daacb95541c37747e61aa99bcdb942a3c4e0aaa1f2400c06787d34
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, :as => :readable, :dependent => :delete_all
12
- has_many :readers, lambda { where :readings => {:state => 'read'} }, :through => :readings, :source => :user
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, lambda {|user| ActsAsReadable::HelperMethods.outer_join_readings(all, user).where(ActsAsReadable::HelperMethods.read_conditions(self, user))}
15
- scope :unread_by, lambda {|user| ActsAsReadable::HelperMethods.outer_join_readings(all, user).where(ActsAsReadable::HelperMethods.unread_conditions(self, user))}
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
- ["(readable_type IS NULL AND COALESCE(#{readable_class.table_name}.updated_at < :all_read_at, :true))
29
- OR (readable_type IS NOT NULL AND COALESCE(readings.updated_at < :all_read_at, :true))
30
- OR (readings.state = 'read')",
31
- :all_read_at => all_read_at(readable_class, user), :true => true]
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}.updated_at > :all_read_at, :true))
37
- OR (readings.state = 'unread' AND COALESCE(readings.updated_at > :all_read_at, :true))
38
- OR (readings.state = 'read' AND COALESCE(#{readable_class.table_name}.updated_at > readings.updated_at, :true))",
39
- :all_read_at => all_read_at(readable_class, user), :true => true]
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.delete_all(:user_id => user.id, :readable_type => name)
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) ).to include(@comment)
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 unread" do
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(:adapter => "postgresql", :database => "acts_as_readable_test") # Not using sqlite3 for testing because of its ridiculous boolean handling
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.2.0
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: 2020-09-08 00:00:00.000000000 Z
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: '4.0'
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.0'
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.0.8
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