Rails 5:迭代多态模型并找到顶级父级的最佳方法?
Rails 5: Best way to iterate through a polymorphic model and find the top level parent?
编辑:为了尽可能保持透明并为将来的人们提供可行的解决方案,我想解释一下我是如何使用@John Hayes-Reed 的回答来解决我的问题的。我将在下面更新方法和模型。
更新方法:
#User.rb
def self.find_all_user_comments(user)
@comment_hash = []
@user_comments = Comment.where(user_id: user.id)
@user_comments.all.each do |co|
post = co.find_parent_post
@comment_hash.push( { comment: co, post: post} )
end
@comment_hash
end
我从下面的答案中得到的新方法:
#comment.rb
def find_parent_post
return self.commentable if self.commentable.is_a?(Post)
self.commentable.find_parent_post
end
我调用方法的控制器:
#users_controller.rb
def control_panel
@comments = User.find_all_user_comments(current_user)
end
结束编辑
我正在尝试在他们的控制面板中为用户实施 "most recent comments"。可以在 Post
或另一个 comment
.
上留下评论
在我看来,我想显示 comment
的 :body
以及通过哈希创建的 post
。这也适用于 comment
s comment
。幸运的是,评论只能像这样深入两层
Post
Comment
Child Comment # Would like to find the parent post.
Child Comment
Comment
我有一个方法,我将在下面输入,它适用于留在 post 上的 comment
,但在尝试找到 comment
时会中断有一个 commentable_type: "Comment"
.
我唯一的解决办法是有一个 if
声明说 if commentable_type == "Comment"
,找到 那个 评论父,抓住 Post,然后取 Post` 并将其带回那个子评论,然后以这种方式将其推入哈希。
我想知道是否有更有效的方法(AR 或 SQL)来做这样的事情,以便最终我可以找到 comment
的父级 Post
即使它是 comment
的 comment
。
以下是我认为有帮助的所有信息:
架构:
create_table "comments", force: :cascade do |t|
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "commentable_id"
t.string "commentable_type"
t.integer "user_id"
end
create_table "forums", force: :cascade do |t|
t.string "name"
t.text "description"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_forums_on_user_id", using: :btree
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "description"
t.integer "user_id"
t.integer "forum_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["forum_id"], name: "index_posts_on_forum_id", using: :btree
t.index ["user_id"], name: "index_posts_on_user_id", using: :btree
end
...User table omitted for brevity...
型号:
#post model
belongs_to :user
belongs_to :forum
has_many :comments, as: :commentable
#comment model
belongs_to :user
belongs_to :commentable, polymorphic: true
has_many :comments, as: :commentable
现在的方法。当它找到 commentable_type: "Comment"
:
的评论时不会工作
def self.find_all_user_comments(user)
@comment_hash = []
@user_comments = Comment.where(user_id: user.id)
@user_comments.all.each do |co|
post = Post.find(co.commentable_id)
@comment_hash.push( { comment: co, post: post} )
end
@comment_hash
end
查看:
<div class="col-md-10 col-md-offset-1">
<h3>Recent comments:</h3>
<% if @comments.any? %>
<table class="table">
<thead>
<tr>
<th>Comment</th>
<th>Post</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% @comments.each do |co| %>
<tr class="comment-<%= co[:comment].id %>">
<td><%= truncate(co[:comment].body, length: 50) %></td>
<td><%= truncate(co[:post].title, length: 50) %></td>
<td><%= link_to "destroy", comment_path(co[:comment]), remote: true, method: :delete, data: {confirm: "Are you sure you want to delete this comment?"} %></td>
</tr>
<% end %>
</tbody>
</table>
<% end %>
</div>
嗯,找到 post 的一个可能的班轮可能是:
post = (comment.commentable.is_a? Post) ? comment.commentable : comment.commentable.commentable
您可以在您的评论中添加一个方法 class,并使用一些递归来完成工作(从技术上讲不是真正的递归,因为它在第二个实例上调用该方法,但我们可以使用一个类似的概念),大致如下:
def find_parent_post
return self.commentable if self.commentable.is_a?(Post)
self.commentable.find_parent_post
end
如果您想更深入地嵌套评论,这也将成为未来的证明。
编辑:为了尽可能保持透明并为将来的人们提供可行的解决方案,我想解释一下我是如何使用@John Hayes-Reed 的回答来解决我的问题的。我将在下面更新方法和模型。
更新方法:
#User.rb
def self.find_all_user_comments(user)
@comment_hash = []
@user_comments = Comment.where(user_id: user.id)
@user_comments.all.each do |co|
post = co.find_parent_post
@comment_hash.push( { comment: co, post: post} )
end
@comment_hash
end
我从下面的答案中得到的新方法:
#comment.rb
def find_parent_post
return self.commentable if self.commentable.is_a?(Post)
self.commentable.find_parent_post
end
我调用方法的控制器:
#users_controller.rb
def control_panel
@comments = User.find_all_user_comments(current_user)
end
结束编辑
我正在尝试在他们的控制面板中为用户实施 "most recent comments"。可以在 Post
或另一个 comment
.
在我看来,我想显示 comment
的 :body
以及通过哈希创建的 post
。这也适用于 comment
s comment
。幸运的是,评论只能像这样深入两层
Post
Comment
Child Comment # Would like to find the parent post.
Child Comment
Comment
我有一个方法,我将在下面输入,它适用于留在 post 上的 comment
,但在尝试找到 comment
时会中断有一个 commentable_type: "Comment"
.
我唯一的解决办法是有一个 if
声明说 if commentable_type == "Comment"
,找到 那个 评论父,抓住 Post,然后取 Post` 并将其带回那个子评论,然后以这种方式将其推入哈希。
我想知道是否有更有效的方法(AR 或 SQL)来做这样的事情,以便最终我可以找到 comment
的父级 Post
即使它是 comment
的 comment
。
以下是我认为有帮助的所有信息:
架构:
create_table "comments", force: :cascade do |t|
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "commentable_id"
t.string "commentable_type"
t.integer "user_id"
end
create_table "forums", force: :cascade do |t|
t.string "name"
t.text "description"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_forums_on_user_id", using: :btree
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "description"
t.integer "user_id"
t.integer "forum_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["forum_id"], name: "index_posts_on_forum_id", using: :btree
t.index ["user_id"], name: "index_posts_on_user_id", using: :btree
end
...User table omitted for brevity...
型号:
#post model
belongs_to :user
belongs_to :forum
has_many :comments, as: :commentable
#comment model
belongs_to :user
belongs_to :commentable, polymorphic: true
has_many :comments, as: :commentable
现在的方法。当它找到 commentable_type: "Comment"
:
def self.find_all_user_comments(user)
@comment_hash = []
@user_comments = Comment.where(user_id: user.id)
@user_comments.all.each do |co|
post = Post.find(co.commentable_id)
@comment_hash.push( { comment: co, post: post} )
end
@comment_hash
end
查看:
<div class="col-md-10 col-md-offset-1">
<h3>Recent comments:</h3>
<% if @comments.any? %>
<table class="table">
<thead>
<tr>
<th>Comment</th>
<th>Post</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% @comments.each do |co| %>
<tr class="comment-<%= co[:comment].id %>">
<td><%= truncate(co[:comment].body, length: 50) %></td>
<td><%= truncate(co[:post].title, length: 50) %></td>
<td><%= link_to "destroy", comment_path(co[:comment]), remote: true, method: :delete, data: {confirm: "Are you sure you want to delete this comment?"} %></td>
</tr>
<% end %>
</tbody>
</table>
<% end %>
</div>
嗯,找到 post 的一个可能的班轮可能是:
post = (comment.commentable.is_a? Post) ? comment.commentable : comment.commentable.commentable
您可以在您的评论中添加一个方法 class,并使用一些递归来完成工作(从技术上讲不是真正的递归,因为它在第二个实例上调用该方法,但我们可以使用一个类似的概念),大致如下:
def find_parent_post
return self.commentable if self.commentable.is_a?(Post)
self.commentable.find_parent_post
end
如果您想更深入地嵌套评论,这也将成为未来的证明。