unread 0.3.1 → 0.4.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
2
  SHA1:
3
- metadata.gz: 22da2f765c42c94461c4bf67560a057ed1f76d8f
4
- data.tar.gz: 3d45b07e1d0fc2a3af20b81a8a8fa0b1ff2bf9de
3
+ metadata.gz: 62f6d5dbe191941fe9f5b358318fefbf93ad0c20
4
+ data.tar.gz: 80e1d361fc919f39f33142283b2dfe8d1d9376a1
5
5
  SHA512:
6
- metadata.gz: c51a5ad38b6a49467f3f3d542e06177c9ea3226cadd1001b66f407bea2f1edf65d7f45bad871184697b526938e62a08905e1e44cb154288eb37a886396d5f53a
7
- data.tar.gz: 53b3e25c4723f78121aa3a1f066a68c91b462cbc3a56f5489ac416ba58cb7bb4ea917bc3c174c4b25a852dee4228c10e90c7c054da2f16ceb73b1e5044e79b1b
6
+ metadata.gz: 8808316873efd20db90cb45b9bbf14e4bc6fb3336f69d3f2480bfe8feaee04a21c39a44672d28c892e6365ceb26440525c36283e27d6508baec32f8e2aa72246
7
+ data.tar.gz: a55db92bee6d0b5969cb244655137e08afc7438a8abedbcb65f92a44d05c77ce60dad18d677e64c745b3b831063e08a5076773d717773d30a1685f74d2735f1e
data/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ coverage/*
@@ -2,8 +2,11 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
+ - 2.1.1
5
6
  gemfile:
6
7
  - ci/Gemfile-rails-3-0
7
8
  - ci/Gemfile-rails-3-1
8
9
  - ci/Gemfile-rails-3-2
9
10
  - ci/Gemfile-rails-4-0
11
+ - ci/Gemfile-rails-4-1
12
+ before_install: gem update bundler
@@ -1,4 +1,6 @@
1
- Copyright (c) 2010,2013 Georg Ledermann
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2010-2014 Georg Ledermann
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining
4
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -5,6 +5,8 @@ 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.png?branch=master)](https://travis-ci.org/ledermann/unread)
7
7
  [![Code Climate](https://codeclimate.com/github/ledermann/unread.png)](https://codeclimate.com/github/ledermann/unread)
8
+ [![Coverage Status](https://coveralls.io/repos/ledermann/unread/badge.png)](https://coveralls.io/r/ledermann/unread)
9
+
8
10
 
9
11
  ## Features
10
12
 
@@ -18,11 +20,16 @@ Ruby gem to manage read/unread status of ActiveRecord objects - and it's fast.
18
20
 
19
21
  ## Requirements
20
22
 
21
- * Ruby 1.9.3 or 2.0.0
23
+ * Ruby 1.9.3 or newer
22
24
  * Rails 3 (including 3.0, 3.1, 3.2) and Rails 4. For use with Rails 2.3 there is a branch named "rails2"
23
25
  * Needs a timestamp field in your models (like created_at or updated_at) with a database index on it
24
26
 
25
27
 
28
+ ## Changelog
29
+
30
+ https://github.com/ledermann/unread/releases
31
+
32
+
26
33
  ## Installation
27
34
 
28
35
  Step 1: Add this to your Gemfile:
@@ -133,4 +140,4 @@ There are two other gems/plugins doing a similar job:
133
140
  Unfortunately, both of them have a lack of performance, because they calculate the unread records doing a `find(:all)`, which should be avoided for a large amount of records. This gem is based on a timestamp algorithm and therefore it's very fast.
134
141
 
135
142
 
136
- Copyright (c) 2010-2013 [Georg Ledermann](http://www.georg-ledermann.de), released under the MIT license
143
+ Copyright (c) 2010-2014 [Georg Ledermann](http://www.georg-ledermann.de), released under the MIT license
data/Rakefile CHANGED
@@ -1,15 +1,6 @@
1
1
  require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
2
3
 
3
- require 'rake'
4
- require 'rake/testtask'
4
+ RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- desc 'Default: run unit tests.'
7
- task :default => :test
8
-
9
- desc 'Test the unread plugin.'
10
- Rake::TestTask.new(:test) do |t|
11
- t.libs << 'lib'
12
- t.libs << 'test'
13
- t.pattern = 'test/**/*_test.rb'
14
- t.verbose = true
15
- end
6
+ task :default => :spec
@@ -1,6 +1,9 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'activerecord', '~> 3.0.10'
3
+ gem 'activerecord', '~> 3.0.20'
4
4
  gem 'sqlite3'
