How to Model "Likes" in Rails

How do you model Likes in rails?

To elaborate further on my comment to Brandon Tilley's answer, I would suggest the following:

class User < ActiveRecord::Base
# your original association
has_many :things

# the like associations
has_many :likes
has_many :liked_things, :through => :likes, :source => :thing
end

class Like < ActiveRecord::Base
belongs_to :user
belongs_to :thing
end

class Thing < ActiveRecord::Base
# your original association
belongs_to :user

# the like associations
has_many :likes
has_many :liking_users, :through => :likes, :source => :user
end

How to like a track and view all liked tracks on my Like index page in my rails app?

Yes, your logic is a bit weird here, you can simplify everything with the following:

  1. Drop the Like model and database table (not sure why do you want to attach a photo here?)
  2. Change the LikedTrack to belong to User instead of Like
  3. Rename the LikedTrack to Like

Now you only need to create a new Like record when user clicks the "heart" button, it should take the track_id and user_id as arguments behind your form.

Rails 5 adding Likes to Articles and Comments

I just figured it out, actually.

class Like < ApplicationRecord
belongs_to :user
belongs_to :article
# belongs_to :comment
end

Commenting the above out, it allows the @article "like" to save without a comment being referenced. Article likes are saved properly. However, article.likes.count still increments whenever an article.comment is liked. This means article.likes is always >= article.comments.likes; which is completely fine.

I just changed the @article.likes to:

  <%= "#{@article.likes.where(comment_id: nil).count}" %>

Filtering out all the strictly article.likes. The comment.likes still work perfectly.

Liking a comment in rails

You should use Polymorphic Association here. But I notice that you have the wrong understanding of Polymorphic Association in the above explanation because you are referencing Blog & Comment via blog_id & comment_id respectively in the Like model instead of referencing those through likeable(i.e., likeable_id & likeable_type). Follow the below steps for better understanding.

  • Generate Like model
rails g model Like user:references likeable:references{polymorphic}
  • Like model migration should look like this
class CreateLikes < ActiveRecord::Migration[6.1]
def change
create_table :likes do |t|
t.references :user, null: false, foreign_key: true
t.references :likeable, polymorphic: true, null: false

t.timestamps
end
end
end
  • Like model
class Like < ApplicationRecord
belongs_to :user
belongs_to :likeable, polymorphic: true
end
  • Blog model
class Blog < ApplicationRecord
has_many :likes, as: :likeable
end
  • Comment model
class Comment < ApplicationRecord
has_many :likes, as: :likeable
end
  • Table entries of Like model should look similar to this
 => #<Like:0x00# id: 1, user_id: 1, likeable_id: 1, likeable_type: "Blog", created_at: <timestamp>, updated_at: <timestamp>>

=> #<Like:0x00# id: 2, user_id: 1, likeable_id: 2, likeable_type: "Comment", created_at: <timestamp>, updated_at: <timestamp>>

Building a form for a like button in a polymorphic relationship in Rails

This should work:

= form_for([@post, @post.likes.find_by(user_id: current_user.id)], html: {method: :delete}) do |f|

url: post_like_path(@post) in your code expects a second argument (the like object). That's what throws the error.
But you don't need it actualy if you put the nested resources as an array in the first argument of the form_for helper.

If the record passed to form_for is a resource, i.e. it corresponds to
a set of RESTful routes, e.g. defined using the resources method in
config/routes.rb. In this case Rails will simply infer the appropriate
URL from the record itself.
(source: http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for)

You can pass an array of resources if your resource is nested within another resource.

Now... You probably want to re-use this code for your other polymorphic models as well. You can do this by passing @post, or @comment to your partial like this:

= render :partial => 'like_button', locals: {likable: @post}

and refactor your partial like this:

= form_for([likable, likable.likes.find_by(user_id: current_user.id)], html: { method: :delete}) do |form|

Limit user to 1 like?

I think you could create additional model:

class CommentLike
belongs_to :comment
belongs_to :user
validates :user, uniqueness: { scope: :comment}
end

class User
has_many :comment_likes
end

class Comment
has_many :comment_likes
end

def like
@comment = Comment.find(params[:id])
if current_user.comment_likes.create(comment: @comment)
@comment.increment!(:likes)
@comment.create_activity :like
flash[:success] = 'Thanks for liking!'
else
flash[:error] = 'Two many likes'
end
redirect_to(:back)
end

It'll solves you problem. If storing likes_count in comment is neccessary, you could use Rails' counter_cache.

How to get post with maximum likes or post with likes counts in rails

Use counter_cache so that you always have a count of likes on the Post objects, then you can call Post.maximum(:likes_count).first to retrieve the one post that has the most likes. Likewise, any Post query will include a post's like count.



Related Topics



Leave a reply



Submit