unread 0.0.5 → 0.0.6

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.
@@ -1,6 +1,6 @@
1
1
  rvm:
2
2
  - 1.8.7
3
- - 1.9.2
3
+ - 1.9.3
4
4
  gemfile:
5
5
  - ci/Gemfile.rails-2.3.x
6
6
  - ci/Gemfile.rails-3.0.x
data/README.md CHANGED
@@ -1,24 +1,25 @@
1
1
  Unread
2
2
  ======
3
3
 
4
- Gem to manage read/unread status of ActiveRecord objects - and it's fast.
4
+ Ruby gem to manage read/unread status of ActiveRecord objects - and it's fast.
5
5
 
6
6
  [![Build Status](https://secure.travis-ci.org/ledermann/unread.png)](http://travis-ci.org/ledermann/unread)
7
7
 
8
+
8
9
  ## Features
9
10
 
10
- * Manages unread records for anything you want your users to read (like messages, documents, comments etc.)
11
- * Supports "mark as read" to mark a **single** record as read
12
- * Supports "mark all as read" to mark **all** records as read in a single step
13
- * Gives you a named_scope to get the unread records for a given user
11
+ * Manages unread records for anything you want users to read (like messages, documents, comments etc.)
12
+ * Supports _mark as read_ to mark a **single** record as read
13
+ * Supports _mark all as read__ to mark **all** records as read in a single step
14
+ * Gives you a scope to get the unread records for a given user
14
15
  * Needs only one additional database table
15
16
  * Most important: Great performance
16
17
 
17
18
 
18
19
  ## Requirements
19
20
 
20
- * Ruby 1.8.7 or 1.9.2
21
- * ActiveRecord 2.3.x, 3.0.x, 3.1.x (tested with SQLite and MySQL)
21
+ * Ruby 1.8.7 or 1.9.x
22
+ * Rails 2.3.x, 3.0.x, 3.1.x (tested with SQLite and MySQL)
22
23
  * Needs a timestamp field in your models (e.g. created_at) with a database index on it
23
24
 
24
25
 
@@ -28,7 +29,7 @@ Step 1: Add this to your Gemfile:
28
29
 
29
30
  gem 'unread'
30
31
 
31
- and run
32
+ and run
32
33
 
33
34
  bundle
34
35
 
@@ -87,16 +88,16 @@ Step 2: Add this migration:
87
88
 
88
89
  ## How does it work?
89
90
 
90
- The main idea of this gem is to manage a list of read items for every user **after** a certain timestamp.
91
+ The main idea of this gem is to manage a list of read items for every reader **after** a certain timestamp.
91
92
 
92
- The gem defines a named_scope doing a LEFT JOIN to this list, so your app can get the unread items in a performant manner. Of course, other scopes can be combined.
93
+ The gem defines a scope doing a LEFT JOIN to this list, so your app can get the unread items in a performant manner. Of course, other scopes can be combined.
93
94
 
94
95
  It will be ensured that the list of read items will not grow up too much:
95
96
 
96
- * If a user uses "mark all as read", his list is deleted and the timestamp is set to the current time.
97
+ * If a user uses "mark all as read", his list gets deleted and the timestamp is set to the current time.
97
98
  * If a user never uses "mark all as read", the list will grow and grow with each item he reads. But there is help: Your app can use a cleanup method which removes unnecessary list items.
98
99
 
99
- Overall, this gem can be used for large tables, too. If you are in doubt, look at the generated SQL queries, here is an example:
100
+ Overall, this gem can be used for large data. Please have a look at the generated SQL queries, here is an example:
100
101
 
101
102
  # Assuming we have a user who has marked all messages as read on 2010-10-20 08:50
102
103
  current_user = User.find(42)
@@ -114,22 +115,17 @@ Overall, this gem can be used for large tables, too. If you are in doubt, look a
114
115
  # WHERE read_marks.id IS NULL
115
116
  # AND messages.created_at > '2010-10-20 08:50:00'
116
117
 
117
- Hint: You should add a database index on messages.created_at.
118
+ Hint: You should add a database index on `messages.created_at`.
118
119
 
119
120
 
120
121
  ## Similar tools
121
122
 
122
- There a two other gems/plugins doing a similar job:
123
+ There are two other gems/plugins doing a similar job:
123
124
 
124
125
  * http://github.com/jhnvz/mark_as_read
125
126
  * http://github.com/mbleigh/acts-as-readable
126
127
 
127
- 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.
128
-
129
-
130
- ## TODO
131
-
132
- * Add more documentation
128
+ 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.
133
129
 
134
130
 
135
131
  Copyright (c) 2010,2011 Georg Ledermann, released under the MIT license
@@ -1,6 +1,6 @@
1
1
  source :rubygems
2
2
 
3
- gem 'activerecord', '~> 3.1.0'
3
+ gem 'activerecord', '~> 3.1.1'
4
4
  gem 'sqlite3'
5
5
  gem 'mysql2', '>= 0.3.6'
6
6
  gem 'mocha'
@@ -1,5 +1,4 @@
1
1
  class ReadMark < ActiveRecord::Base
2
- belongs_to :user
3
2
  belongs_to :readable, :polymorphic => true
4
3
 
5
4
  validates_presence_of :user_id, :readable_type
@@ -11,10 +10,16 @@ class ReadMark < ActiveRecord::Base
11
10
  send scope_method, :readable_type, lambda { |readable_type | { :conditions => { :readable_type => readable_type }}}
12
11
  send scope_method, :user, lambda { |user| { :conditions => { :user_id => user.id }}}
13
12
  send scope_method, :older_than, lambda { |timestamp| { :conditions => [ 'timestamp < ?', timestamp] }}
13
+
14
+ # Returns the class defined by ActsAsReadable::acts_as_reader
15
+ def self.reader_class
16
+ user_association = reflect_on_all_associations(:belongs_to).find { |assoc| assoc.name == :user }
17
+ user_association.try(:klass)
18
+ end
14
19
 
15
20
  if respond_to?(:class_attribute)
16
- class_attribute :reader_class, :readable_classes
21
+ class_attribute :readable_classes
17
22
  else
18
- class_inheritable_accessor :reader_class, :readable_classes
23
+ class_inheritable_accessor :readable_classes
19
24
  end
20
25
  end
@@ -5,9 +5,9 @@ module Unread
5
5
 
6
6
  module ActsAsReadable
7
7
  def acts_as_reader
8
- ReadMark.reader_class = self
8
+ ReadMark.belongs_to :user, :class_name => self.to_s
9
9
 
10
- has_many :read_marks, :dependent => :delete_all
10
+ has_many :read_marks, :dependent => :delete_all, :foreign_key => 'user_id'
11
11
 
12
12
  after_create do |user|
13
13
  (ReadMark.readable_classes || []).each do |klass|
@@ -1,3 +1,3 @@
1
1
  module Unread
2
- VERSION = '0.0.5'
2
+ VERSION = '0.0.6'
3
3
  end
@@ -1,5 +1,5 @@
1
1
  ActiveRecord::Schema.define(:version => 0) do
2
- create_table :users, :force => true do |t|
2
+ create_table :readers, :force => true do |t|
3
3
  t.string :name
4
4
  end
5
5
 
@@ -15,7 +15,7 @@ ActiveRecord::Base.establish_connection(db_name)
15
15
  ActiveRecord::Migration.verbose = false
16
16
  load(File.dirname(__FILE__) + "/schema.rb")
17
17
 
18
- class User < ActiveRecord::Base
18
+ class Reader < ActiveRecord::Base
19
19
  acts_as_reader
20
20
  end
21
21
 
@@ -2,8 +2,8 @@ require 'test_helper'
2
2
 
3
3
  class UnreadTest < ActiveSupport::TestCase
4
4
  def setup
5
- @user = User.create! :name => 'David'
6
- @other_user = User.create :name => 'Matz'
5
+ @reader = Reader.create! :name => 'David'
6
+ @other_reader = Reader.create :name => 'Matz'
7
7
  wait
8
8
  @email1 = Email.create!
9
9
  wait
@@ -11,7 +11,7 @@ class UnreadTest < ActiveSupport::TestCase
11
11
  end
12
12
 
13
13
  def teardown
14
- User.delete_all
14
+ Reader.delete_all
15
15
  Email.delete_all
16
16
  ReadMark.delete_all
17
17
  end
@@ -25,15 +25,15 @@ class UnreadTest < ActiveSupport::TestCase
25
25
  end
26
26
 
27
27
  def test_reader_class
28
- assert_equal User, ReadMark.reader_class
28
+ assert_equal Reader, ReadMark.reader_class
29
29
  end
30
30
 
31
31
  def test_scope
32
- assert_equal [@email1, @email2], Email.unread_by(@user)
33
- assert_equal [@email1, @email2], Email.unread_by(@other_user)
32
+ assert_equal [@email1, @email2], Email.unread_by(@reader)
33
+ assert_equal [@email1, @email2], Email.unread_by(@other_reader)
34
34
 
35
- assert_equal 2, Email.unread_by(@user).count
36
- assert_equal 2, Email.unread_by(@other_user).count
35
+ assert_equal 2, Email.unread_by(@reader).count
36
+ assert_equal 2, Email.unread_by(@other_reader).count
37
37
 
38
38
  assert_raise(ArgumentError) {
39
39
  Email.unread_by(42)
@@ -41,15 +41,15 @@ class UnreadTest < ActiveSupport::TestCase
41
41
  end
42
42
 
43
43
  def test_scope_after_reset
44
- @email1.mark_as_read! :for => @user
44
+ @email1.mark_as_read! :for => @reader
45
45
 
46
- assert_equal [@email2], Email.unread_by(@user)
47
- assert_equal 1, Email.unread_by(@user).count
46
+ assert_equal [@email2], Email.unread_by(@reader)
47
+ assert_equal 1, Email.unread_by(@reader).count
48
48
  end
49
49
 
50
50
  def test_unread_after_create
51
- assert_equal true, @email1.unread?(@user)
52
- assert_equal true, @email1.unread?(@other_user)
51
+ assert_equal true, @email1.unread?(@reader)
52
+ assert_equal true, @email1.unread?(@other_reader)
53
53
 
54
54
  assert_raise(ArgumentError) {
55
55
  @email1.unread?(42)
@@ -57,77 +57,77 @@ class UnreadTest < ActiveSupport::TestCase
57
57
  end
58
58
 
59
59
  def test_unread_after_update
60
- @email1.mark_as_read! :for => @user
60
+ @email1.mark_as_read! :for => @reader
61
61
  wait
62
62
  @email1.update_attributes! :subject => 'changed'
63
63
 
64
- assert_equal true, @email1.unread?(@user)
64
+ assert_equal true, @email1.unread?(@reader)
65
65
  end
66
66
 
67
67
  def test_mark_as_read
68
- @email1.mark_as_read! :for => @user
68
+ @email1.mark_as_read! :for => @reader
69
69
 
70
- assert_equal false, @email1.unread?(@user)
71
- assert_equal [@email2], Email.unread_by(@user)
70
+ assert_equal false, @email1.unread?(@reader)
71
+ assert_equal [@email2], Email.unread_by(@reader)
72
72
 
73
- assert_equal true, @email1.unread?(@other_user)
74
- assert_equal [@email1, @email2], Email.unread_by(@other_user)
73
+ assert_equal true, @email1.unread?(@other_reader)
74
+ assert_equal [@email1, @email2], Email.unread_by(@other_reader)
75
75
 
76
- assert_equal 1, @user.read_marks.single.count
77
- assert_equal @email1, @user.read_marks.single.first.readable
76
+ assert_equal 1, @reader.read_marks.single.count
77
+ assert_equal @email1, @reader.read_marks.single.first.readable
78
78
  end
79
79
 
80
80
  def test_mark_as_read_multiple
81
- assert_equal true, @email1.unread?(@user)
82
- assert_equal true, @email2.unread?(@user)
81
+ assert_equal true, @email1.unread?(@reader)
82
+ assert_equal true, @email2.unread?(@reader)
83
83
 
84
- Email.mark_as_read! [ @email1, @email2 ], :for => @user
84
+ Email.mark_as_read! [ @email1, @email2 ], :for => @reader
85
85
 
86
- assert_equal false, @email1.unread?(@user)
87
- assert_equal false, @email2.unread?(@user)
86
+ assert_equal false, @email1.unread?(@reader)
87
+ assert_equal false, @email2.unread?(@reader)
88
88
  end
89
89
 
90
90
  def test_mark_as_read_with_marked_all
91
91
  wait
92
92
 
93
- Email.mark_as_read! :all, :for => @user
94
- @email1.mark_as_read! :for => @user
93
+ Email.mark_as_read! :all, :for => @reader
94
+ @email1.mark_as_read! :for => @reader
95
95
 
96
- assert_equal [], @user.read_marks.single
96
+ assert_equal [], @reader.read_marks.single
97
97
  end
98
98
 
99
99
  def test_mark_as_read_twice
100
- @email1.mark_as_read! :for => @user
101
- @email1.mark_as_read! :for => @user
100
+ @email1.mark_as_read! :for => @reader
101
+ @email1.mark_as_read! :for => @reader
102
102
 
103
- assert_equal 1, @user.read_marks.single.count
103
+ assert_equal 1, @reader.read_marks.single.count
104
104
  end
105
105
 
106
106
  def test_mark_all_as_read
107
- Email.mark_as_read! :all, :for => @user
108
- assert_equal Time.now.to_s, Email.read_mark(@user).timestamp.to_s
107
+ Email.mark_as_read! :all, :for => @reader
108
+ assert_equal Time.now.to_s, Email.read_mark(@reader).timestamp.to_s
109
109
 
110
- assert_equal [], @user.read_marks.single
110
+ assert_equal [], @reader.read_marks.single
111
111
  assert_equal 0, ReadMark.single.count
112
112
  assert_equal 2, ReadMark.global.count
113
113
  end
114
114
 
115
115
  def test_cleanup_read_marks
116
- assert_equal 0, @user.read_marks.single.count
116
+ assert_equal 0, @reader.read_marks.single.count
117
117
 
118
- @email1.mark_as_read! :for => @user
118
+ @email1.mark_as_read! :for => @reader
119
119
 
120
- assert_equal [@email2], Email.unread_by(@user)
121
- assert_equal 1, @user.read_marks.single.count
120
+ assert_equal [@email2], Email.unread_by(@reader)
121
+ assert_equal 1, @reader.read_marks.single.count
122
122
 
123
123
  Email.cleanup_read_marks!
124
124
 
125
- @user.reload
126
- assert_equal 0, @user.read_marks.single.count
125
+ @reader.reload
126
+ assert_equal 0, @reader.read_marks.single.count
127
127
  end
128
128
 
129
129
  def test_cleanup_read_marks_not_delete_from_other_readables
130
- other_read_mark = @user.read_marks.create! :readable_type => 'Foo', :readable_id => 42, :timestamp => 5.years.ago
130
+ other_read_mark = @reader.read_marks.create! :readable_type => 'Foo', :readable_id => 42, :timestamp => 5.years.ago
131
131
  Email.cleanup_read_marks!
132
132
  assert_equal true, ReadMark.exists?(other_read_mark.id)
133
133
  end
@@ -1,7 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
3
  require "unread/version"
4
- require 'active_record/version'
5
4
 
6
5
  Gem::Specification.new do |s|
7
6
  s.name = "unread"
@@ -24,10 +23,5 @@ Gem::Specification.new do |s|
24
23
  s.add_development_dependency 'rake'
25
24
  s.add_development_dependency 'mocha'
26
25
  s.add_development_dependency 'sqlite3'
27
-
28
- if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR >= 1
29
- s.add_development_dependency 'mysql2', '>= 0.3.6'
30
- else
31
- s.add_development_dependency 'mysql2', '~> 0.2.11'
32
- end
26
+ s.add_development_dependency 'mysql2'
33
27
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unread
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 5
10
- version: 0.0.5
9
+ - 6
10
+ version: 0.0.6
11
11
  platform: ruby
12
12
  authors:
13
13
  - Georg Ledermann
@@ -15,7 +15,8 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-09-09 00:00:00 Z
18
+ date: 2011-11-11 00:00:00 +01:00
19
+ default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: activerecord
@@ -82,12 +83,10 @@ dependencies:
82
83
  requirements:
83
84
  - - ">="
84
85
  - !ruby/object:Gem::Version
85
- hash: 31
86
+ hash: 3
86
87
  segments:
87
88
  - 0
88
- - 3
89
- - 6
90
- version: 0.3.6
89
+ version: "0"
91
90
  type: :development
92
91
  version_requirements: *id005
93
92
  description: "This gem creates a scope for unread objects and adds methods to mark objects as read "
@@ -121,6 +120,7 @@ files:
121
120
  - test/unread_test.rb
122
121
  - uninstall.rb
123
122
  - unread.gemspec
123
+ has_rdoc: true
124
124
  homepage: ""
125
125
  licenses: []
126
126
 
@@ -150,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
150
  requirements: []
151
151
 
152
152
  rubyforge_project: unread
153
- rubygems_version: 1.8.6
153
+ rubygems_version: 1.6.2
154
154
  signing_key:
155
155
  specification_version: 3
156
156
  summary: Manages read/unread status of ActiveRecord objects