5
5
  gem 'timecop'
6
6
  gem 'rake'
7
+ gem 'rspec'
8
+ gem 'simplecov'
9
+ gem 'coveralls'
@@ -1,6 +1,9 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'activerecord', '~> 3.1.1'
3
+ gem 'activerecord', '~> 3.1.12'
4
4
  gem 'sqlite3'
5
5
  gem 'timecop'
6
6
  gem 'rake'
7
+ gem 'rspec'
8
+ gem 'simplecov'
9
+ gem 'coveralls'
@@ -1,6 +1,9 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'activerecord', '~> 3.2.1'
3
+ gem 'activerecord', '~> 3.2.17'
4
4
  gem 'sqlite3'
5
5
  gem 'timecop'
6
6
  gem 'rake'
7
+ gem 'rspec'
8
+ gem 'simplecov'
9
+ gem 'coveralls'
@@ -1,6 +1,9 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'activerecord', '4.0.0.rc1'
3
+ gem 'activerecord', '~> 4.0.4'
4
4
  gem 'sqlite3'
5
5
  gem 'timecop'
6
6
  gem 'rake'
7
+ gem 'rspec'
8
+ gem 'simplecov'
9
+ gem 'coveralls'
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 4.1.0'
4
+ gem 'sqlite3'
5
+ gem 'timecop'
6
+ gem 'rake'
7
+ gem 'rspec'
8
+ gem 'simplecov'
9
+ gem 'coveralls'
@@ -9,7 +9,7 @@ module Unread
9
9
  source_root File.expand_path('../templates', __FILE__)
10
10
 
11
11
  def create_migration_file
12
- migration_template 'migration.rb', 'db/migrate/unread_migration'
12
+ migration_template 'migration.rb', 'db/migrate/unread_migration.rb'
13
13
  end
14
14
 
15
15
  def self.next_migration_number(dirname)
@@ -2,6 +2,8 @@ module Unread
2
2
  module Readable
3
3
  module ClassMethods
4
4
  def mark_as_read!(target, options)
5
+ raise ArgumentError unless options.is_a?(Hash)
6
+
5
7
  user = options[:for]
6
8
  assert_reader(user)
7
9
 
@@ -70,7 +72,7 @@ module Unread
70
72
  ReadMark.transaction do
71
73
  ReadMark.delete_all :readable_type => self.base_class.name
72
74
  ReadMark.connection.execute <<-EOT
73
- INSERT INTO read_marks (user_id, readable_type, timestamp)
75
+ INSERT INTO #{ReadMark.table_name} (user_id, readable_type, timestamp)
74
76
  SELECT #{ReadMark.reader_class.primary_key}, '#{self.base_class.name}', '#{Time.current.to_s(:db)}'
75
77
  FROM #{ReadMark.reader_class.table_name}
76
78
  EOT
@@ -4,7 +4,7 @@ module Unread
4
4
  def join_read_marks(user)
5
5
  assert_reader(user)
6
6
 
7
- joins "LEFT JOIN read_marks ON read_marks.readable_type = '#{base_class.name}'
7
+ joins "LEFT JOIN #{ReadMark.table_name} as read_marks ON read_marks.readable_type = '#{base_class.name}'
8
8
  AND read_marks.readable_id = #{table_name}.#{primary_key}
9
9
  AND read_marks.user_id = #{user.id}
10
10
  AND read_marks.timestamp >= #{table_name}.#{readable_options[:on]}"
@@ -1,3 +1,3 @@
1
1
  module Unread
