unread 0.9.1 → 0.10.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
- SHA1:
3
- metadata.gz: de3df2e59a6b6f3a9526ff9e5fa922c110ef8be3
4
- data.tar.gz: d5978503df223116016aeb6295d75c9ff3cf5183
2
+ SHA256:
3
+ metadata.gz: 783e65e652089e8325398c9f593d126f4332d83041cd2fd88cc86266105a1809
4
+ data.tar.gz: 24f73b4d3038e0d81acff4ca44c7fead8f628a2eea5e7479420b47952d8215fe
5
5
  SHA512:
6
- metadata.gz: 52db71810adf1939ebf35bd0aedf2ce6f9f546190ec35719dc3dfc6a190132585b49dbd5fa0e44ef47ebb2b0bb5a06832bde7c9073c8b80066a0de3ff9b98dee
7
- data.tar.gz: 6178164de3a46bb4c40a1a0e7ab5c0d9eef3a3dd71a8ee642701a19555f38f026ca6f28018967b96b982e1281d225f3a8aeed81d2343567d8c0ca4955aa1e165
6
+ metadata.gz: ba242fd2a04f70545c5313bc73d5aff1a5bbee97b29a52625df620a3290800a90267693e8d3d5d488b00d4dd72e6dfe0a8eb1eae12428cb56ccd6cbff4dd04fe
7
+ data.tar.gz: 849a46af19decb7627d0359b46bfd79f269751603144e59c621d27c56caac81943b8b2ae9b85e03a0326ac84f28d4fca59288d627d4d8eacca61fe05decb1ae7
@@ -1,44 +1,25 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.0.0
4
- - 2.1.10
5
- - 2.2.7
6
- - 2.3.3
7
- - 2.4.1
3
+ - 2.2.9
4
+ - 2.3.6
5
+ - 2.4.3
6
+ - 2.5.0
8
7
  gemfile:
8
+ - gemfiles/rails_5_2.gemfile
9
9
  - gemfiles/rails_5_1.gemfile
10
10
  - gemfiles/rails_5_0.gemfile
11
11
  - gemfiles/rails_4_2.gemfile
12
12
  - gemfiles/rails_4_1.gemfile
13
13
  - gemfiles/rails_4_0.gemfile
14
- - gemfiles/rails_3_2.gemfile
15
- - gemfiles/rails_3_1.gemfile
16
- - gemfiles/rails_3_0.gemfile
17
14
  matrix:
18
15
  exclude:
19
- - rvm: 2.0.0
20
- gemfile: gemfiles/rails_5_1.gemfile
21
- - rvm: 2.1.10
22
- gemfile: gemfiles/rails_5_1.gemfile
23
- - rvm: 2.0.0
24
- gemfile: gemfiles/rails_5_0.gemfile
25
- - rvm: 2.1.10
26
- gemfile: gemfiles/rails_5_0.gemfile
27
- - rvm: 2.3.3
28
- gemfile: gemfiles/rails_3_0.gemfile
29
- - rvm: 2.3.3
30
- gemfile: gemfiles/rails_3_1.gemfile
31
- - rvm: 2.3.3
32
- gemfile: gemfiles/rails_3_2.gemfile
33
- - rvm: 2.4.1
34
- gemfile: gemfiles/rails_3_0.gemfile
35
- - rvm: 2.4.1
36
- gemfile: gemfiles/rails_3_1.gemfile
37
- - rvm: 2.4.1
38
- gemfile: gemfiles/rails_3_2.gemfile
39
- - rvm: 2.4.1
16
+ - rvm: 2.4.3
40
17
  gemfile: gemfiles/rails_4_0.gemfile
41
- - rvm: 2.4.1
18
+ - rvm: 2.4.3
19
+ gemfile: gemfiles/rails_4_1.gemfile
20
+ - rvm: 2.5.0
21
+ gemfile: gemfiles/rails_4_0.gemfile
22
+ - rvm: 2.5.0
42
23
  gemfile: gemfiles/rails_4_1.gemfile
43
24
  before_install: gem update bundler
44
25
  sudo: false
@@ -47,5 +28,6 @@ env:
47
28
  - DB=mysql
48
29
  - DB=postgres
49
30
  before_script:
31
+ - gem update --system # https://github.com/travis-ci/travis-ci/issues/8978
50
32
  - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS unread_test;'; fi"
51
33
  - sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'create database unread_test;' -U postgres; fi"
data/Appraisals CHANGED
@@ -1,3 +1,8 @@
1
+ appraise "rails-5-2" do
2
+ gem "activerecord", "~> 5.2.0.beta2"
3
+ gem "mysql2", ">= 0.3.18", "< 0.5", "!= 0.4.3"
4
+ end
5
+
1
6
  appraise "rails-5-1" do
2
7
  gem "activerecord", "~> 5.1.0"
3
8
  gem 'mysql2', '>= 0.3.18', '< 0.5'
@@ -22,18 +27,3 @@ appraise "rails-4-0" do
22
27
  gem "activerecord", "~> 4.0.13"
23
28
  gem "mysql2", '~> 0.3.10'
24
29
  end
