Add comments to photos (#4130)

* Add comments to photos

Extend the photo show page to support comments by logged in users.

- Make the Comment model polymorphic.
- Update the Photo and Post models to have comments.
- Update the comments controller to handle the polymorphic association.
- Update the photo show page to display comments and a comment form.
- Create a reusable comments partial.

* Add migration

* Fix tests

* Fix tests

* Slightly fix tests

* Fix variables

* Add field

* Refactor slightly

* Refactor slightly

* Refactor slightly

* Refactor

* Photos respond to this as well

* Refactor to polymorphic_url

* Rename

* Wrong relationship

* Refactor and fix tests

* Fix relationships

* Fix rendering

* Fix tests

* Fix model tests

* Fix test

* Fix test

* Fix test

* Fix test

* Fix controller spec

* Fix view tests

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: Daniel O'Connor <daniel.oconnor@gmail.com>
This commit is contained in:
google-labs-jules[bot]
2025-08-24 21:10:16 +09:30
committed by GitHub
parent 79a54351e3
commit 8564ec7a7c
37 changed files with 219 additions and 112 deletions

View File

@@ -13,43 +13,55 @@ class CommentsController < ApplicationController
end
def new
@commentable = find_commentable
@comment = Comment.new
@post = Post.find_by(id: params[:post_id])
if @post
@comments = @post.comments
if @commentable
@comments = @commentable.comments
respond_with(@comments)
else
redirect_to(request.referer || root_url,
alert: "Can't post a comment on a non-existent post")
alert: "Can't post a comment on a non-existent commentable")
end
end
def edit
@comments = @comment.post.comments
# TODO: Why does this need a collection of comments?
@comments = @comment.commentable.comments
@commentable = @comment.commentable
end
def create
@comment = Comment.new(comment_params)
@commentable = @comment.commentable
@comment.author = current_member
@comment.save
respond_with @comment, location: @comment.post
respond_with @comment, location: @commentable
end
def update
@comment.update(body: comment_params['body'])
respond_with @comment, location: @comment.post
respond_with @comment, location: @comment.commentable
end
def destroy
@post = @comment.post
@commentable = @comment.commentable
@comment.destroy
respond_with(@post)
respond_with(@commentable)
end
private
def find_commentable
return unless params[:comment]
if params[:comment][:commentable_type] == 'Photo'
Photo.find(params[:comment][:commentable_id])
elsif params[:comment][:commentable_type] == 'Post'
Post.find(params[:comment][:commentable_id])
end
end
def comment_params
params.require(:comment).permit(:body, :post_id)
params.require(:comment).permit(:body, :commentable_id, :commentable_type)
end
end

View File

@@ -21,6 +21,7 @@ class PhotosController < ApplicationController
def show
@crops = Crop.distinct.joins(:photo_associations).where(photo_associations: { photo: @photo })
@comment = Comment.new(commentable: @photo)
respond_with(@photo)
end

View File

@@ -2,26 +2,27 @@
class Comment < ApplicationRecord
belongs_to :author, class_name: 'Member', inverse_of: :comments
belongs_to :post, counter_cache: true
belongs_to :commentable, polymorphic: true, counter_cache: true
# validates :body, presence: true
scope :post_order, -> { order(created_at: :asc) } # for display on post page
after_create do
recipient = post.author.id
recipient = commentable.author.id
sender = author.id
# don't send notifications to yourself
if recipient != sender
Notification.create(
recipient_id: recipient,
sender_id: sender,
subject: "#{author} commented on #{post.subject}",
subject: "#{author} commented on #{commentable.subject}",
body:,
post_id: post.id
notifiable: commentable
)
end
end
def to_s
"#{author.login_name} commented on #{post.subject}"
"#{author.login_name} commented on #{commentable.subject}"
end
end

View File

@@ -10,7 +10,8 @@ class Follow < ApplicationRecord
recipient_id: followed_id,
sender_id: follower_id,
subject: "#{follower.login_name} is now following you",
body: "#{follower.login_name} just followed you on #{ENV.fetch('GROWSTUFF_SITE_NAME', nil)}. "
body: "#{follower.login_name} just followed you on #{ENV.fetch('GROWSTUFF_SITE_NAME', nil)}. ",
notifiable: self
)
end
end

View File