2
- VERSION = '0.3.1'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unread::Base do
4
+ before :each do
5
+ @email = Email.create!
6
+ wait
7
+ @reader = Reader.create! :name => 'John'
8
+ end
9
+
10
+ describe :acts_as_reader do
11
+ it "should create global read mark" do
12
+ expect(@reader.read_marks.count).to eq 1
13
+ expect(@reader.read_marks.global.count).to eq 1
14
+ end
15
+
16
+ it "should define association for ReadMark" do
17
+ expect(@reader.read_marks.first.user).to eq(@reader)
18
+ end
19
+
20
+ it "should reset read_marks for created reader" do
21
+ expect(Email.unread_by(@reader)).to be_empty
22
+ end
23
+ end
24
+
25
+ describe :acts_as_readable do
26
+ it "should define association" do
27
+ expect(@email.read_marks.count).to eq 0
28
+ end
29
+
30
+ it "should add class to ReadMark.readable_classes" do
31
+ expect(ReadMark.readable_classes).to eq [ Email ]
32
+ end
33
+
34
+ it "should use default options" do
35
+ expect(Email.readable_options).to eq({ :on => :updated_at })
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,4 @@
1
+ class Email < ActiveRecord::Base
2
+ self.primary_key = 'messageid'
3
+ acts_as_readable :on => :updated_at
4
+ end
@@ -0,0 +1,4 @@
1
+ class Reader < ActiveRecord::Base
2
+ self.primary_key = 'number'
3
+ acts_as_reader
4
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe ReadMark do
4
+ it "should have reader_class" do
5
+ expect(ReadMark.reader_class).to eq Reader
6
+ end
7
+ end
@@ -0,0 +1,206 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unread::Readable do
4
+ before :each do
5
+ @reader = Reader.create! :name => 'David'
6
+ @other_reader = Reader.create :name => 'Matz'
7
+ wait
8
+ @email1 = Email.create!
9
+ wait
10
+ @email2 = Email.create!
11
+ end
12
+
13
+ describe :unread_by do
14
+ it "should return all objects" do
15
+ expect(Email.unread_by(@reader)).to eq [@email1, @email2]
16
+ expect(Email.unread_by(@other_reader)).to eq [@email1, @email2]
17
+ end
18
+
19
+ it "should return unread records" do
20
+ @email1.mark_as_read! :for => @reader
21
+
22
+ expect(Email.unread_by(@reader)).to eq [@email2]
23
+ expect(Email.unread_by(@reader).count).to eq 1
24
+ end
25
+
26
+ it "should not allow invalid parameter" do
27
+ [ 42, nil, 'foo', :foo, {} ].each do |not_a_reader|
28
+ expect {
29
+ Email.unread_by(not_a_reader)
30
+ }.to raise_error(ArgumentError)
31
+ end
32
+ end
33
+
34
+ it "should not allow unsaved reader" do
35
+ unsaved_reader = Reader.new
36
+
37
+ expect {
38
+ Email.unread_by(unsaved_reader)
39
+ }.to raise_error(ArgumentError)
40
+ end
41
+ end
42
+
43
+ describe :with_read_marks_for do
44
+ it "should return readables" do
45
+ expect(Email.with_read_marks_for(@reader).to_a).to eq([@email1, @email2])
46
+ end
47
+
48
+ it "should be countable" do
49
+ expect(Email.with_read_marks_for(@reader).count(:messageid)).to eq(2)
50
+ end
51
+
52
+ it "should not allow invalid parameter" do
53
+ [ 42, nil, 'foo', :foo, {} ].each do |not_a_reader|
54
+ expect {
55
+ Email.with_read_marks_for(not_a_reader)
56
+ }.to raise_error(ArgumentError)
57
+ end
58
+ end
59
+
60
+ it "should not allow unsaved reader" do
61
+ unsaved_reader = Reader.new
62
+
63
+ expect {
64
+ Email.with_read_marks_for(unsaved_reader)
65
+ }.to raise_error(ArgumentError)
66
+ end
67
+ end
68
+
69
+ describe :unread? do
70
+ it "should recognize unread object" do
71
+ expect(@email1.unread?(@reader)).to be_truthy
72
+ expect(@email1.unread?(@other_reader)).to be_truthy
73
+ end
74
+
75
+ it "should handle updating object" do
76
+ @email1.mark_as_read! :for => @reader
77
+ wait
78
+ expect(@email1.unread?(@reader)).to be_falsey
79
+
80
+ @email1.update_attributes! :subject => 'changed'
81
+ expect(@email1.unread?(@reader)).to be_truthy
82
+ end
83
+
84
+ it "should raise error for invalid argument" do
85
+ expect {
86
+ @email1.unread?(42)
87
+ }.to raise_error(ArgumentError)
88
+ end
89
+
90
+ it "should work with eager-loaded read marks" do
91
+ @email1.mark_as_read! :for => @reader
92
+
93
+ expect {
94
+ emails = Email.with_read_marks_for(@reader).to_a
95
+
96
+ expect(emails[0].unread?(@reader)).to be_falsey
97
+ expect(emails[1].unread?(@reader)).to be_truthy
98
+ }.to perform_queries(1)
99
+ end
100
+ end
101
+
102
+ describe '#mark_as_read!' do
103
+ it "should mark a single object as read" do
104
+ @email1.mark_as_read! :for => @reader
105
+
106
+ expect(@email1.unread?(@reader)).to be_falsey
107
+ expect(Email.unread_by(@reader)).to eq [@email2]
108
+
109
+ expect(@email1.unread?(@other_reader)).to be_truthy
110
+ expect(Email.unread_by(@other_reader)).to eq [@email1, @email2]
111
+
112
+ expect(@reader.read_marks.single.count).to eq 1
113
+ expect(@reader.read_marks.single.first.readable).to eq @email1
114
+ end
115
+
116
+ it "should be idempotent" do
117
+ @email1.mark_as_read! :for => @reader
118
+ @email1.mark_as_read! :for => @reader
119
+
120
+ expect(@reader.read_marks.single.count).to eq 1
121
+ end
122
+ end
123
+
124
+ describe '.mark_as_read!' do
125
+ it "should mark multi objects as read" do
126
+ expect(@email1.unread?(@reader)).to be_truthy
127
+ expect(@email2.unread?(@reader)).to be_truthy
128
+
129
+ Email.mark_as_read! [ @email1, @email2 ], :for => @reader
130
+
131
+ expect(@email1.unread?(@reader)).to be_falsey
132
+ expect(@email2.unread?(@reader)).to be_falsey
133
+ end
134
+
135
+ it "should mark all objects as read" do
136
+ Email.mark_as_read! :all, :for => @reader
137
+
138
+ expect(@reader.read_mark_global(Email).timestamp).to eq Time.current
139
+ expect(@reader.read_marks.single).to eq []
140
+ expect(ReadMark.single.count).to eq 0
141
+ expect(ReadMark.global.count).to eq 2
142
+ end
143
+
144
+ it "should mark all objects as read with existing read objects" do
145
+ wait
146
+
147
+ Email.mark_as_read! :all, :for => @reader
148
+ @email1.mark_as_read! :for => @reader
149
+
150
+ expect(@reader.read_marks.single).to eq []
151
+ end
152
+
153
+ it "should not allow invalid arguments" do
154
+ expect {
155
+ Email.mark_as_read! :foo, :for => @reader
156
+ }.to raise_error(ArgumentError)
157
+
158
+ expect {
159
+ Email.mark_as_read! :foo, :bar
160
+ }.to raise_error(ArgumentError)
161
+ end
162
+ end
163
+
164
+ describe :reset_read_marks_for_all do
165
+ it "should reset read marks" do
166
+ Email.reset_read_marks_for_all
167
+
168
+ expect(ReadMark.single.count).to eq 0
169
+ expect(ReadMark.global.count).to eq 2
170
+ end
171
+ end
172
+
173
+ describe :cleanup_read_marks! do
174
+ it "should delete all single read marks" do
175
+ expect(@reader.read_marks.single.count).to eq 0
176
+
177
+ @email1.mark_as_read! :for => @reader
178
+
179
+ expect(Email.unread_by(@reader)).to eq [@email2]
180
+ expect(@reader.read_marks.single.count).to eq 1
181
+
182
+ Email.cleanup_read_marks!
183
+
184
+ @reader.reload
185
+ expect(@reader.read_marks.single.count).to eq 0
186
+ end
187
+
188
+ it "should reset if all objects are read" do
189
+ @email1.mark_as_read! :for => @reader
190
+ @email2.mark_as_read! :for => @reader
191
+
192
+ expect(@reader.read_marks.single.count).to eq 2
193
+
194
+ Email.cleanup_read_marks!
195
+
196
+ expect(@reader.read_marks.single.count).to eq 0
197
+ end
198
+
199
+ it "should not delete read marks from other readables" do
200
+ other_read_mark = @reader.read_marks.create! :readable_type => 'Foo', :readable_id => 42, :timestamp => 5.years.ago
201
+ Email.cleanup_read_marks!
202
+
203
+ expect(ReadMark.exists?(other_read_mark.id)).to be_truthy
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,78 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ]
8
+ SimpleCov.start do
9
+ add_filter '/spec/'
10
+ end
11
+
12
+ require 'active_record'
13
+ require 'timecop'
14
+ require 'unread'
15
+
16
+ require 'model/reader'
17
+ require 'model/email'
18
+
19
+ # Requires supporting ruby files with custom matchers and macros, etc,
20
+ # in spec/support/ and its subdirectories.
21
+ Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
22
+
23
+ # This file was generated by the `rspec --init` command. Conventionally, all
24
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
25
+ # Require this file using `require "spec_helper"` to ensure that it is only
26
+ # loaded once.
27
+ #
28
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
29
+ RSpec.configure do |config|
30
+ # Run specs in random order to surface order dependencies. If you find an
31
+ # order dependency and want to debug it, you can fix the order by providing
32
+ # the seed, which is printed after each run.
33
+ # --seed 1234
34
+ # config.order = 'random'
35
+
36
+ config.before :each do
37
+ clear_db
38
+ end
39
+
40
+ config.after :each do
41
+ Timecop.return
42
+ end
43
+ end
44
+
45
+ if I18n.respond_to?(:enforce_available_locales=)
46
+ I18n.enforce_available_locales = false
47
+ end
48
+
49
+ def setup_db
50
+ puts "Testing with ActiveRecord #{ActiveRecord::VERSION::STRING}"
51
+
52
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
53
+ ActiveRecord::Migration.verbose = false
54
+
55
+ require File.expand_path('../../lib/generators/unread/migration/templates/migration.rb', __FILE__)
56
+ UnreadMigration.migrate(:up)
57
+
58
+ ActiveRecord::Schema.define(:version => 1) do
59
+ create_table :readers, :primary_key => 'number', :force => true do |t|
60
+ t.string :name
61
+ end
62
+
63
+ create_table :emails, :primary_key => 'messageid', :force => true do |t|
64
+ t.string :subject
65
+ t.text :content
66
+ t.datetime :created_at
67
+ t.datetime :updated_at
68
+ end
69
+ end
70
+ end
71
+
72
+ def clear_db
73
+ Reader.delete_all
74
+ Email.delete_all
75
+ ReadMark.delete_all
76
+ end
77
+
78
+ setup_db
@@ -0,0 +1,22 @@
1
+ RSpec::Matchers.define :perform_queries do |expected|
2
+ match do |block|
3
+ query_count(&block) == expected
4
+ end
5
+
6
+ failure_message do |actual|
7
+ "Expected to run #{expected} queries, got #{@counter.query_count}"
8
+ end
9
+
10
+ def query_count(&block)
11
+ @counter = ActiveRecord::QueryCounter.new
12
+ ActiveSupport::Notifications.subscribe('sql.active_record', @counter.to_proc)
13
+ yield
14
+ ActiveSupport::Notifications.unsubscribe(@counter.to_proc)
15
+
16
+ @counter.query_count
17
+ end
18
+
19
+ def supports_block_expectations?
20
+ true
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveRecord
2
+ class QueryCounter
3
+ attr_reader :query_count
4
+
5
+ def initialize
6
+ @query_count = 0
7
+ end
8
+
9
+ def to_proc
10
+ lambda(&method(:callback))
11
+ end
12
+
13
+ def callback(name, start, finish, message_id, values)
14
+ @query_count += 1 unless %w(CACHE SCHEMA).include?(values[:name]) || values[:sql] =~ /^begin/i || values[:sql] =~ /^commit/i
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ def wait
2
+ Timecop.freeze(1.minute.from_now.change(:usec => 0))
3
+ end
@@ -23,4 +23,7 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency 'rake'
24
24
  s.add_development_dependency 'timecop'
