Greg Answer

Joined

970 Experience
9 Lessons Completed
0 Questions Solved

Activity

Posted in has_one association on polymorphic model

I'm trying to build an activity feed based on user selected conditions.

Example:

  • user follows Comments 1, 2, and 3
  • user follows Note 4, 5, and 6
  • user would like to be notified about Comments on Notes they follow
  • show the activities ONLY for these models

There will be an Activity feed for all Activities at example.com/activities.

The user can Follow different records and when the user goes to example.com/followings they will see only activities for records they follow.

class Following < ActiveRecord::Base
  belongs_to :followable, polymorphic: true
  belongs_to :user 
end

I'm sorry if I'm being too vague. I'm trying to figure out the best way to go about this. I would like to use some kind of OR query without adding an additional gem. Example:

# Grab the ids of the models the user is "following"
@note_ids = current_user.followings.where(followable_type: "Note").pluck(:followable_id)
@comment_ids = current_user.followings.where(followable_type: "Comment").pluck(:followable_id)
@comment_ids += Comment.where(commentable_type: "Note", commentable_id: @note_ids).ids

# Get the activities that occurred on those models
@activities = Activity
  .where(trackable_type: "Comment", trackable_id: @comment_ids)
  .or(trackable_type: "Note", trackable_id: @note_ids)
  .limit(20)

I do have the Ransack gem installed. Maybe I could use it somehow? I'll keep searching till I find a viable solution. I really appreciate your help Chris.

EDIT:

So far this is the best solution I've found (tested in IRB with slightly different variable and attribute names):

# Get the Note and Comment ids
@note_ids = current_user.followings.where(followable_type: "Note").pluck(:followable_id)
@comment_ids = current_user.followings.where(followable_type: "Comment").pluck(:followable_id)
@comment_ids += Comment.where(commentable_type: "Note", commentable_id: @note_ids).ids

# Get the activities
input = { "Comment" => @comment_ids, "Note" => @note_ids }
Activity.where("trackable_type = ? AND trackable_id IN (?) OR trackable_type = ? AND trackable_id IN (?)", *input.flatten)

This returns 8 activities (5 Comments, 3 Notes) based on my sample data. This will work untill I find a more optimal solution. Thanks for all your help.

Posted in has_one association on polymorphic model

Awesome response time Chris!

This solution feels simple enough. I believe I can remove the following line from the Activity class:

has_one :comment, as: :trackable

My only concern is that there could be a lot of queries depending on how many times I have to do something like the following (untested code):

@comment_ids = Comment.where(commentable_type: "Note", commentable_id: [1,2,3]).pluck(:id)
@note_ids = Note.where(user_id: [4, 5, 6]).ids
@note_ids += Note.where("created_at > ? ", 10.days.ago).ids
# additional model ids...

@activity_ids = Activity.where(trackable_type: "Comment", trackable_id: @comment_ids).ids
@activity_ids += Activity.where(trackable_type: "Note", trackable_id: @note_ids).ids
# additional Activity ids...

@activities = Activity.find(@activity_ids).order(created_at: :desc).limit(20)

where I'm trying to build a list of Activities based on specific criteria. Is there a way to optimize this?

Posted in has_one association on polymorphic model

I have the following models (stripped down for simplicity) :

class Activity < ActiveRecord::Base
  belongs_to :trackable, polymorphic: true
  belongs_to :user
  has_one :comment, as: :trackable
end

class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
  belongs_to :user
end

class Note < ActiveRecord::Base
  belongs_to :user
  has_many :comments
end

There are Notes with the ids 1, 2, and 3. There are Comments on these notes.
I would like to get the ids for the Activities where a Comment was created on any of these Notes.

I run the following query:

Activity.where({
    trackable_type: "Comment",
    action: "comment.create",
    comments: { commentable_type: "Note", commentable_id: [1,2, 3] }
  })
  .joins(:comment)
  .ids

But the result is empty.

QUESTION: What association do I have to add to the Activity model to make it join the comment model in this query?