@@ -3,7 +3,7 @@
class Notification < ApplicationRecord
belongs_to :sender, class_name: 'Member', inverse_of: :sent_notifications
belongs_to :recipient, class_name: 'Member', inverse_of: :notifications
belongs_to :post, optional: true
belongs_to :notifiable, polymorphic: true
validates :subject, length: { maximum: 255 }

View File

@@ -8,6 +8,7 @@ class Photo < ApplicationRecord
PHOTO_CAPABLE = %w(Garden Planting Harvest Seed Post Crop).freeze
has_many :photo_associations, dependent: :delete_all, inverse_of: :photo
has_many :comments, as: :commentable, dependent: :destroy
# This doesn't work, ActiveRecord tries to use the polymoriphic photographable
# relationship instead.
@@ -83,6 +84,14 @@ class Photo < ApplicationRecord
"#{title} by #{owner.login_name}"
end
def subject
title
end
def author
owner
end
def flickr_photo_id
source_id if source == 'flickr'
end

View File

@@ -3,6 +3,7 @@
class Post < ApplicationRecord
extend FriendlyId
include Likeable
friendly_id :author_date_subject, use: %i(slugged finders)
include PhotoCapable
@@ -10,9 +11,10 @@ class Post < ApplicationRecord
# Relationships
belongs_to :author, class_name: 'Member', inverse_of: :posts
belongs_to :forum, optional: true
has_many :comments, dependent: :destroy
has_many :comments, as: :commentable, dependent: :destroy
has_many :crop_posts, dependent: :delete_all
has_many :crops, through: :crop_posts
has_many :notifications, as: :notifiable, dependent: :destroy
after_create :send_notification
#
@@ -95,6 +97,7 @@ class Post < ApplicationRecord
Notification.create(
recipient_id:,
sender_id: sender,
notifiable: self,
subject: "#{author} mentioned you in their post #{subject}",
body:
)

View File

@@ -1,12 +1,11 @@
%a{ name: "comments" }
- if post.comments
- if commentable.comments
%hr/
%h2
= comment_icon
= localize_plural(post.comments, Comment)
- post.comments.post_order.each do |comment|
= localize_plural(commentable.comments, Comment)
- commentable.comments.post_order.each do |comment|
= render "comments/single", comment: comment
- else
%h2 There are no comments yet

View File

@@ -1 +1 @@
#{link_to 'commented', event_model} on #{link_to event_model.post, event_model.post}
#{link_to 'commented', event_model} on #{link_to event_model.commentable, event_model.commentable}

View File

@@ -1,3 +1,4 @@
- @comment ||= Comment.new(commentable: @commentable)
.card.col-md-8.col-lg-7.mx-auto.float-none.white.z-depth-1.py-2.px-2
.card-body
- if content_for? :title
@@ -14,13 +15,13 @@
%li= msg
.md-form
= f.text_area :body, rows: 6, class: 'form-control md-textarea', autofocus: 'autofocus'
= f.text_area :body, rows: 6, class: 'form-control md-textarea', autofocus: 'autofocus', required: true, pattern: '\w+'
= f.label :body, "Your comment:"
%span.help-block
= render partial: "shared/markdown_help"
.actions.text-right
= f.submit 'Post comment', class: 'btn btn-primary'
- if defined?(@post)
.field
= f.hidden_field :post_id, value: @post.id
.field
= f.hidden_field :commentable_id, value: @commentable.id
= f.hidden_field :commentable_type, value: @commentable.class.name

View File

@@ -2,6 +2,6 @@
%p
Editing comment on
= link_to @comment.post.subject, @comment.post
= link_to @comment.commentable.subject, @comment.commentable
= render 'form'
= render 'form', locals: { comment: @comment, commentable: @comment.commentable }

View File

@@ -5,17 +5,18 @@
%link= comments_url
- @comments.each do |comment|
%item
%title Comment by #{comment.author.login_name} on #{comment.post.subject}
%title Comment by #{comment.author.login_name} on #{comment.commentable.subject}
%description
:escaped_markdown
<p>
Comment on
#{ link_to comment.post.subject, post_url(comment.post) }
#{ link_to comment.commentable.subject, polymorphic_url(comment.commentable) }
</p>
:escaped_markdown
#{ strip_tags markdownify(comment.body) }
%pubdate= comment.created_at.to_fs(:rfc822)
%link= post_url(comment.post)
%link= polymorphic_url(comment.commentable)
%guid= comment_url(comment)

View File

