Skip to content

Commit

Permalink
FIX: First Quote badge bust
Browse files Browse the repository at this point in the history
Feature: track quoted posts
  • Loading branch information
SamSaffron committed Jul 15, 2014
1 parent 4c25fed commit 2d0def9
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 9 deletions.
1 change: 1 addition & 0 deletions app/controllers/posts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ def update
revisor = PostRevisor.new(post)
if revisor.revise!(current_user, params[:post][:raw], edit_reason: params[:post][:edit_reason])
TopicLink.extract_from(post)
QuotedPost.extract_from(post)
end

if post.errors.present?
Expand Down
15 changes: 7 additions & 8 deletions app/models/badge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,16 @@ module Queries
SQL

FirstQuote = <<SQL
SELECT l.user_id, l.post_id, l.created_at granted_at
SELECT ids.user_id, q.post_id, q.created_at granted_at
FROM
(
SELECT MIN(l1.id) id
FROM topic_links l1
JOIN badge_posts p1 ON p1.id = l1.post_id
JOIN badge_posts p2 ON p2.id = l1.link_post_id
WHERE NOT reflection AND quote
GROUP BY l1.user_id
SELECT p1.user_id, MIN(q1.id) id
FROM quoted_posts q1
JOIN badge_posts p1 ON p1.id = q1.post_id
JOIN badge_posts p2 ON p2.id = q1.quoted_post_id
GROUP BY p1.user_id
) ids
JOIN topic_links l ON l.id = ids.id
JOIN quoted_posts q ON q.id = ids.id
SQL

FirstLink = <<SQL
Expand Down
5 changes: 4 additions & 1 deletion app/models/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def recover!
super
update_flagged_posts_count
TopicLink.extract_from(self)
QuotedPost.extract_from(self)
if topic && topic.category_id && topic.category
topic.category.update_latest
end
Expand Down Expand Up @@ -336,7 +337,9 @@ def rebake!(opts={})
update_columns(cooked: new_cooked, baked_at: Time.new, baked_version: BAKED_VERSION)

# Extracts urls from the body
TopicLink.extract_from self
TopicLink.extract_from(self)
QuotedPost.extract_from(self)

# make sure we trigger the post process
trigger_post_process(true)

Expand Down
46 changes: 46 additions & 0 deletions app/models/quoted_post.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class QuotedPost < ActiveRecord::Base
belongs_to :post
belongs_to :quoted_post, class_name: 'Post'

# NOTE we already have a path that does this for topic links,
# however topic links exclude quotes and links within a topic
# we are double parsing this fragment, this may be worth optimising later
def self.extract_from(post)

doc = Nokogiri::HTML.fragment(post.cooked)

uniq = {}
ids = []

doc.css("aside.quote[data-topic]").each do |a|
topic_id = a['data-topic'].to_i
post_number = a['data-post'].to_i

next if topic_id == 0 || post_number == 0
next if uniq[[topic_id,post_number]]
uniq[[topic_id,post_number]] = true


# It would be so much nicer if we used post_id in quotes
results = exec_sql "INSERT INTO quoted_posts(post_id, quoted_post_id, created_at, updated_at)
SELECT :post_id, id, current_timestamp, current_timestamp
FROM posts
WHERE post_number = :post_number AND
topic_id = :topic_id
RETURNING quoted_post_id
", post_id: post.id, post_number: post_number, topic_id: topic_id

results = results.to_a

if results.length > 0
ids << results[0]["quoted_post_id"].to_i
end
end

if ids.length > 0
exec_sql "DELETE FROM quoted_posts WHERE post_id = :post_id AND quoted_post_id NOT IN (:ids)",
post_id: post.id, ids: ids
end

end
end
1 change: 1 addition & 0 deletions app/models/topic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,7 @@ def add_moderator_post(user, text, opts={})

# Grab any links that are present
TopicLink.extract_from(new_post)
QuotedPost.extract_from(new_post)
end

new_post
Expand Down
54 changes: 54 additions & 0 deletions db/migrate/20140715055242_add_quoted_posts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
class AddQuotedPosts < ActiveRecord::Migration
def change
create_table :quoted_posts do |t|
t.integer :post_id, null: false
t.integer :quoted_post_id, null: false
t.timestamps
end

add_index :quoted_posts, [:post_id, :quoted_post_id], unique: true
add_index :quoted_posts, [:quoted_post_id, :post_id], unique: true


# NOTE this can be done in pg but too much of a headache
id = 0
while id = backfill_batch(id, 1000); end
end

def backfill_batch(start_id, batch_size)

results = execute <<SQL
SELECT id, cooked
FROM posts
WHERE raw like '%quote=%' AND id > #{start_id}
ORDER BY id
LIMIT #{batch_size}
SQL

max_id = nil

results.each do |row|
post_id, max_id = row["id"].to_i
doc = Nokogiri::HTML.fragment(row["cooked"])

uniq = {}

doc.css("aside.quote[data-topic]").each do |a|
topic_id = a['data-topic'].to_i
post_number = a['data-post'].to_i

next if uniq[[topic_id,post_number]]
uniq[[topic_id,post_number]] = true


execute "INSERT INTO quoted_posts(post_id, quoted_post_id, created_at, updated_at)
SELECT #{post_id}, id, created_at, updated_at
FROM posts
WHERE post_number = #{post_number} AND
topic_id = #{topic_id}"
end
end

max_id
end
end
1 change: 1 addition & 0 deletions lib/post_creator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ def publish

def extract_links
TopicLink.extract_from(@post)
QuotedPost.extract_from(@post)
end

def track_topic
Expand Down
27 changes: 27 additions & 0 deletions spec/models/quoted_post_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'spec_helper'

describe QuotedPost do
it 'correctly extracts quotes in integration test' do
post1 = create_post
post2 = create_post(topic_id: post1.topic_id,
raw: "[quote=\"#{post1.user.username}, post: 1, topic:#{post1.topic_id}\"]\ntest\n[/quote]\nthis is a test post")

QuotedPost.find_by(post_id: post2.id, quoted_post_id: post1.id).should_not be_nil
end

it 'correctly handles deltas' do
post1 = Fabricate(:post)
post2 = Fabricate(:post)

post2.cooked = <<HTML
<aside class="quote" data-post="#{post1.post_number}" data-topic="#{post1.topic_id}"><div class="title"><div class="quote-controls"></div><img width="20" height="20" src="/user_avatar/meta.discourse.org/techapj/20/3281.png" class="avatar">techAPJ said:</div><blockquote><p>When the user will v</p></blockquote></aside>
HTML

QuotedPost.create!(post_id: post2.id, quoted_post_id: 999)

QuotedPost.extract_from(post2)
QuotedPost.where(post_id: post2.id).count.should == 1
QuotedPost.find_by(post_id: post2.id, quoted_post_id: post1.id).should_not be_nil

end
end

0 comments on commit 2d0def9

Please sign in to comment.