25
25
  s.add_development_dependency 'sqlite3'
26
+ s.add_development_dependency 'rspec'
27
+ s.add_development_dependency 'simplecov'
28
+ s.add_development_dependency 'coveralls'
26
29
  end
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.3.1
4
+ version: 0.4.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: 2013-12-04 00:00:00.000000000 Z
11
+ date: 2014-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -66,6 +66,48 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: coveralls
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
69
111
  description: 'This gem creates a scope for unread objects and adds methods to mark
70
112
  objects as read '
71
113
  email:
@@ -80,11 +122,11 @@ files:
80
122
  - MIT-LICENSE
81
123
  - README.md
82
124
  - Rakefile
83
- - changelog.md
84
125
  - ci/Gemfile-rails-3-0
85
126
  - ci/Gemfile-rails-3-1
86
127
  - ci/Gemfile-rails-3-2
87
128
  - ci/Gemfile-rails-4-0
129
+ - ci/Gemfile-rails-4-1
88
130
  - lib/generators/unread/migration/migration_generator.rb
89
131
  - lib/generators/unread/migration/templates/migration.rb
90
132
  - lib/unread.rb
@@ -94,10 +136,15 @@ files:
94
136
  - lib/unread/reader.rb
95
137
  - lib/unread/scopes.rb