@@ -1,11 +1,17 @@
= content_for :title, "New comment"
- if @commentable.is_a?(Post)
%section.blog-post
.card.post{ id: "post-#{@commentable.id}" }
.card-header
%h2.display-3= @commentable.subject
.card-body= render "posts/single", post: @commentable || @comment.commentable, subject: true
- elsif @commentable.is_a?(Photo)
%section.blog-post
.card.photo{ id: "photo-#{@commentable.id}" }
.card-header
%h2.display-3= @commentable.subject
.card-body= render "photos/card", photo: @commentable || @comment.commentable, subject: true
%section.blog-post
.card.post{ id: "post-#{@post.id}" }
.card-header
%h2.display-3= @post.subject
.card-body= render "posts/single", post: @post || @comment.post, subject: true
= render partial: "comments/comments", locals: { commentable: @commentable || @comment.commentable }
= render partial: "posts/comments", locals: { post: @post || @comment.post }
= render 'form'
= render 'form', locals: { comment: @comment, commentable: @commentable || @comment.commentable }

View File

@@ -46,4 +46,12 @@
- else
= @photo.license_name
= render "associations", photo: @photo
= render "associations", photo: @photo
.row
- if can? :create, Comment
= link_to new_comment_path(comment: { commentable_type: 'Photo', commentable_id: @photo.id }), class: 'btn' do
= icon 'fas', 'comment'
Comment
.row
.col-md-9
= render 'comments/comments', commentable: @photo

View File

@@ -1,3 +1,4 @@
- @post ||= post if defined?(post)
%p
Posted by
- if @post.author
@@ -13,7 +14,7 @@
and edited at
= @post.updated_at.to_fs(:default)
= link_to "Permalink", post
= link_to "Permalink", @post
:markdown
#{ strip_tags markdownify(@post.body) }

View File

@@ -24,7 +24,7 @@
- content_for :buttonbar do
- if @post.comments.count > 10 && can?(:create, Comment)
= link_to 'Comment', new_comment_path(post_id: @post.id), class: 'btn'
= link_to 'Comment', new_comment_path(comment: { commentable_type: 'Post', commentable_id: @post.id }), class: 'btn'
- content_for :breadcrumbs do
%li.breadcrumb-item= link_to @post.author, @post.author
@@ -48,12 +48,12 @@
= render 'likes/likes', object: @post
.float-right
- if can? :create, Comment
= link_to new_comment_path(post_id: @post.id), class: 'btn' do
= link_to new_comment_path(comment: { commentable_type: 'Post', commentable_id: @post.id }), class: 'btn' do
= icon 'fas', 'comment'
Comment
%section.comments
= render "comments", post: @post
= render "comments/comments", commentable: @post
.col-md-4.col-12
= render @post.author

View File

@@ -0,0 +1,14 @@
class MakeNotificationsPolymorphic < ActiveRecord::Migration[6.1]
def change
add_column :notifications, :notifiable_type, :string
rename_column :notifications, :post_id, :notifiable_id
reversible do |dir|
dir.up do
ActiveRecord::Base.connection.execute("UPDATE notifications SET notifiable_type = 'Post' WHERE notifiable_type IS NULL")
end
end
add_index :notifications, %i(notifiable_type notifiable_id)
end
end

View File

@@ -0,0 +1,14 @@
class ChangeCommentsPolymorphic < ActiveRecord::Migration[7.2]
def change
add_column :comments, :commentable_type, :string
rename_column :comments, :post_id, :commentable_id
add_index :comments, %i(commentable_type commentable_id)
reversible do |dir|
dir.up do
ActiveRecord::Base.connection.execute("UPDATE comments SET commentable_type = 'Post' WHERE commentable_type IS NULL")
end
end
end
end

View File

@@ -0,0 +1,24 @@
# frozen_string_literal: true
class AddPhotosCommentCount < ActiveRecord::Migration[7.2]
def change
change_table :photos do |t|
t.integer :comments_count, default: 0
end
reversible do |dir|
dir.up { set_counter_value }
end
end
def set_counter_value
execute <<-SQL.squish
UPDATE photos
SET comments_count = (
SELECT count(1)
FROM comments
WHERE comments.commentable_id = comments.id
AND comments.commentable_type = 'Photo'
)
SQL
end
end

View File

