【问题标题】:Remove a comment if user does not exist Ruby on Rails如果用户不存在,则删除评论 Ruby on Rails
【发布时间】:2016-02-05 16:28:09
【问题描述】:

当我尝试访问包含已在数据库中删除的用户的评论的帖子时,我收到错误 undefined method 'email' for nil:NilClass

我想知道:如何删除“即时”不再存在的用户创建的 cmets?

我试过这样的

<%= div_for(comment) do %>
    <% if comment.user.email.nil?%>
        <% comment.destroy %>
    <%else%>
        <p><%= comment.body %></p>
        <p class="comment-submitted-by"><%= time_ago_in_words(comment.created_at) %> ago by
        <%= comment.user.email %></p>
    <%end%> 

但我仍然得到错误。

【问题讨论】:

    标签: ruby-on-rails ruby database null


    【解决方案1】:

    您仍然收到错误,因为您引用了 comment.user.email,而 usernil。您需要检查comment.user.nil?,否则您也有可能因为缺少用户的电子邮件而删除评论(尽管您可能不允许这样做):

    <% if comment.user.nil? %>
      <% comment.destroy %>
    

    即时清理工作既繁琐又繁琐。你想要的是 dependent: :destroy 在你的 User#comments 关联上。

    class User
      has_many :comments, dependent: :destroy
    end
    

    那么当你的User被删除时,他们所有的Comments也会被删除,你不必担心在显示时。

    由于存在孤立的 cmets,您可以使用简单的 SQL 语句将它们清除:

    DELETE FROM comments WHERE user_id NOT IN (
      SELECT id FROM users
    )
    

    或者你的 Rails 控制台:

    Comments.find_each { |c| c.destroy if c.user.nil? }
    

    【讨论】:

    • 很好的答案,这为我解决了很多问题!我有一个后续问题。在我的应用程序中,我有一个用户、链接和 cmets 的模型。一个用户 has_many :links,一个链接 has_many :cmets。如果用户评论了一个不属于他的链接,然后他删除了他的帐户怎么办。然后在我的情况下,他的链接会消失,但从外观上看,如果他的 cmets 会保留。我应该在链接模型中添加什么,以便该用户在该链接上的 cmets 也被破坏?对不起,如果我没有任何意义。
    • 如果用户可以评论其他用户的链接,我假设Commentlink_id, user_id,所以User#has_many :comments, dependent: :destroy应该清除他们的cmets而不影响其他用户的链接。同时删除被破坏的用户链接,User#has_many :links, dependent: :destroy,并在链接被破坏时清理 cmets,Link#has_many :comments, dependent: :destroy。基本上,将:dependent 添加到任何需要清理的关联中。
    • @Kristján Comments.find_each { |c| c.destroy if c.user.nil? } 收到 N+1 个查询问题,应该是 Comment.joins('LEFT OUTER JOIN users ON comments.user_id = users.id').where(users: {id: nil}).destroy_all
    • 感谢优化@HieuPham :)
    • Comments belongs_to :user 在 Comments.rb 中,但在 User.rb 中没有 has_many :cmets。我可以在用户中添加 has_many :cmets 以使依赖: :destroy 工作吗?
    【解决方案2】:

    由于缺少上下文,从线程中删除一些 cmets 可能会导致难以理解剩余的 cmets。

    因此我想建议另一种方法:当用户被删除时,只显示删除的用户而不是用户的电子邮件。

    一个简单的实现可能如下所示:

    <%= div_for(comment) do %>
      <p><%= comment.body %></p>
      <p class="comment-submitted-by">
        <%= time_ago_in_words(comment.created_at) %> ago by
        <%= comment.user ? comment.user.email : 'deleted user' %>
      </p>
    <%end%> 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-12
      • 2023-03-02
      • 2019-02-20
      • 2012-11-07
      • 1970-01-01
      • 1970-01-01
      • 2014-08-19
      • 2016-04-17
      相关资源
      最近更新 更多