【问题标题】:Refactoring a find for children of parent created after a time重构一段时间后创建的父级子级的查找
【发布时间】:2010-12-13 17:18:54
【问题描述】:

我正在尝试查找不是由当前用户创建的日期时间之后创建的任何 cmets。

一开始我是这样做的..

current_user.comments.find(:all, :conditions=>["created_at > ? AND user_id != ?",
                            current_user.last_checked_mail, current_user])

但这里的问题是因为它从用户模型开始,它只能找到由该用户专门制作的 cmets。

因此,我开始搜索与该用户关联的所有 cmets,以及这些 cmets 子项,只要它们的 user_id 不是 current_user 即可

Comment.find(:all, :conditions => ["user_id = ?", current_user]).select { |c|
  c.comments.find(:all, :conditions => ["user_id != ?", current_user])  
}

但似乎仍然会吸引与 current_user 相关的每条评论,而不是他们的孩子。

我的评论模型:

belongs_to  :commentable, :polymorphic => true
has_many    :comments, :as => :commentable

【问题讨论】:

    标签: sql ruby-on-rails syntax find


    【解决方案1】:

    所以您的评论模型中有父关系?使用它!

    class Comment < ActiveRecord::Base
    
       belongs_to :user
       belongs_to :parent, :class_name => "Comment"
    
       def self.after(date)
         where "created_at > ?", date
       end
    
       def self.replies_for(comments)
         where :parent_id => comments.map(&:id)
       end
    
       def self.exclude_user(user_id)
         where "user_id != ?", user_id
       end
    
     end
    
     class User < ActiveRecord::Base
    
        has_many :comments
    
        def new_comments
          comments.after(last_check_mail)
        end
    
        def new_responses
          Comment.replies_for(new_comments).after(last_check_mail).exclude_user(id)
        end
    
     end
    
     current_user.new_responses
    

    PS。这是针对 Rails 3 的。

    【讨论】:

    • 这是一个非常令人兴奋的回应。我在这里学到了很多新东西。唯一的问题是这不排除 OP 制作的 cmets
    • 我试过这个.. 但它似乎没有工作where :commentable_id =&gt; comments.map(&amp;:id), :user_id != user.id
    • 因为这不是哈希的有效语法。我已经更新了一些答案。我看到你正在使用多态性。我把它留给你弄清楚;)
    【解决方案2】:

    试试:

    Comment.find(:all, :conditions => ["created_at > ? AND user_id != ?", current_user.last_checked_mail, current_user])
    

    【讨论】:

    • 嗯,是的,但还需要一个变量。父评论必须归当前用户所有。在这种情况下,所有 cmets 都有一个 commentable_id,即其父评论的 ID。
    • 哦,我明白了。你的问题不是很清楚。因此,您只想选择属于用户拥有的 cmets 的子 cmets?在这种情况下,它会变得一团糟,但你可能想要这样的东西: Comment.find(:all, :joins => :commentable, :conditions => ["created_at > :time AND user_id != :user AND commentable.user_id = :user AND commentable_id 不为空", :time => current_user.last_checked_mail, :user => current_user])
    • 啊,它确实变得丑陋了。我很好奇它是否不必......我得到了这个ActiveRecord::EagerLoadPolymorphicError: Can not eagerly load the polymorphic association :commentable很好奇这是我的错。
    【解决方案3】:

    试试这个:

    Comment.all(:conditions => ["user_id != ? AND parent_id = ? AND created_at > ?",
               current_user.id, current_user.id, current_user.last_checked_mail])
    

    更好的解决方案是在Comment 模型上创建一个named_scope。

    class Comment
    
      named_scope :other_comments, lambda {|u| { :conditions => 
                    ["user_id != ? AND parent_id = ? AND created_at > ?",
                      u.id, u.id, u.last_checked_mail ] }}
    end
    

    现在您可以将其他 cmets 设置为:

    Comment.other_comments(current_user)
    

    编辑 1 更新了基于多态关联的答案:

    class Comment
      def self.other_comments(u)
        Comment.all(
          :joins => "JOIN comments A 
                     ON   A.commentable_type = 'User' AND 
                          A.commentable_id = #{u.id} AND 
                          comments.commentable_type = 'Comment' AND 
                          comments.commentable_id = A.id",
    
          :conditions => ["comments.user_id != ? AND comments.created_at > ?",
                 u.id, u.last_checked_mail]
        )
      end
    end
    

    现在您可以将其他 cmets 设置为:

    Comment.other_comments(current_user)
    

    【讨论】:

    • parent_id 称为commentable_id,这个数字只是引用评论的ID,其中,我需要做出父评论的用户的ID。注释连接在一个多态表中。我会在上面更新。
    • 更新答案看看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多