@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.2].define(version: 2024_09_29_041435) do
ActiveRecord::Schema[7.2].define(version: 2025_08_24_085224) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -202,11 +202,12 @@ ActiveRecord::Schema[7.2].define(version: 2024_09_29_041435) do
end
create_table "comments", id: :serial, force: :cascade do |t|
t.integer "post_id", null: false
t.integer "commentable_id", null: false
t.integer "author_id", null: false
t.text "body", null: false
t.datetime "created_at", precision: nil
t.datetime "updated_at", precision: nil
t.string "commentable_type"
end
create_table "crop_companions", force: :cascade do |t|
@@ -470,9 +471,11 @@ ActiveRecord::Schema[7.2].define(version: 2024_09_29_041435) do
t.string "subject"
t.text "body"
t.boolean "read", default: false
t.integer "post_id"
t.integer "notifiable_id"
t.datetime "created_at", precision: nil
t.datetime "updated_at", precision: nil
t.string "notifiable_type"
t.index ["notifiable_type", "notifiable_id"], name: "index_notifications_on_notifiable_type_and_notifiable_id"
end
create_table "orders_products", id: false, force: :cascade do |t|
@@ -505,6 +508,7 @@ ActiveRecord::Schema[7.2].define(version: 2024_09_29_041435) do
t.datetime "date_taken", precision: nil
t.integer "likes_count", default: 0
t.string "source"
t.integer "comments_count", default: 0
t.index ["fullsize_url"], name: "index_photos_on_fullsize_url", unique: true
t.index ["thumbnail_url"], name: "index_photos_on_thumbnail_url", unique: true
end

View File

@@ -35,12 +35,16 @@ describe CommentsController do
let(:post) { FactoryBot.create(:post) }
describe "with valid params" do
before { get :new, params: { post_id: post.id } }
before do
get :new, params: {
comment: { commentable_id: post.id, commentable_type: "Post" }
}
end
let(:old_comment) { FactoryBot.create(:comment, post:) }
let(:old_comment) { FactoryBot.create(:comment, commentable: post) }
it "picks up post from params" do
expect(assigns(:post)).to eq(post)
expect(assigns(:commentable)).to eq(post)
end
it "assigns the old comments as @comments" do
@@ -60,8 +64,8 @@ describe CommentsController do
before { get :edit, params: { id: comment.to_param } }
describe "my comment" do
let!(:comment) { FactoryBot.create(:comment, author: member, post:) }
let!(:old_comment) { FactoryBot.create(:comment, post:, created_at: Time.zone.yesterday) }
let!(:comment) { FactoryBot.create(:comment, author: member, commentable: post) }
let!(:old_comment) { FactoryBot.create(:comment, commentable: post, created_at: Time.zone.yesterday) }
it "assigns previous comments as @comments" do
expect(assigns(:comments)).to eq([comment, old_comment])
@@ -69,7 +73,7 @@ describe CommentsController do
end
describe "not my comment" do
let(:comment) { FactoryBot.create(:comment, post:) }
let(:comment) { FactoryBot.create(:comment, commentable: post) }
it { expect(response).not_to be_successful }
end
@@ -82,7 +86,7 @@ describe CommentsController do
let(:comment) { FactoryBot.create(:comment, author: member) }
it "redirects to the comment's post" do
expect(response).to redirect_to(comment.post)
expect(response).to redirect_to(comment.commentable)
end
end
@@ -95,12 +99,12 @@ describe CommentsController do
describe "attempting to change post_id" do
let(:post) { FactoryBot.create(:post, subject: 'our post') }
let(:other_post) { FactoryBot.create(:post, subject: 'the other post') }
let(:valid_attributes) { { post_id: other_post.id, body: "kōrero" } }
let(:comment) { FactoryBot.create(:comment, author: member, post:) }
let(:valid_attributes) { { commentable_type: "Post", commentable_id: other_post.id, body: "kōrero" } }
let(:comment) { FactoryBot.create(:comment, author: member, commentable: post) }
it "does not change post_id" do
comment.reload
expect(comment.post_id).to eq(post.id)
expect(comment.commentable_id).to eq(post.id)
end
end
end
@@ -112,7 +116,7 @@ describe CommentsController do
let(:comment) { FactoryBot.create(:comment, author: member) }
it "redirects to the post the comment was on" do
expect(response).to redirect_to(comment.post)
expect(response).to redirect_to(comment.commentable)
end
end

View File

@@ -2,7 +2,7 @@
FactoryBot.define do
factory :comment do
post
association :commentable, factory: :post
author
sequence(:body) { |n| "OMG LOL #{n}" }
# because our commenters are more polite than YouTube's

View File

