使用acts_as_tree 插件应该可以很容易地实现。使用安装它
ruby script/plugin install acts_as_tree
app/models/comment.rb
class Comment < ActiveRecord::Base
acts_as_tree :order => 'created_at'
end
db/migrate/20090121025349_create_comments.rb
class CreateComments < ActiveRecord::Migration
def self.up
create_table :comments do |t|
t.references :parent
t.string :title
t.text :content
...
t.timestamps
end
end
def self.down
drop_table :comments
end
end
app/views/comments/_comment.html.erb
<div id="comment_<%= comment.id %>">
<h1><%= comment.title %></h1>
<%= comment.content %>
<%= render :partial => 'comments/comment', :collection => comments.children %>
</div>
app/views/comments/show.html.erb
<div id="comments">
<%= render :partial => 'comments/comment', :object => Comment.find(params[:id]) %>
</div>
魔法发生在show.html.erb 调用<%= render :partial => 'comments/comment', :object => Comment.find(params[:id]) %> 时,这将导致部分递归渲染所有子cmets。如果你想限制深度,可以在局部或模型中进行。
编辑:
这将使您在 HTML 中为每个深度都提供相同间距的所有 cmets。如果您想生成易于阅读的 HTML,只需使用 render(...).gsub(/^/, "\t") 这将递归地工作以及生成良好缩进的 HTML。
我在app/helpers/application_helper.rb中将它组合成我自己的方法
def indented_render(num, *args)
render(*args).gsub(/^/, "\t" * num)
end
所以现在你可以拨打<%= indented_render 1, :partial => 'comments/comment', ... %>
编辑:
修复了示例中缺少关闭 </h1> 标记的问题。