【问题标题】:Rails 5 adding Likes to Articles and CommentsRails 5 为文章和评论添加点赞
【发布时间】:2019-01-26 03:34:31
【问题描述】:

Rails 5,我正在尝试在不依赖 gem 的情况下从头开始添加 Likes。我非常接近让它下来,但是当评论参与其中时,我完全被正在发生的事情所困扰。

存储和保存 article.likes 效果很好。然后我得到了评论。喜欢工作。现在,当我喜欢评论时,他们会单独存储一个新的喜欢(太棒了!),除了现在文章没有正确保存任何喜欢,甚至更奇怪:article.likes.count 给出了它所有 cmets 喜欢的总和。我确信这是一个简单的解决方法,但我完全想念它,我已经尝试了一切。为此,我已经钻了一些很深的兔子洞。

我认为问题在于路由,或者模型之间的关系。

文章评论多,点赞多。 以下是以 like.rb 开头的模型:

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

   # Make sure that one user can only have one like per post or comment
   validates :user_id, uniqueness: { scope: [:article_id, :comment_id] }

 end

article.rb

class Article < ApplicationRecord

  belongs_to :user

  ...

  # destroy associated comments on article deletion
  has_many :comments, dependent: :destroy

  has_many :likes, dependent: :destroy

end

comment.rb

class Comment < ApplicationRecord
  belongs_to :article
  belongs_to :user

  ...

  has_many :likes, dependent: :destroy

end

routes.rb

  ...
  resources :articles, :path => 'blog' do
    resources :likes, only: [:create, :destroy]

    resources :comments do
      resources :likes, only: [:create, :destroy]
    end

  end

多肉的 likes_controller.rb。注意#{},一切都按照它应该的方式检查,那么为什么comment.likes.create 保存正确,但article.likes.create 没有?请帮忙。

class LikesController < ApplicationController
  before_action :get_signed_in_user
  before_action :comment_or_article

  def create
    if @comment_like
      like_resource(comment)
    else
      like_resource(article)
    end
  end

  def destroy
    if @comment_like
      comment.likes.where(user: current_user).destroy_all
    else
      article.likes.where(user: current_user).destroy_all
    end
    flash[:success] = "Unliked! :("
    redirect_to article_redirect(article)
  end

  private
  def like_resource(obj)
    if obj.likes.where(user: current_user.id).present?
      flash[:error] = "You've already upvoted this! + #{like_params} + #{@comment_like} + #{obj}"
    if @comment_like
      if obj.likes.create(user: current_user, article: @article)
        flash[:success] = "Upvoted Comment! + #{like_params} + #{@comment_like} + #{obj}"
      else
          flash[:error] = "An error prevented you from upvoting."
      end
    elsif obj.likes.create(user: current_user)
      flash[:success] = "Upvoted Blog! + #{like_params} + #{@comment_like} + #{obj}"
    else
      flash[:error] = "An error prevented you from upvoting."
    end
    redirect_to article_path(article)
  end

  def get_signed_in_user
    unless user_signed_in?
      flash[:error] = "Sign in to upvote!"
      redirect_back(fallback_location: articles_path)
    end
  end

  # decide what we are liking
  def comment_or_article
    if comment
      @comment_like = true
    else
      @comment_like = false
    end
  end

  def article
    @article = Article.find(params[:article_id])
  end

  def comment
    unless params[:comment_id].nil?
      @comment = article.comments.find(params[:comment_id])
    end
  end

  def like_params
    params.permit( :article_id, :comment_id).merge(user_id: current_user.id)
  end
end

最后是我的文章/show.html.erb 中的点赞按钮:

<%= link_to "Like", article_likes_path(@article), method: :post %>
<%= "#{@article.likes.count}" %>

... # inside loop to show comments:
<%= link_to "Like", article_comment_likes_path(@article, comment), method: :post %>
<%= "#{comment.likes.count}" %>

TLDR: 评论喜欢工作正常,保存好,单独计算好。 文章点赞不保存,但是article.likes.count === article.cmets.likes.count。为什么? 我希望 article.likes 完全独一无二,就像它自己的 cmets 一样。

提前谢谢你。

编辑:取出like.rb中的belongs_to :comments并将like_controller.rb主函数重构为

 private
  def like_resource(obj)
    if obj.likes.where(user: current_user.id).present?
      flash[:error] = "You've already upvoted this!"
    elsif obj.likes.create(user: current_user, article: @article)
      flash[:success] = "Upvoted!"
    else
      flash[:error] = "An error prevented you from upvoting."
    end
    redirect_to article_path(article)
  end

点赞评论时,始终提供@article 会有所帮助。类似的文章不需要comment_id 来保存。

抱歉发了这么长的帖子,希望对大家有所帮助。

【问题讨论】:

    标签: ruby-on-rails ruby model-view-controller model routes


    【解决方案1】:

    实际上,我只是想通了。

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

    注释掉上面的内容,它允许@article“喜欢”保存而不引用注释。文章喜欢被正确保存。但是,article.likes.count 仍然会在 article.comment 被点赞时增加。这意味着 article.likes 总是 >= article.cmets.likes;这完全没问题。

    我刚刚将@article.likes 更改为:

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

    过滤掉所有严格的article.likes。 comment.likes 仍然可以正常工作。

    【讨论】:

    • 一个建议:您的关联没问题,但它对数据库不友好。如您所见,Like 模型用于CommentArticle,因此您需要在三个模型之间定义多态关联。它更像是 Rails。 :)
    • 谢谢@Emu,我会继续阅读的。有没有什么明确的例子可以说明如何在不破坏它的情况下使其成为多态关联?
    • Rails guides 是最好的地方:guides.rubyonrails.org/… 或者,如果你仍然不相信,你可以谷歌它。 (Rails Casts 也有视频)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多