@@ -10,7 +10,7 @@ FactoryBot.define do
body { "MyText" }
read { false }
post
association :notifiable, factory: :post
factory :no_email_notification do
recipient { FactoryBot.create(:no_email_notifications_member) }

View File

@@ -7,9 +7,9 @@ describe 'Commenting on a post' do
let(:member) { create(:member) }
let(:post) { create(:post, author: member) }
before { visit new_comment_path post_id: post.id }
before { visit new_comment_path(comment: { commentable_type: "Post", commentable_id: post.id }) }
include_examples 'is accessible'
it_behaves_like 'is accessible'
it "creating a comment" do
fill_in "comment_body", with: "This is a sample test for comment"
@@ -20,13 +20,13 @@ describe 'Commenting on a post' do
end
context "editing a comment" do
let(:existing_comment) { create(:comment, post:, author: member) }
let(:existing_comment) { create(:comment, commentable: post, author: member) }
before do
visit edit_comment_path existing_comment
end
include_examples 'is accessible'
it_behaves_like 'is accessible'
it "saving edit" do
fill_in "comment_body", with: "Testing edit for comment"

View File

@@ -155,7 +155,7 @@ describe "member profile", :js do
context 'member has comments' do
let(:post) { FactoryBot.create(:post) }
let!(:comment) { FactoryBot.create(:comment, post:, author: member) }
let!(:comment) { FactoryBot.create(:comment, commentable: post, author: member) }
before { visit member_path(member) }
@@ -221,8 +221,8 @@ describe "member profile", :js do
end
context "not signed in" do
include_examples 'member details'
include_examples 'member activity'
it_behaves_like 'member details'
it_behaves_like 'member activity'
it "no bio" do
member.update! bio: nil
@@ -233,8 +233,8 @@ describe "member profile", :js do
context "signed in member" do
include_context 'signed in member'
include_examples 'member details'
include_examples 'member activity'
it_behaves_like 'member details'
it_behaves_like 'member activity'
context "your own profile page" do
before { visit member_path(member) }

View File

@@ -188,8 +188,8 @@ rest of the garden.
describe 'posts' do
it 'loads posts#show' do
FactoryBot.create(:comment, post:)
FactoryBot.create(:comment, post:)
FactoryBot.create(:comment, commentable: post)
FactoryBot.create(:comment, commentable: post)
visit post_path(post)
page.percy_snapshot(page, name: "#{prefix}/posts#show")
end
@@ -199,7 +199,7 @@ rest of the garden.
FactoryBot.create_list(:post, 12, author: member)
end
Post.all.order(id: :desc).limit(4) do |post|
FactoryBot.create_list(:comment, rand(1..5), post:)
FactoryBot.create_list(:comment, rand(1..5), commentable: post)
end
visit posts_path
page.percy_snapshot(page, name: "#{prefix}/posts#index")
@@ -218,7 +218,7 @@ rest of the garden.
context "when signed out" do
let(:prefix) { 'signed-out' }
include_examples 'visit pages'
it_behaves_like 'visit pages'
it 'loads sign in page' do
visit crops_path # some random page
@@ -247,7 +247,7 @@ rest of the garden.
let(:prefix) { 'signed-in' }
include_context 'signed in member'
include_examples 'visit pages'
it_behaves_like 'visit pages'
it 'load my plantings#show' do
planting = FactoryBot.create(:planting, crop: tomato, owner: member, garden: member.gardens.first)
@@ -329,7 +329,7 @@ rest of the garden.
end
it 'comments#new' do
visit new_comment_path(post_id: post.id)
visit new_comment_path(comment: { commentable_type: Post, commentable_id: post.id })
page.percy_snapshot(page, name: "comments#new")
end
end

View File

@@ -41,7 +41,7 @@ describe ApplicationHelper do
context 'with a populated collection' do
context 'with one element' do
before { create(:comment, post:) }
before { create(:comment, commentable: post) }
it 'returns a string with the quantity and the plural of the model' do
expect(localize_plural(post.comments, Comment)).to eq '1 comment'
@@ -49,7 +49,7 @@ describe ApplicationHelper do
end
context 'with more than one element' do
before { create_list(:comment, 2, post:) }
before { create_list(:comment, 2, commentable: post) }
it 'returns a string with the quantity and the plural of the model' do
expect(localize_plural(post.comments, Comment)).to eq '2 comments'

View File

