Code Monkey home page Code Monkey logo

unread's Introduction

Unread

Ruby gem to manage read/unread status of ActiveRecord objects - and it's fast.

Build Status Code Climate Coverage Status

Features

  • Manages unread records for anything you want readers (e.g. users) to read (like messages, documents, comments etc.)
  • Supports mark as read to mark a single record as read
  • Supports mark all as read to mark all records as read in a single step
  • Gives you a scope to get the unread records for a given reader
  • Needs only one additional database table
  • Most important: Great performance

Requirements

  • Ruby 2.0.0 or newer
  • Rails 3.0 or newer (including Rails 4.x and Rails 5.x)
  • MySQL, PostgreSQL or SQLite
  • Needs a timestamp field in your models (like created_at or updated_at) with a database index on it

Changelog

https://github.com/ledermann/unread/releases

Installation

Step 1: Add this to your Gemfile:

gem 'unread'

and run

bundle

Step 2: Generate and run the migration:

rails g unread:migration
rake db:migrate

Upgrade from previous releases

If you upgrade from an older release of this gem, you should read the upgrade notes.

Usage

class User < ActiveRecord::Base
  acts_as_reader

  # Optional: Allow a subset of users as readers only
  def self.reader_scope
    where(:is_admin => true)
  end
end

class Message < ActiveRecord::Base
  acts_as_readable :on => :created_at
end

message1 = Message.create!
message2 = Message.create!

## Get unread messages for a given user
Message.unread_by(current_user)
# => [ message1, message2 ]

message1.mark_as_read! :for => current_user
Message.unread_by(current_user)
# => [ message2 ]

## Get read messages for a given user
Message.read_by(current_user)
# => [ ]

message1.mark_as_read! :for => current_user
Message.read_by(current_user)
# => [ message1 ]

## Get all messages including the read status for a given user
messages = Message.with_read_marks_for(current_user)
# => [ message1, message2 ]
messages[0].unread?(current_user)
# => false
messages[1].unread?(current_user)
# => true

Message.mark_as_read! :all, :for => current_user
Message.unread_by(current_user)
# => [ ]

Message.read_by(current_user)
# => [ message1, message2 ]

## Get users that have not read a given message
user1 = User.create!
user2 = User.create!

User.have_not_read(message1)
# => [ user1, user2 ]

message1.mark_as_read! :for => user1
User.have_not_read(message1)
# => [ user2 ]

## Get users that have read a given message
User.have_read(message1)
# => [ user1 ]

message1.mark_as_read! :for => user2
User.have_read(message1)
# => [ user1, user2 ]

Message.mark_as_read! :all, :for => user1
User.have_not_read(message1)
# => [ ]
User.have_not_read(message2)
# => [ user2 ]

User.have_read(message1)
# => [ user1, user2 ]
User.have_read(message2)
# => [ user1 ]

## Get all users including their read status for a given message
users = User.with_read_marks_for(message1)
# => [ user1, user2 ]
users[0].have_read?(message1)
# => true
users[1].have_read?(message2)
# => false

# Optional: Cleaning up unneeded markers
# Do this in a cron job once a day
Message.cleanup_read_marks!

How does it work?

The main idea of this gem is to manage a list of read items for every reader after a certain timestamp.

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.

It will be ensured that the list of read items will not grow up too much:

  • If a user uses "mark all as read", his list gets deleted and the timestamp is set to the current time.
  • 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.

Overall, this gem can be used for large data. Please have a look at the generated SQL queries, here is an example:

# Assuming we have a user who has marked all messages as read on 2010-10-20 08:50
current_user = User.find(42)

# Get the unread messages for this user
Message.unread_by(current_user)

Generated query:

SELECT messages.*
FROM messages
LEFT JOIN read_marks ON read_marks.readable_type = "Message"
                    AND read_marks.readable_id = messages.id
                    AND read_marks.reader_id = 42
                    AND read_marks.reader_type = 'User'
                    AND read_marks.timestamp >= messages.created_at
WHERE read_marks.id IS NULL
AND messages.created_at > '2010-10-20 08:50:00'

Hint: You should add a database index on messages.created_at.

Copyright (c) 2010-2017 Georg Ledermann and contributors, released under the MIT license

unread's People

Contributors

yxf avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.