96
138
  - lib/unread/version.rb
97
- - test/database.yml
98
- - test/schema.rb
99
- - test/test_helper.rb
100
- - test/unread_test.rb
139
+ - spec/base_spec.rb
140
+ - spec/model/email.rb
141
+ - spec/model/reader.rb
142
+ - spec/read_mark_spec.rb
143
+ - spec/readable_spec.rb
144
+ - spec/spec_helper.rb
145
+ - spec/support/matchers/perform_queries.rb
146
+ - spec/support/query_counter.rb
147
+ - spec/support/timecop.rb
101
148
  - unread.gemspec
102
149
  homepage: ''
103
150
  licenses: []
@@ -118,12 +165,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
165
  version: '0'
119
166
  requirements: []
120
167
  rubyforge_project: unread
121
- rubygems_version: 2.0.14
168
+ rubygems_version: 2.2.2
122
169
  signing_key:
123
170
  specification_version: 4
124
171
  summary: Manages read/unread status of ActiveRecord objects
125
172
  test_files:
126
- - test/database.yml
127
- - test/schema.rb
128
- - test/test_helper.rb
129
- - test/unread_test.rb
173
+ - spec/base_spec.rb
174
+ - spec/model/email.rb
175
+ - spec/model/reader.rb
176
+ - spec/read_mark_spec.rb
177
+ - spec/readable_spec.rb
178
+ - spec/spec_helper.rb
179
+ - spec/support/matchers/perform_queries.rb
180
+ - spec/support/query_counter.rb
181
+ - spec/support/timecop.rb
@@ -1,75 +0,0 @@
1
- # Changelog
2
-
3
- ## 0.3.1 - 2013-12-04
4
-
5
- * Use Time.current instead of Time.now to avoid time zone trouble. Issue #18 (thanks to @henrythe9th)
6
- * Handle primary keys other than "id". Issue #29 (thanks to @bcavileer)
7
-
8
-
9
- ## 0.3.0 - 2013-03-17
10
-
11
- * Support for Rails 4 (beta1)
12
-
13
-
14
- ## 0.2.0 - 2013-02-18
15
-
16
- * Support for Rails 2 dropped
17
- * Refactoring
18
- * Added migration generator
19
-
20
-
21
- ## 0.1.2 - 2013-01-27
22
-
23
- * Scopes: Improved parameter check
24
-
25
-
26
- ## 0.1.1 - 2012-05-01
27
-
28
- * Fixed handling namespaced classes. Closes #10 (thanks to @stanislaw)
29
-
30
-
31
- ## 0.1.0 - 2012-04-21
32
-
33
- * Added scope "with_read_marks_for"
34
- * Fixed #7: Added attr_accessible to all ReadMark attributes (thanks to @negative)
35
-
36
-
37
- ## 0.0.7 - 2012-02-29
38
-
39
- * Cleanup files
40
- * acts_as_reader: Using inverse_of (available since Rails 2.3.6)
41
-
42
-
43
- ## 0.0.6 - 2011-11-11
44
-
45
- * Fixed #5: Gemspec dependency fix (thanks to @bricker88)
46
- * Fixed #6: Removed hard coded dependency on a class named "User" (thanks to @mixandgo)
47
- * Some cleanup
48
-
49
-
50
- ## 0.0.5 - 2011-09-09
51
-
52
- * Fixed class loading issue in development environment
53
-
54
-
55
- ## 0.0.4 - 2011-08-31
56
-
57
- * Ignore multiple calls of acts_as_*
58
- * Improved error messages
59
- * Tested with Rails 3.1
60
-
61
-
62
- ## 0.0.3 - 2011-08-01
63
-
64
- * Fixed gemspec by adding development dependencies
65
- * Testing with Travis CI
66
-
67
-
68
- ## 0.0.2 - 2011-06-23
69
-
70
- * Fixed scoping for ActiveRecord 2.x
71
-
72
-
73
- ## 0.0.1 - 2011-06-23
74
-
75
- * Released as Gem
@@ -1,3 +0,0 @@
1
- sqlite:
2
- adapter: sqlite3
3
- database: ":memory:"
@@ -1,20 +0,0 @@
1
- ActiveRecord::Schema.define(:version => 0) do
2
- create_table :readers, :primary_key => 'number', :force => true do |t|
3
- t.string :name
4
- end
5
-
6
- create_table :emails, :primary_key => 'messageid', :force => true do |t|
7
- t.string :subject
8
- t.text :content
9
- t.datetime :created_at
10
- t.datetime :updated_at
11
- end
12
-
13
- create_table :read_marks, :force => true do |t|
14
- t.integer :readable_id
15
- t.integer :user_id, :null => false
16
- t.string :readable_type, :null => false
17
- t.datetime :timestamp
18
- end
19
- add_index :read_marks, [:user_id, :readable_type, :readable_id]
20
- end
@@ -1,27 +0,0 @@
1
- require 'test/unit'
2
- require 'active_support'
3
- require 'active_support/test_case'
4
- require 'active_record'
5
- require 'timecop'
6
-
7
- configs = YAML.load_file(File.dirname(__FILE__) + '/database.yml')
8
- ActiveRecord::Base.configurations = configs
9
-
10
- ActiveRecord::Base.establish_connection('sqlite')
11
- ActiveRecord::Migration.verbose = false
12
- load(File.dirname(__FILE__) + "/schema.rb")
13
-
14
- require 'unread'
15
-
16
- class Reader < ActiveRecord::Base
17
- self.primary_key = 'number'
18
- acts_as_reader
19
- end
20
-
21
- class Email < ActiveRecord::Base
22
- self.primary_key = 'messageid'
23
-
24
- acts_as_readable :on => :updated_at
25
- end
26
-
27
- puts "Testing with ActiveRecord #{ActiveRecord::VERSION::STRING}"
@@ -1,166 +0,0 @@
1
- require 'test_helper'
2
-
3
- class UnreadTest < ActiveSupport::TestCase
4
- def setup
5
- @reader = Reader.create! :name => 'David'
6
- @other_reader = Reader.create :name => 'Matz'
7
- wait
8
- @email1 = Email.create!
9
- wait
10
- @email2 = Email.create!
11
- end
12
-
13
- def teardown
14
- Reader.delete_all
15
- Email.delete_all
16
- ReadMark.delete_all
17
- Timecop.return
18
- end
19
-
20
- def test_schema_has_loaded_correctly
21
- assert_equal [@email1, @email2], Email.all
22
- end
23
-
24
- def test_readable_classes
25
- assert_equal [ Email ], ReadMark.readable_classes
26
- end
27
-
28
- def test_reader_class
29
- assert_equal Reader, ReadMark.reader_class
30
- end
31
-
32
- def test_scope
33
- assert_equal [@email1, @email2], Email.unread_by(@reader)
34
- assert_equal [@email1, @email2], Email.unread_by(@other_reader)
35
-
36
- assert_equal 2, Email.unread_by(@reader).count
37
- assert_equal 2, Email.unread_by(@other_reader).count
38
- end
39
-
40
- def test_with_read_marks_for
41
- @email1.mark_as_read! :for => @reader
42
-
43
- emails = Email.with_read_marks_for(@reader).to_a
44
-
45
- assert emails[0].read_mark_id.present?
46
- assert emails[1].read_mark_id.nil?
47
-
48
- assert_equal false, emails[0].unread?(@reader)
49
- assert_equal true, emails[1].unread?(@reader)
50
- end
51
-
52
- def test_scope_param_check
53
- [ 42, nil, 'foo', :foo, {} ].each do |not_a_reader|
54
- assert_raise(ArgumentError) { Email.unread_by(not_a_reader)}
55
- assert_raise(ArgumentError) { Email.with_read_marks_for(not_a_reader)}
56
- end
57
-
58
- unsaved_reader = Reader.new
59
- assert_raise(ArgumentError) { Email.unread_by(unsaved_reader)}
60
- assert_raise(ArgumentError) { Email.with_read_marks_for(unsaved_reader)}
61
- end
62
-
63
- def test_scope_after_reset
64
- @email1.mark_as_read! :for => @reader
65
-
66
- assert_equal [@email2], Email.unread_by(@reader)
67
- assert_equal 1, Email.unread_by(@reader).count
68
- end
69
-
70
- def test_unread_after_create
71
- assert_equal true, @email1.unread?(@reader)
72
- assert_equal true, @email1.unread?(@other_reader)
73
-
74
- assert_raise(ArgumentError) {
75
- @email1.unread?(42)
76
- }
77
- end
78
-
79
- def test_unread_after_update
80
- @email1.mark_as_read! :for => @reader
81
- wait
82
- @email1.update_attributes! :subject => 'changed'
83
-
84
- assert_equal true, @email1.unread?(@reader)
85
- end
86
-
87
- def test_mark_as_read
88
- @email1.mark_as_read! :for => @reader
89
-
90
- assert_equal false, @email1.unread?(@reader)
91
- assert_equal [@email2], Email.unread_by(@reader)
92
-
93
- assert_equal true, @email1.unread?(@other_reader)
94
- assert_equal [@email1, @email2], Email.unread_by(@other_reader)
95
-
96
- assert_equal 1, @reader.read_marks.single.count
97
- assert_equal @email1, @reader.read_marks.single.first.readable
98
- end
99
-
100
- def test_mark_as_read_multiple
101
- assert_equal true, @email1.unread?(@reader)
102
- assert_equal true, @email2.unread?(@reader)
103
-
104
- Email.mark_as_read! [ @email1, @email2 ], :for => @reader
105
-
106
- assert_equal false, @email1.unread?(@reader)
107
- assert_equal false, @email2.unread?(@reader)
108
- end
109
-
110
- def test_mark_as_read_with_marked_all
111
- wait
112
-
113
- Email.mark_as_read! :all, :for => @reader
114
- @email1.mark_as_read! :for => @reader
115
-
116
- assert_equal [], @reader.read_marks.single
117
- end
118
-
119
- def test_mark_as_read_twice
120
- @email1.mark_as_read! :for => @reader
121
- @email1.mark_as_read! :for => @reader
122
-
123
- assert_equal 1, @reader.read_marks.single.count
124
- end
125
-
126
- def test_mark_all_as_read
127
- Email.mark_as_read! :all, :for => @reader
128
-
129
- assert_equal Time.current, @reader.read_mark_global(Email).timestamp
130
- assert_equal [], @reader.read_marks.single
131
- assert_equal 0, ReadMark.single.count
132
- assert_equal 2, ReadMark.global.count
133
- end
134
-
135
- def test_cleanup_read_marks
136
- assert_equal 0, @reader.read_marks.single.count
137
-
138
- @email1.mark_as_read! :for => @reader
139
-
140
- assert_equal [@email2], Email.unread_by(@reader)
141
- assert_equal 1, @reader.read_marks.single.count
142
-
143
- Email.cleanup_read_marks!
144
-
145
- @reader.reload
146
- assert_equal 0, @reader.read_marks.single.count
147
- end
148
-
149
- def test_cleanup_read_marks_not_delete_from_other_readables
150
- other_read_mark = @reader.read_marks.create! :readable_type => 'Foo', :readable_id => 42, :timestamp => 5.years.ago
151
- Email.cleanup_read_marks!
152
- assert_equal true, !!ReadMark.exists?(other_read_mark.id) # Rails4 does not return true, but count instead.
153
- end
154
-
155
- def test_reset_read_marks_for_all
156
- Email.reset_read_marks_for_all
157
-
158
- assert_equal 0, ReadMark.single.count
159
- assert_equal 2, ReadMark.global.count
160
- end
161
-
162
- private
163
- def wait
164
- Timecop.freeze(1.minute.from_now.change(:usec => 0))
165
- end
166
- end