@@ -7,7 +7,7 @@ describe Comment do
let(:comment) { FactoryBot.create(:comment) }
it "belongs to a post" do
comment.post.should be_an_instance_of Post
comment.commentable.should be_an_instance_of Post
end
it "belongs to an author" do
@@ -26,17 +26,17 @@ describe Comment do
@c = FactoryBot.create(:comment)
@n = Notification.first
@n.sender.should eq @c.author
@n.recipient.should eq @c.post.author
@n.recipient.should eq @c.commentable.author
@n.subject.should include 'commented on'
@n.body.should eq @c.body
@n.post.should eq @c.post
@n.notifiable.should eq @c.commentable # polymorphic association, this is a Post.
end
it "doesn't send notifications to yourself" do
@m = FactoryBot.create(:member)
@p = FactoryBot.create(:post, author: @m)
expect do
FactoryBot.create(:comment, post: @p, author: @m)
FactoryBot.create(:comment, commentable: @p, author: @m)
end.not_to change(Notification, :count)
end
end
@@ -45,8 +45,8 @@ describe Comment do
before do
@m = FactoryBot.create(:member)
@p = FactoryBot.create(:post, author: @m)
@c1 = FactoryBot.create(:comment, post: @p, author: @m)
@c2 = FactoryBot.create(:comment, post: @p, author: @m)
@c1 = FactoryBot.create(:comment, commentable: @p, author: @m)
@c2 = FactoryBot.create(:comment, commentable: @p, author: @m)
end
it 'has a scope for ASC order for displaying on post page' do

View File

@@ -6,7 +6,7 @@ describe Notification do
let(:notification) { FactoryBot.create(:notification) }
it "belongs to a post" do
expect(notification.post).to be_an_instance_of Post
expect(notification.notifiable).to be_an_instance_of Post
end
it "belongs to a recipient" do

View File

@@ -19,22 +19,22 @@ describe Post do
it "has many comments" do
post = FactoryBot.create(:post, author: member)
FactoryBot.create(:comment, post:)
FactoryBot.create(:comment, post:)
FactoryBot.create(:comment, commentable: post)
FactoryBot.create(:comment, commentable: post)
post.comments.size.should == 2
end
it "supports counting comments" do
post = FactoryBot.create(:post, author: member)
FactoryBot.create(:comment, post:)
FactoryBot.create(:comment, post:)
FactoryBot.create(:comment, commentable: post)
FactoryBot.create(:comment, commentable: post)
post.comment_count.should == 2
end
it "destroys comments when deleted" do
post = FactoryBot.create(:post, author: member)
FactoryBot.create(:comment, post:)
FactoryBot.create(:comment, post:)
FactoryBot.create(:comment, commentable: post)
FactoryBot.create(:comment, commentable: post)
post.comments.size.should eq(2)
all = Comment.count
post.destroy
@@ -73,8 +73,8 @@ describe Post do
end
it "sets recent activity to comment time" do
comment = FactoryBot.create(:comment, post:,
created_at: 1.hour.ago)
comment = FactoryBot.create(:comment, commentable: post,
created_at: 1.hour.ago)
post.recent_activity.to_i.should eq comment.created_at.to_i
end
@@ -88,7 +88,7 @@ describe Post do
it "new comment on old post is recently active" do
# now comment on an older post
post2 = FactoryBot.create(:post, created_at: 1.minute.ago)
FactoryBot.create(:comment, post:, created_at: 1.second.ago)
FactoryBot.create(:comment, commentable: post, created_at: 1.second.ago)
described_class.recently_active.first.should eq post
described_class.recently_active.second.should eq post2
end

View File

@@ -3,9 +3,12 @@
require 'rails_helper'
describe "comments/edit" do
let(:comment) { FactoryBot.create(:comment) }
before do
controller.stub(:current_user) { nil }
assign(:comment, FactoryBot.create(:comment))
assign(:comment, comment)
assign(:commentable, comment.commentable)
end
it "renders the edit comment form" do

View File

@@ -8,8 +8,8 @@ describe 'comments/index.rss.haml' do
@author = FactoryBot.create(:member)
@post = FactoryBot.create(:post)
assign(:comments, [
FactoryBot.create(:comment, author: @author, post: @post),
FactoryBot.create(:comment, author: @author, post: @post)
FactoryBot.create(:comment, author: @author, commentable: @post),
FactoryBot.create(:comment, author: @author, commentable: @post)
])
render
end

View File

