unread 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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: "../"