25
-
26
- appraise "rails-3-2" do
27
- gem "activerecord", "~> 3.2.22"
28
- gem 'mysql2', '~> 0.3.10'
29
- end
30
-
31
- appraise "rails-3-1" do
32
- gem "activerecord", "~> 3.1.12"
33
- gem 'mysql2', '~> 0.3.10'
34
- end
35
-
36
- appraise "rails-3-0" do
37
- gem "activerecord", "~> 3.0.20"
38
- gem "activerecord-mysql2-adapter"
39
- end
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2010-2017 Georg Ledermann
3
+ Copyright (c) 2010-2018 Georg Ledermann
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -4,7 +4,7 @@ Unread
4
4
  Ruby gem to manage read/unread status of ActiveRecord objects - and it's fast.
5
5
 
6
6
  [![Build Status](https://travis-ci.org/ledermann/unread.svg?branch=master)](https://travis-ci.org/ledermann/unread)
7
- [![Code Climate](https://codeclimate.com/github/ledermann/unread.svg)](https://codeclimate.com/github/ledermann/unread)
7
+ [![Maintainability](https://api.codeclimate.com/v1/badges/930c8df0f99b20324444/maintainability)](https://codeclimate.com/github/ledermann/unread/maintainability)
8
8
  [![Coverage Status](https://coveralls.io/repos/ledermann/unread/badge.svg?branch=master)](https://coveralls.io/r/ledermann/unread?branch=master)
9
9
 
10
10
  ## Features
@@ -19,8 +19,8 @@ Ruby gem to manage read/unread status of ActiveRecord objects - and it's fast.
19
19
 
20
20
  ## Requirements
21
21
 
22
- * Ruby 2.0.0 or newer
23
- * Rails 3.0 or newer (including Rails 4.x and Rails 5.x)
22
+ * Ruby 2.2 or newer
23
+ * Rails 4.0 or newer (including Rails 5.1 and 5.2)
24
24
  * MySQL, PostgreSQL or SQLite
25
25
  * Needs a timestamp field in your models (like created_at or updated_at) with a database index on it
26
26
 
@@ -65,12 +65,22 @@ class User < ActiveRecord::Base
65
65
 
66
66
  # Optional: Allow a subset of users as readers only
67
67
  def self.reader_scope
68
- where(:is_admin => true)
68
+ where(is_admin: true)
69
69
  end
70
70
  end
71
71
 
72
72
  class Message < ActiveRecord::Base
73
- acts_as_readable :on => :created_at
73
+ acts_as_readable on: :created_at
74
+
75
+ # The `on:` option sets the relevant attribute for comparing timestamps.
76
+ #
77
+ # The default is :updated_at, so updating a record, which was read by a
78
+ # reader makes it unread again.
79
+ #
80
+ # Using :created_at, only new records will show up as unread. Updating a
81
+ # record which was read by a reader, will NOT mark it as unread.
82
+ #
83
+ # Any other existing timestamp field can be used as `on:` option.
74
84
  end
75
85
 
76
86
  message1 = Message.create!
@@ -80,7 +90,7 @@ message2 = Message.create!
80
90
  Message.unread_by(current_user)
81
91
  # => [ message1, message2 ]
82
92
 
83
- message1.mark_as_read! :for => current_user
93
+ message1.mark_as_read! for: current_user
84
94
  Message.unread_by(current_user)
85
95
  # => [ message2 ]
86
96
 
@@ -88,7 +98,7 @@ Message.unread_by(current_user)
88
98
  Message.read_by(current_user)
89
99
  # => [ ]
90
100
 
91
- message1.mark_as_read! :for => current_user
101
+ message1.mark_as_read! for: current_user
92
102
  Message.read_by(current_user)
93
103
  # => [ message1 ]
94
104
 
@@ -100,7 +110,7 @@ messages[0].unread?(current_user)
100
110
  messages[1].unread?(current_user)
101
111
  # => true
102
112
 
103
- Message.mark_as_read! :all, :for => current_user
113
+ Message.mark_as_read! :all, for: current_user
104
114
  Message.unread_by(current_user)
105
115
  # => [ ]
106
116
 
@@ -114,7 +124,7 @@ user2 = User.create!
114
124
  User.have_not_read(message1)
115
125
  # => [ user1, user2 ]
116
126
 
117
- message1.mark_as_read! :for => user1
127
+ message1.mark_as_read! for: user1
118
128
  User.have_not_read(message1)
119
129
  # => [ user2 ]
120
130
 
@@ -122,11 +132,11 @@ User.have_not_read(message1)
122
132
  User.have_read(message1)
123
133
  # => [ user1 ]
124
134
 
125
- message1.mark_as_read! :for => user2
135
+ message1.mark_as_read! for: user2
126
136
  User.have_read(message1)
127
137
  # => [ user1, user2 ]
128
138
 
129
- Message.mark_as_read! :all, :for => user1
139
+ Message.mark_as_read! :all, for: user1
130
140
  User.have_not_read(message1)
131
141
  # => [ ]
132
142
  User.have_not_read(message2)
@@ -189,4 +199,4 @@ AND messages.created_at > '2010-10-20 08:50:00'
189
199
  Hint: You should add a database index on `messages.created_at`.
190
200
 
191
201
 
192
- Copyright (c) 2010-2017 [Georg Ledermann](http://www.georg-ledermann.de) and [contributors](https://github.com/ledermann/unread/graphs/contributors), released under the MIT license
202
+ Copyright (c) 2010-2018 [Georg Ledermann](http://www.georg-ledermann.de) and [contributors](https://github.com/ledermann/unread/graphs/contributors), released under the MIT license
data/Rakefile CHANGED
@@ -3,4 +3,4 @@ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
data/UPGRADE.md CHANGED
@@ -11,7 +11,7 @@ The gem accepts any type of classes as reader and it's not limited to `User` cla
11
11
 
12
12
  ```ruby
13
13
  Customer.have_not_read(message1)
14
- message1.mark_as_read! :for => Customer.find(1)
14
+ message1.mark_as_read! for: Customer.find(1)
15
15
  ```
16
16
 
17
17
  If you are upgrading from v0.6.3 or older, you need to do the following after upgrading:
@@ -32,7 +32,7 @@ The class method `acts_as_reader` doesn't take the option `:scope` anymore. If y
32
32
 
33
33
  ```ruby
34
34
  class User < ActiveRecord::Base
35
- acts_as_reader :scope => -> { where(:is_admin => true) }
35
+ acts_as_reader scope: -> { where(is_admin: true) }
36
36
  end
37
37
  ```
38
38
 
@@ -43,7 +43,7 @@ class User < ActiveRecord::Base
43
43
  acts_as_reader
44
44
 
45
45
  def self.reader_scope
46
- where(:is_admin => true)
46
+ where(is_admin: true)
47
47
  end
48
48
  end
49
49
  ```
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "~> 3.0.20"
6
- gem "activerecord-mysql2-adapter"
5
+ gem "activerecord", "~> 5.2.0.beta2"
6
+ gem "mysql2", ">= 0.3.18", "< 0.5", "!= 0.4.3"
7
7
 
8
8
  gemspec path: "../"
@@ -8,9 +8,9 @@ module Unread
8
8
  ReadMark.reader_classes ||= []
9
9
 
10
10
  unless ReadMark.reader_classes.include?(self)
11
- ReadMark.belongs_to :reader, :polymorphic => true, inverse_of: :read_marks
11
+ ReadMark.belongs_to :reader, polymorphic: true, inverse_of: :read_marks
12
12
 
13
- has_many :read_marks, :dependent => :delete_all, as: :reader, :inverse_of => :reader
13
+ has_many :read_marks, dependent: :delete_all, as: :reader, inverse_of: :reader
14
14
 
15
15
  after_create :setup_new_reader
16
16
 
@@ -28,10 +28,10 @@ module Unread
28
28
  unless ReadMark.readable_classes.include?(self)
29
29
  class_attribute :readable_options
30
30
 
31
- options.reverse_merge!(:on => :updated_at)
31
+ options.reverse_merge!(on: :updated_at)
32
32
  self.readable_options = options
33
33
 
34
- has_many :read_marks, :as => :readable, :dependent => :delete_all, inverse_of: :readable
34
+ has_many :read_marks, as: :readable, dependent: :delete_all, inverse_of: :readable
35
35
 
36
36
  ReadMark.readable_classes << self
37
37
 
@@ -7,7 +7,7 @@ module Unread
7
7
 
8
8
  def run!
9
9
  ReadMark.reader_classes.each do |reader_class|
10
- readers_to_cleanup(reader_class).each do |reader|
10
+ readers_to_cleanup(reader_class).find_each do |reader|
11
11
  if oldest_timestamp = readable_class.read_scope(reader).
12
12
  unread_by(reader).
13
13
  minimum(readable_class.readable_options[:on])
@@ -29,16 +29,17 @@ module Unread
29
29
  reader_class.
30
30
  reader_scope.
31
31
  joins(:read_marks).
32
- where(ReadMark.table_name => { :readable_type => readable_class.name }).
32
+ where(ReadMark.table_name => { readable_type: readable_class.name }).
33
33
  group("#{ReadMark.quoted_table_name}.reader_type, #{ReadMark.quoted_table_name}.reader_id, #{reader_class.quoted_table_name}.#{reader_class.quoted_primary_key}").
34
- having("COUNT(#{ReadMark.quoted_table_name}.id) > 1")
34
+ having("COUNT(#{ReadMark.quoted_table_name}.id) > 1").
35
+ select("#{reader_class.quoted_table_name}.#{reader_class.quoted_primary_key}")
35
36
  end
36
37
 
37
38
  def update_read_marks_for_user(reader, timestamp)
38
39
  ReadMark.transaction do
39
40
  # Delete markers OLDER than the given timestamp
40
41
  reader.read_marks.
41
- where(:readable_type => readable_class.name).
42
+ where(readable_type: readable_class.name).
42
43
  single.
43
44
  older_than(timestamp).
44
45
  delete_all
@@ -1,9 +1,9 @@
1
1
  class ReadMark < ActiveRecord::Base
2
- belongs_to :readable, :polymorphic => true
2
+ belongs_to :readable, polymorphic: true, inverse_of: :read_marks
3
3
 
4
4
  validates_presence_of :reader_id, :reader_type, :readable_type
5
5
 
6
- scope :global, lambda { where(:readable_id => nil) }
6
+ scope :global, lambda { where(readable_id: nil) }
7
7
  scope :single, lambda { where('readable_id IS NOT NULL') }
8
8
  scope :older_than, lambda { |timestamp| where([ 'timestamp < ?', timestamp ]) }
9
9
 
@@ -9,41 +9,58 @@ module Unread
9
9
 
10
10
  if target == :all
11
11
  reset_read_marks_for_user(reader)
12
- elsif target.is_a?(Array)
13
- mark_array_as_read(target, reader)
12
+ elsif target.respond_to?(:each)
13
+ mark_collection_as_read(target, reader)
14
14
  else
15
15
  raise ArgumentError
16
16
  end
17
17
  end
18
18
 
19
- def mark_array_as_read(array, reader)
19
+ def mark_collection_as_read(collection, reader)
20
20
  ReadMark.transaction do
21
21
  global_timestamp = reader.read_mark_global(self).try(:timestamp)
22
22
 
23
- array.each do |obj|
23
+ collection.each do |obj|
24
24
  raise ArgumentError unless obj.is_a?(self)
25
25
  timestamp = obj.send(readable_options[:on])
26
26
 
27
27
  if global_timestamp && global_timestamp >= timestamp
28
28
  # The object is implicitly marked as read, so there is nothing to do
29
29
  else
30
- # This transaction is needed, so that parent transaction won't rollback even there's an error.
31
- ReadMark.transaction(requires_new: true) do
32
- begin
33
- rm = obj.read_marks.where(reader_id: reader.id, reader_type: reader.class.base_class.name).first || obj.read_marks.build
34
- rm.reader_id = reader.id
35
- rm.reader_type = reader.class.base_class.name
36
- rm.timestamp = timestamp
37
- rm.save!
38
- rescue ActiveRecord::RecordNotUnique
39
- raise ActiveRecord::Rollback
40
- end
41
- end
30
+ mark_collection_item_as_read(obj, reader, timestamp)
42
31
  end
43
32
  end
44
33
  end
45
34
  end
46
35
 
36
+ def mark_collection_item_as_read(obj, reader, timestamp)
37
+ marking_proc = proc {
38
+ rm = obj.read_marks.find_or_initialize_by(reader: reader)
39
+ rm.timestamp = timestamp
40
+ rm.save!
41
+ }
42
+
43
+ if using_postgresql?
44
+ # With PostgreSQL, a transaction is unusable after a unique constraint vialoation.
45
+ # To avoid this, nested transactions are required.
46
+ # http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html#module-ActiveRecord::Transactions::ClassMethods-label-Exception+handling+and+rolling+back
47
+ ReadMark.transaction(requires_new: true) do
48
+ begin
49
+ marking_proc.call
50
+ rescue ActiveRecord::RecordNotUnique
51
+ # The object is explicitly marked as read, so rollback the inner transaction
52
+ raise ActiveRecord::Rollback
53
+ end
54
+ end
55
+ else
56
+ begin
57
+ marking_proc.call
58
+ rescue ActiveRecord::RecordNotUnique
59
+ # The object is explicitly marked as read, so there is nothing to do
60
+ end
61
+ end
62
+ end
63
+
47
64
  # A scope with all items accessable for the given reader
48
65
  # It's used in cleanup_read_marks! to support a filtered cleanup
49
66
  # Should be overriden if a reader doesn't have access to all items
@@ -70,7 +87,7 @@ module Unread
70
87
  assert_reader(reader)
71
88
 
72
89
  ReadMark.transaction do
73
- reader.read_marks.where(:readable_type => self.readable_parent.name).delete_all
90
+ reader.read_marks.where(readable_type: self.readable_parent.name).delete_all
74
91
  rm = reader.read_marks.new
75
92
  rm.readable_type = self.readable_parent.name
76
93
  rm.timestamp = Time.current
@@ -123,12 +140,12 @@ module Unread
123
140
  end
124
141
  end
125
142
 
143
+ private
144
+
126
145
  def read_mark(reader)
127
- read_marks.where(:reader_id => reader.id, reader_type: reader.class.base_class.name).first
146
+ read_marks.where(reader_id: reader.id, reader_type: reader.class.base_class.name).first
128
147
  end
129
148
 
130
- private
131
-
132
149
  def read_mark_id_belongs_to?(reader)
133
150
  self.read_mark_reader_id.to_i == reader.id &&
134
151
  self.read_mark_reader_type == reader.class.base_class.name
@@ -16,7 +16,7 @@ module Unread
16
16
  def read_mark_global(klass)
17
17
  @read_mark_global ||= {}
18
18
  readable_klass = klass.readable_parent
19
- @read_mark_global[readable_klass] ||= read_marks.where(:readable_type => readable_klass.name).global.first
19
+ @read_mark_global[readable_klass] ||= read_marks.where(readable_type: readable_klass.name).global.first
20
20
  end
21
21
 
22
22
  def forget_memoized_read_mark_global
@@ -44,7 +44,7 @@ module Unread
44
44
  # If you don't want this, you can override this method in your reader class
45
45
  def setup_new_reader
46
46
  (ReadMark.readable_classes || []).each do |klass|
47
- klass.mark_as_read! :all, :for => self
47
+ klass.mark_as_read! :all, for: self
48
48
  end
49
49
  end
50
50
  end
@@ -1,3 +1,3 @@
1
1
  module Unread
2
- VERSION = '0.9.1'
2
+ VERSION = '0.10.0'
3
3
  end
@@ -1,4 +1,4 @@
1
1
  class Document < ActiveRecord::Base
2
2
  self.primary_key = 'uid'
3
- acts_as_readable :on => :updated_at
3
+ acts_as_readable on: :updated_at
4
4
  end
@@ -1,18 +1,18 @@
1
1
  class SpecMigration < Unread::MIGRATION_BASE_CLASS
2
2
  def self.up
3
- create_table Reader, :primary_key => 'number', :force => true do |t|
3
+ create_table Reader, primary_key: 'number', force: true do |t|
4
4
  t.string :name
5
5
  end
6
6
 
7
- create_table DifferentReader, :primary_key => 'number', :force => true do |t|
7
+ create_table DifferentReader, primary_key: 'number', force: true do |t|
8
8
  t.string :name
9
9
  end
10
10
 
11
- create_table Customer, :force => true do |t|
11
+ create_table Customer, force: true do |t|
12
12
  t.string :type
13
13
  end
14
14
 
15
- create_table Document, :primary_key => 'uid', :force => true do |t|
15
+ create_table Document, primary_key: 'uid', force: true do |t|
16
16
  t.string :type
17
17
  t.string :subject
18
18
  t.text :content
@@ -1,3 +1,3 @@
1
1
  def wait
2
- Timecop.freeze(1.minute.from_now.change(:usec => 0))
2
+ Timecop.freeze(1.minute.from_now.change(usec: 0))
3
3
  end
@@ -4,7 +4,7 @@ describe Unread::Base do
4
4
  before :each do
5
5
  @email = Email.create!
6
6
  wait
7
- @reader = Reader.create! :name => 'John'
7
+ @reader = Reader.create! name: 'John'
8
8
  end
9
9
 
10
10
  describe :acts_as_reader do
@@ -47,7 +47,7 @@ describe Unread::Base do
47
47
  end
48
48
 
49
49
  it "should use default options" do
50
- expect(Email.readable_options).to eq({ :on => :updated_at })
50
+ expect(Email.readable_options).to eq({ on: :updated_at })
51
51
  end
52
52
 
53
53
  it "should be idempotent" do
@@ -2,8 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  describe Unread::GarbageCollector do
4
4
  before :each do
5
- @reader = Reader.create! :name => 'David'
6
- @other_reader = Reader.create :name => 'Matz'
5
+ @reader = Reader.create! name: 'David'
6
+ @other_reader = Reader.create name: 'Matz'
7
7
  @sti_reader = StiReader.create!
8
8
  wait
9
9
  @email1 = Email.create!
@@ -15,7 +15,7 @@ describe Unread::GarbageCollector do
15
15
  it "should delete all single read marks" do
16
16
  expect(@reader.read_marks.single.count).to eq 0
17
17
 
18
- @email1.mark_as_read! :for => @reader
18
+ @email1.mark_as_read! for: @reader
19
19
 
20
20
  expect(Email.unread_by(@reader)).to eq [@email2]
21
21
  expect(@reader.read_marks.single.count).to eq 1
@@ -27,8 +27,8 @@ describe Unread::GarbageCollector do
27
27
  end
28
28
 
29
29
  it "should reset if all objects are read" do
30
- @email1.mark_as_read! :for => @reader
31
- @email2.mark_as_read! :for => @reader
30
+ @email1.mark_as_read! for: @reader
31
+ @email2.mark_as_read! for: @reader
32
32
 
33
33
  expect(@reader.read_marks.single.count).to eq 2
34
34
 
@@ -2,8 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  describe Unread::Readable do
4
4
  before :each do
5
- @reader = Reader.create! :name => 'David'
6
- @other_reader = Reader.create :name => 'Matz'
5
+ @reader = Reader.create! name: 'David'
6
+ @other_reader = Reader.create name: 'Matz'
7
7
  @sti_reader = StiReader.create!
8
8
  wait
9
9
  @email1 = Email.create!
@@ -18,7 +18,7 @@ describe Unread::Readable do
18
18
  end
19
19
 
20
20
  it "should return unread records" do
21
- @email1.mark_as_read! :for => @reader
21
+ @email1.mark_as_read! for: @reader
22
22
 
23
23
  expect(Email.unread_by(@reader)).to eq [@email2]
24
24
  expect(Email.unread_by(@reader).count).to eq 1
@@ -27,7 +27,7 @@ describe Unread::Readable do
27
27
  end
28
28
 
29
29
  it "should return empty array directly after marking all as read" do
30
- Email.mark_as_read! :all, :for => @reader
30
+ Email.mark_as_read! :all, for: @reader
31
31
  expect(Email.unread_by(@reader)).to eq([])
32
32
  end
33
33
 
@@ -58,7 +58,7 @@ describe Unread::Readable do
58
58
  end
59
59
 
60
60
  it "should return unread records" do
61
- @email1.mark_as_read! :for => @reader
61
+ @email1.mark_as_read! for: @reader
62
62
 
63
63
  expect(Email.unread_by(@reader)).to eq [@email2]
64
64
  expect(Email.unread_by(@reader).count).to eq 1
@@ -89,14 +89,14 @@ describe Unread::Readable do
89
89
  end
90
90
 
91
91
  it "should return read records" do
92
- @email1.mark_as_read! :for => @reader
92
+ @email1.mark_as_read! for: @reader
93
93
 
94
94
  expect(Email.read_by(@reader)).to eq [@email1]
95
95
  expect(Email.read_by(@reader).count).to eq 1
96
96
  end
97
97
 
98
98
  it "should return all records when all read" do
99
- Email.mark_as_read! :all, :for => @reader
99
+ Email.mark_as_read! :all, for: @reader
100
100
 
101
101
  expect(Email.read_by(@reader)).to eq [@email1, @email2]
102
102
  end
@@ -128,14 +128,14 @@ describe Unread::Readable do
128
128
  end
129
129
 
130
130
  it "should return read records" do
131
- @email1.mark_as_read! :for => @reader
131
+ @email1.mark_as_read! for: @reader
132
132
 
133
133
  expect(Email.read_by(@reader)).to eq [@email1]
134
134
  expect(Email.read_by(@reader).count).to eq 1
135
135
  end
136
136
 
137
137
  it "should return all records when all read" do
138
- Email.mark_as_read! :all, :for => @reader
138
+ Email.mark_as_read! :all, for: @reader
139
139
 
140
140
  expect(Email.read_by(@reader)).to eq [@email1, @email2]
141
141
  end
@@ -191,11 +191,11 @@ describe Unread::Readable do
191
191
  end
192
192
 
193
193
  it "should handle updating object" do
194
- @email1.mark_as_read! :for => @reader
194
+ @email1.mark_as_read! for: @reader
195
195
  wait
196
196
  expect(@email1.unread?(@reader)).to be_falsey
197
197
 
198
- @email1.update_attributes! :subject => 'changed'
198
+ @email1.update_attributes! subject: 'changed'
199
199
  expect(@email1.unread?(@reader)).to be_truthy
200
200
  end
201
201
 
@@ -206,7 +206,7 @@ describe Unread::Readable do
206
206
  end
207
207
 
208
208
  it "should work with eager-loaded read marks" do
209
- @email1.mark_as_read! :for => @reader
209
+ @email1.mark_as_read! for: @reader
210
210
 
211
211
  expect {
212
212
  emails = Email.with_read_marks_for(@reader).to_a
@@ -225,7 +225,7 @@ describe Unread::Readable do
225
225
  end
226
226
 
227
227
  it "should work with eager-loaded read marks for the correct reader" do
228
- @email1.mark_as_read! :for => @reader
228
+ @email1.mark_as_read! for: @reader
229
229
 
230
230
  emails = Email.with_read_marks_for(@reader).to_a
231
231
  expect(emails[0].unread?(@reader)).to be_falsey
@@ -235,7 +235,7 @@ describe Unread::Readable do
235
235
 
236
236
  describe '#mark_as_read!' do
237
237
  it "should mark a single object as read" do
238
- @email1.mark_as_read! :for => @reader
238
+ @email1.mark_as_read! for: @reader
239
239
 
240
240
  expect(@email1.unread?(@reader)).to be_falsey
241
241
  expect(Email.unread_by(@reader)).to eq [@email2]
@@ -248,8 +248,8 @@ describe Unread::Readable do
248
248
  end
249
249
 
250
250
  it "should be idempotent" do
251
- @email1.mark_as_read! :for => @reader
252
- @email1.mark_as_read! :for => @reader
251
+ @email1.mark_as_read! for: @reader
252
+ @email1.mark_as_read! for: @reader
253
253
 
254
254
  expect(@reader.read_marks.single.count).to eq 1
255
255
  end
@@ -260,7 +260,7 @@ describe Unread::Readable do
260
260
  expect(@email1.unread?(@reader)).to be_truthy
261
261
  expect(@email2.unread?(@reader)).to be_truthy
262
262
 
263
- Email.mark_as_read! [ @email1, @email2 ], :for => @reader
263
+ Email.mark_as_read! [ @email1, @email2 ], for: @reader
264
264
 
265
265
  expect(@email1.unread?(@reader)).to be_falsey
266
266
  expect(@email2.unread?(@reader)).to be_falsey
@@ -269,8 +269,8 @@ describe Unread::Readable do
269
269
  it "should mark the rest as read when the first record is not unique" do
270
270
  Email.mark_as_read! [ @email1 ], for: @reader
271
271
 
272
- allow(@email1).to receive_message_chain("read_marks.build").and_return(@email1.read_marks.build)
273
- allow(@email1).to receive_message_chain("read_marks.where").and_return([])
272
+ allow(@email1).to receive_message_chain("read_marks.find_or_initialize_by")
273
+ .and_return(@email1.read_marks.build(reader: @reader))
274
274
 
275
275
  expect do
276
276
  Email.mark_as_read! [ @email1, @email2 ], for: @reader
@@ -281,15 +281,22 @@ describe Unread::Readable do
281
281
  end
282
282
 
283
283
  it "should perform less queries if the objects are already read" do
284
- Email.mark_as_read! :all, :for => @reader
284
+ Email.mark_as_read! :all, for: @reader
285
285
 
286
286
  expect {
287
- Email.mark_as_read! [ @email1, @email2 ], :for => @reader
287
+ Email.mark_as_read! [ @email1, @email2 ], for: @reader
288
288
  }.to perform_queries(1)
289
289
  end
290
290
 
291
+ it "should allow a collection of records to be marked as read" do
292
+ Email.mark_as_read! Email.all, for: @reader
293
+
294
+ expect(@email1.unread?(@reader)).to be_falsey
295
+ expect(@email2.unread?(@reader)).to be_falsey
296
+ end
297
+
291
298
  it "should mark all objects as read" do
292
- Email.mark_as_read! :all, :for => @reader
299
+ Email.mark_as_read! :all, for: @reader
293
300
 
294
301
  expect(@reader.read_mark_global(Email).timestamp).to eq Time.current
295
302
  expect(@reader.read_marks.single).to eq []
@@ -300,8 +307,8 @@ describe Unread::Readable do
300
307
  it "should mark all objects as read with existing read objects" do
301
308
  wait
302
309
 
303
- Email.mark_as_read! :all, :for => @reader
304
- @email1.mark_as_read! :for => @reader
310
+ Email.mark_as_read! :all, for: @reader
311
+ @email1.mark_as_read! for: @reader
305
312
 
306
313
  expect(@reader.read_marks.single).to eq []
307
314
  end
@@ -309,19 +316,24 @@ describe Unread::Readable do
309
316
  it "should reset memoized global read mark" do
310
317
  rm_global = @reader.read_mark_global(Email)
311
318
 
312
- Email.mark_as_read! :all, :for => @reader
319
+ Email.mark_as_read! :all, for: @reader
313
320
  expect(@reader.read_mark_global(Email)).not_to eq(rm_global)
314
321
  end
315
322
 
316
323
  it "should not allow invalid arguments" do
317
324
  expect {
318
- Email.mark_as_read! :foo, :for => @reader
325
+ Email.mark_as_read! :foo, for: @reader
319
326
  }.to raise_error(ArgumentError)
320
327
 
321
328
  expect {
322
329
  Email.mark_as_read! :foo, :bar
323
330
  }.to raise_error(ArgumentError)
324
331
  end
332
+
333
+ it "should work with STI readers" do
334
+ Email.mark_as_read! [ @email1 ], for: Customer.find(@sti_reader.id)
335
+ expect(@email1.unread?(@sti_reader)).to be_falsey
336
+ end
325
337
  end
326
338
 
327
339
  describe :cleanup_read_marks! do
@@ -2,9 +2,9 @@ require 'spec_helper'
2
2
 
3
3
  describe Unread::Reader do
4
4
  before :each do
5
- @reader = Reader.create! :name => 'David'
6
- @other_reader = Reader.create :name => 'Matz'
7
- @different_reader = DifferentReader.create! :name => 'Behrooz', :number => @reader.number
5
+ @reader = Reader.create! name: 'David'
6
+ @other_reader = Reader.create name: 'Matz'
7
+ @different_reader = DifferentReader.create! name: 'Behrooz', number: @reader.number
8
8
  wait
9
9
  @email1 = Email.create!
10
10
  wait
@@ -18,7 +18,7 @@ describe Unread::Reader do
18
18
  end
19
19
 
20
20
  it "should return *only* the readers that have not read a given object" do
21
- @email1.mark_as_read! :for => @reader
21
+ @email1.mark_as_read! for: @reader
22
22
 
23
23
  expect(Reader.have_not_read(@email1)).to eq [@other_reader]
24
24
  expect(Reader.have_not_read(@email1).count).to eq 1
@@ -30,7 +30,7 @@ describe Unread::Reader do
30
30
  # even though the id of @reader and @different_reader is the same because
31
31
  # they are different object types, the @email1 should only be marked as
32
32
  # read for @reader.
33
- @email1.mark_as_read! :for => @reader
33
+ @email1.mark_as_read! for: @reader
34
34
 
35
35
  expect(Reader.have_not_read(@email1)).to eq [@other_reader]
36
36
  expect(Reader.have_not_read(@email1).count).to eq 1
@@ -38,7 +38,7 @@ describe Unread::Reader do
38
38
  expect(DifferentReader.have_not_read(@email1)).to eq [@different_reader]
39
39
  expect(DifferentReader.have_not_read(@email1).count).to eq 1
40
40
 
41
- @email1.mark_as_read! :for => @different_reader
41
+ @email1.mark_as_read! for: @different_reader
42
42
 
43
43
  expect(DifferentReader.have_not_read(@email1).count).to eq 0
44
44
 
@@ -69,7 +69,7 @@ describe Unread::Reader do
69
69
  end
70
70
 
71
71
  it "should return *only* the readers that have read the given object" do
72
- @email1.mark_as_read! :for => @reader
72
+ @email1.mark_as_read! for: @reader
73
73
 
74
74
  expect(Reader.have_read(@email1)).to eq [@reader]
75
75
  expect(Reader.have_read(@email1).count).to eq 1
@@ -78,7 +78,7 @@ describe Unread::Reader do
78
78
  end
79
79
 
80
80
  it "should return the reader for all the object when all read" do
81
- Email.mark_as_read! :all, :for => @reader
81
+ Email.mark_as_read! :all, for: @reader
82
82
 
83
83
  expect(Reader.have_read(@email1)).to eq [@reader]
84
84
  expect(Reader.have_read(@email1).count).to eq 1
@@ -145,11 +145,11 @@ describe Unread::Reader do
145
145
  end
146
146
 
147
147
  it "should handle updating object" do
148
- @email1.mark_as_read! :for => @reader
148
+ @email1.mark_as_read! for: @reader
149
149
  wait
150
150
  expect(@reader.have_read?(@email1)).to be_truthy
151
151
 
152
- @email1.update_attributes! :subject => 'changed'
152
+ @email1.update_attributes! subject: 'changed'
153
153
  expect(@reader.have_read?(@email1)).to be_falsey
154
154
  end
155
155
 
@@ -160,7 +160,7 @@ describe Unread::Reader do
160
160
  end
161
161
 
162
162
  it "should work with eager-loaded read marks" do
163
- @email1.mark_as_read! :for => @reader
163
+ @email1.mark_as_read! for: @reader
164
164
 
165
165
  expect {
166
166
  readers = Reader.with_read_marks_for(@email1).to_a
@@ -171,7 +171,7 @@ describe Unread::Reader do
171
171
  end
172
172
 
173
173
  it "should work with eager-loaded read marks for the correct readable" do
174
- @email1.mark_as_read! :for => @reader
174
+ @email1.mark_as_read! for: @reader
175
175
 
176
176
  readers = Reader.with_read_marks_for(@email1).to_a
177
177
  expect(readers[0].have_read?(@email1)).to be_truthy
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.homepage = "https://github.com/ledermann/unread"
12
12
  s.summary = %q{Manages read/unread status of ActiveRecord objects}
13
13
  s.description = %q{This gem creates a scope for unread objects and adds methods to mark objects as read }
14
- s.required_ruby_version = '>= 2.0.0'
14
+ s.required_ruby_version = '>= 2.2'
15
15
 
16
16
  s.rubyforge_project = "unread"
17
17
 
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.add_development_dependency 'timecop'
27
27
  s.add_development_dependency 'sqlite3'
28
28
  s.add_development_dependency 'mysql2'
29
- s.add_development_dependency 'pg'
29
+ s.add_development_dependency 'pg', '< 1'
30
30
  s.add_development_dependency 'rspec'
31
31
  s.add_development_dependency 'simplecov'
32
32
  s.add_development_dependency 'term-ansicolor'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unread
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Georg Ledermann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-29 00:00:00.000000000 Z
11
+ date: 2018-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -84,16 +84,16 @@ dependencies:
84
84
  name: pg
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "<"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '1'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "<"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '1'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rspec
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -182,14 +182,12 @@ files:
182
182
  - Rakefile
183
183
  - UPGRADE.md
184
184
  - bin/console
185
- - gemfiles/rails_3_0.gemfile
186
- - gemfiles/rails_3_1.gemfile
187
- - gemfiles/rails_3_2.gemfile
188
185
  - gemfiles/rails_4_0.gemfile
189
186
  - gemfiles/rails_4_1.gemfile
190
187
  - gemfiles/rails_4_2.gemfile
191
188
  - gemfiles/rails_5_0.gemfile
192
189
  - gemfiles/rails_5_1.gemfile
190
+ - gemfiles/rails_5_2.gemfile
193
191
  - lib/generators/unread/migration/migration_generator.rb
194
192
  - lib/generators/unread/migration/templates/migration.rb
195
193
  - lib/generators/unread/polymorphic_reader_migration/polymorphic_reader_migration_generator.rb
@@ -235,7 +233,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
235
233
  requirements:
236
234
  - - ">="
237
235
  - !ruby/object:Gem::Version
238
- version: 2.0.0
236
+ version: '2.2'
239
237
  required_rubygems_version: !ruby/object:Gem::Requirement
240
238
  requirements:
241
239
  - - ">="
@@ -243,7 +241,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
243
241
  version: '0'
244
242
  requirements: []
245
243
  rubyforge_project: unread
246
- rubygems_version: 2.6.11
244
+ rubygems_version: 2.7.5
247
245
  signing_key:
248
246
  specification_version: 4
249
247
  summary: Manages read/unread status of ActiveRecord objects
@@ -1,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 3.1.12"
6
- gem "mysql2", "~> 0.3.10"
7
-
8
- gemspec path: "../"
@@ -1,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 3.2.22"
6
- gem "mysql2", "~> 0.3.10"
7
-
8
- gemspec path: "../"