@@ -6,9 +6,10 @@ describe "comments/new" do
before do
controller.stub(:current_user) { nil }
@post = FactoryBot.create(:post, body: 'tena koutou ki te ao')
@comment = FactoryBot.create(:comment, post: @post)
@comment = FactoryBot.create(:comment, commentable: @post)
assign(:comment, @comment)
assign(:comments, [@comment])
assign(:commentable, @post)
render
end

View File

@@ -24,7 +24,7 @@ describe "forums/index" do
context "posts" do
let!(:post) { FactoryBot.create(:forum_post, forum: forum1) }
let!(:comment) { FactoryBot.create(:comment, post:) }
let!(:comment) { FactoryBot.create(:comment, commentable: post) }
before { render }

View File

@@ -22,7 +22,7 @@ describe "posts/_single" do
end
it "doesn't contain a link to new comment" do
assert_select("a", { href: new_comment_path(post_id: @post.id) }, false)
assert_select("a", { href: new_comment_path(comment: { commmentable_type: "Post", commentable_id: @post.id }) }, false)
end
end
@@ -35,7 +35,7 @@ describe "posts/_single" do
end
it "contains link to new comment" do
assert_select("a", { href: new_comment_path(post_id: @post.id) }, "Reply")
assert_select("a", { href: new_comment_path(comment: { commmentable_type: "Post", commentable_id: @post.id }) }, "Reply")
end
it "does not contain an edit link" do
@@ -78,7 +78,7 @@ describe "posts/_single" do
sign_in @member
controller.stub(:current_user) { @member }
@post = FactoryBot.create(:post, author: @member)
@comment = FactoryBot.create(:comment, post: @post)
@comment = FactoryBot.create(:comment, commentable: @post)
@comment.update(body: "I've been updated")
render partial: "comments/single", locals: { comment: @comment }
end
@@ -113,7 +113,7 @@ describe "posts/_single" do
sign_in @member
controller.stub(:current_user) { @member }
@post = FactoryBot.create(:post, author: @member)
@comment = FactoryBot.create(:comment, post: @post)
@comment = FactoryBot.create(:comment, commentable: @post)
@comment.update(updated_at: @comment.created_at)
render partial: "comments/single", locals: { comment: @comment }
end

View File

@@ -61,7 +61,7 @@ describe "posts/show" do
context "when there is one comment" do
let(:post) { FactoryBot.create(:html_post, author:) }
let!(:comment) { FactoryBot.create(:comment, post:) }
let!(:comment) { FactoryBot.create(:comment, commentable: post) }
before do
@comments = post.comments
@@ -85,12 +85,12 @@ describe "posts/show" do
let(:post) { FactoryBot.create(:html_post, author:) }
before do
@comment1 = FactoryBot.create(:comment, post:, body: "F1rst!!!",
@comment1 = FactoryBot.create(:comment, commentable: post, body: "F1rst!!!",
created_at: Date.new(2010, 5, 17))
@comment3 = FactoryBot.create(:comment, post:, body: "Th1rd!!!",
@comment3 = FactoryBot.create(:comment, commentable: post, body: "Th1rd!!!",
created_at: Date.new(2012, 5, 17))
@comment4 = FactoryBot.create(:comment, post:, body: "F0urth!!!")
@comment2 = FactoryBot.create(:comment, post:, body: "S3c0nd!!1!",
@comment4 = FactoryBot.create(:comment, commentable: post, body: "F0urth!!!")
@comment2 = FactoryBot.create(:comment, commentable: post, body: "S3c0nd!!1!",
created_at: Date.new(2011, 5, 17))
@comments = post.comments
render
@@ -121,7 +121,7 @@ describe "posts/show" do
end
it 'shows a comment button' do
expect(subject).to have_link "Comment", href: new_comment_path(post_id: post.id)
expect(subject).to have_link "Comment", href: new_comment_path(comment: { commentable_type: "Post", commentable_id: post.id })
end
end
end

View File

@@ -7,8 +7,8 @@ describe 'posts/show.rss.haml' do
controller.stub(:current_user) { nil }
@author = FactoryBot.create(:member)
@post = FactoryBot.create(:post)
FactoryBot.create(:comment, author: @author, post: @post)
FactoryBot.create(:comment, author: @author, post: @post)
FactoryBot.create(:comment, author: @author, commentable: @post)
FactoryBot.create(:comment, author: @author, commentable: @post)
assign(:post, @post)
render
end