Git Product home page Git Product logo

Comments (15)

renius avatar renius commented on May 21, 2024 3

+1 for mark_as_unread!

from unread.

aried3r avatar aried3r commented on May 21, 2024 1

I've tried to wrap my head around this, but it feels like the solution proposed by @arusa should work, even with .cleanup_read_marks!, except for the fact that this method is now private.

@ledermann, could you chime in on this again?

The way I see it the read_mark(reader) method returns the latest read mark (actually, this is not true, it doesn't use .order on the relation and thus no order is guaranteed in e.g. PostgreSQL:

If sorting is not chosen, the rows will be returned in an unspecified order.

https://www.postgresql.org/docs/9.5/static/queries-order.html)

If we delete that ReadMark, a record is unread for that user. Isn't that correct?

I might be wrong because I don't exactly know how the Garbage Collector class of this gem works completely.

from unread.

ledermann avatar ledermann commented on May 21, 2024 1

@aried3r, @arusa The garbage collector .cleanup_read_marks! searches for the oldest unread record (if there is any). Then all read_marks before its timestamp are deleted and the global timestamp is moved. The cleanup is essential for this gem, because it keeps the number of read_marks as low as possible. I recommended to run it once a day (via a CRON job or similar).

Because old read_marks are deleted this way, we cannot mark a record as unread after a cleanup was done. Note: There are situations where it does work. Example: If you have an old unread record, the garbage collector cannot remove newer read_marks, so you can delete them manually to mark records as unread. But in a real world app, it's unlikely that a user keeps an old record unread for a long time.

So: Without big changes in the algorithm it's not possible to mark a record as unread.

from unread.

ledermann avatar ledermann commented on May 21, 2024

The gem manages a timestamp and a list of read items (which were read after the timestamp) for a every user. This is efficient for marking items as read. Sadly, marking items as unread is hard with this approach: If we want to mark an old item as unread, we have to move the timestamp to the past and have to insert lots of items into the list of read items. This is not efficient.

But perhaps the approach can be enhanced by managing an additional list of unread items. This would be a big change, but perhaps it's worth it.

from unread.

leonardoafpinto avatar leonardoafpinto commented on May 21, 2024

For a while, i found a way to do that: instead of set a model to acts_as_readable on created_at, i set it on updated_at. When i want to set a record as unread, i update your "updated_at" with Time.now. It worked perfectly.
@ledermann , what do you think?

from unread.

ledermann avatar ledermann commented on May 21, 2024

@leonardoafpinto I don't think your approach will work, because changing updated_at marks the record as unread for all readers, not for the current one only.

from unread.

leonardoafpinto avatar leonardoafpinto commented on May 21, 2024

My readable is a shared model among other readers, such as an email, for example. In this context, it worked for me, in this scenario.
But I agree with you that this will not work another business model.

from unread.

ledermann avatar ledermann commented on May 21, 2024

@leonardoafpinto You are right, if every reader is accessing his own scope of records (fully separated from other readers), changing updated_at should work.

from unread.

firedev avatar firedev commented on May 21, 2024

I suggest .mark_as_unread(for: :all), .mark_as_unread(for: current_user) and also .read_by(current_user). Right now I am going to destroy records matching current message.id and current_user.id.

Here is what I did:

  def mark_as_unread_except current_user
    ReadMark.where(readable_type: self.class.class_name, readable_id: id).each(&:destroy!)
    mark_as_read!(for: current_user)
  end

from unread.

sysout avatar sysout commented on May 21, 2024

For .mark_as_unread, why not just delete the record in read_marks table?
Use user_id readable_type and readable_id to locate the record and delete it.

from unread.

firedev avatar firedev commented on May 21, 2024

In the end, just wrote my own readmarks that sort by unread, don't need cleanups and basically just work. Here it is if you interested: readmarkable.rb

This is an optimized version where I removed polymorphic relation due to speed concerns since I needed it only for one model. But you get the idea.

from unread.

jarinudom avatar jarinudom commented on May 21, 2024

@sysout That approach doesn't work because cleanup_read_marks! will delete the record and set a global timestamp for the user. If cleanup_read_marks! has already been run, there's no ReadMark to delete.

from unread.

zx1986 avatar zx1986 commented on May 21, 2024

I am using devise for Users.
But when I register a new user, all the Posts are READ for the new user.
So I am looking for the mark_as_unread method for the new user.
I knew this is so wrong ....

How come?
Did I miss something?

from unread.

jarinudom avatar jarinudom commented on May 21, 2024

Seems like the best way to go about it for items that are shared between users is to use a join table as the model for determining whether or not something is read.

For example, you might have the following (p.s. none of this is tested so it may not work):

class User
  acts_as_reader
  has_many :participations
  has_many :conversations, through: :participations

  def unread_conversations
    Conversation.find(Participation.where(user: self).unread_by(self).pluck(:conversation_id))
  end
end

class Participation
  acts_as_readable on: :updated_at
  belongs_to :user
  belongs_to :conversation
end

class Conversation
  has_many :participations
  has_many :users, through: :participations

  def mark_unread_for(user)
    participations.where(user: user).first.touch
  end
end

from unread.

arusa avatar arusa commented on May 21, 2024

For me it works this way:
post.read_mark(current_user).destroy!

from unread.

Related Issues (20)

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.