Я изучаю Rails и пытаюсь создать сайт с вложенными полиморфными комментариями.
Я следовал этому руководству http://www.tweetegy.com/2013/04/create-nested-comments-in-rails-using-ancestry-gem/, а также некоторые RailsCast (262-trees-with-ancestry и 154-polymorphic- ассоциация).
Мне удалось создать вложенные полиморфные комментарии (когда я проверяю консоль рельсов для каждого комментария). Однако проблема, с которой я сталкиваюсь, заключается в выводе комментариев. Все они отображаются на странице показа каждого ресурса, а не на соответствующей странице показа. Другими словами, все комментарии отображаются на /videos/1 и videos/2, и на уроках/1, и на уроках/3 (одни и те же комментарии отображаются на каждой странице).
Я подозреваю, что моя проблема в файле comments_helper.rb или /lib/commentable.rb, однако мне не удалось отладить проблему.
Маршруты
config/routes.rb
devise_for :users
resources :videos do
resources :comments
end
resources :lessons do
resources :comments
end
Контроллеры
приложение/контроллеры/comments_controller.rb
class CommentsController < ApplicationController
def new
@parent_id = params.delete(:parent_id)
@commentable = find_commentable
@comment = Comment.new( :parent_id => @parent_id,
:commentable_id => @commentable.id,
:commentable_type => @commentable.class.to_s)
end
def create
@commentable = find_commentable
@comment = @commentable.comments.build(comment_params)
@comment.user_id = current_user.id
if @comment.save
flash[:notice] = "Successfully created comment."
redirect_to @commentable
else
flash[:error] = "Error adding comment."
end
end
private
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
def comment_params
params.require(:comment).permit(:body, :parent_id, :commentable_id, :commentable_type)
end
end
приложение/контроллеры/lessons_controller.rb
class LessonsController < ApplicationController
include Commentable
...
end
приложение/контроллеры/videos_controller.rb
class VideosController < ApplicationController
include Commentable
...
end
Модели
приложение/модели/comment.rb
class Comment < ActiveRecord::Base
has_ancestry
belongs_to :user
belongs_to :commentable, polymorphic: true
end
приложение/модели/урок.рб
class Lesson < ActiveRecord::Base
has_many :comments, :as => :commentable, :dependent => :destroy
end
приложение/модели/видео.рб
class Video < ActiveRecord::Base
has_many :comments, :as => :commentable, :dependent => :destroy
end
приложение/модели/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :comments, :as => :commentable, :dependent => :destroy
end
Помощники
приложение/помощники/comments_helper.rb
module CommentsHelper
def nested_comments(comments)
comments.map do |comment, sub_comments|
content_tag(:div, render(comment), :class => "media media-nested")
end.join.html_safe
end
end
Либ
/lib/commentable.rb
require 'active_support/concern'
module Commentable
extend ActiveSupport::Concern
included do
before_filter :comments, :only => [:show]
end
def comments
@commentable = find_commentable
@comments = @commentable.comments.arrange(:order => :created_at)
@comment = Comment.new
end
private
def find_commentable
return params[:controller].singularize.classify.constantize.find(params[:id])
end
end
Схема
create_table "comments", force: true do |t|
t.text "body"
t.integer "user_id"
t.integer "commentable_id"
t.string "commentable_type"
t.datetime "created_at"
t.datetime "updated_at"
t.string "ancestry"
end
add_index "comments", ["ancestry"], name: "index_comments_on_ancestry"
Просмотры
Уроки и просмотры show.html.erb
<div class="tab-pane" id="comments">
<%= nested_comments @comments %>
<%= render "comments/form" %>
</div>
приложение/просмотры/комментарии/_form.html.erb
<%= form_for [@commentable, @comment] do |f| %>
<%= f.hidden_field :parent_id %>
<p>
<%= f.label :body, "New comment" %>
</p>
<%= f.text_area :body, :rows => 4 %>
<p>
<%= f.submit "Post Comment" %>
</p>
<% end %>
приложение/представления/комментарии/_comment.html.erb
<div class="media-body">
<h4 class="media-heading"><%= comment.user.username %></h4>
<i>
<%= comment.created_at.strftime('%b %d, %Y at %H:%M') %>
</i>
<p>
<%= simple_format comment.body %>
</p>
<div class="actions">
<%= link_to "Reply", new_polymorphic_path([@commentable, Comment.new], :parent_id => comment) %>
</div>
<%= nested_comments comment.children %>
</div>
Любые отзывы или идеи будут высоко оценены. Спасибо ;)