* Reworked how post versioning works, now more closely resembles the 1.18 strategy

This commit is contained in:
albert
2011-01-26 18:10:49 -05:00
parent 683d4583ac
commit f7e2344b9f
21 changed files with 292 additions and 308 deletions

View File

@@ -1,6 +0,0 @@
class PostHistoriesController < ApplicationController
def index
@search = PostHistory.search(params[:search])
@histories = @search.paginate(:page => params[:page], :per_page => 20, :order => "updated_at DESC")
end
end

View File

@@ -0,0 +1,6 @@
class PostVersionsController < ApplicationController
def index
@search = PostVersion.search(params[:search])
@post_versions = @search.paginate(:page => params[:page], :per_page => 20, :order => "updated_at DESC")
end
end

View File

@@ -5,7 +5,4 @@ class PostVotesController < ApplicationController
rescue PostVote::Error => x
@error = x
end
def destroy
end
end

View File

@@ -4,6 +4,11 @@ class JanitorTrial < ActiveRecord::Base
after_create :promote_user
after_destroy :create_feedback
validates_presence_of :user
before_validation :initialize_creator
def initialize_creator
self.creator_id = CurrentUser.id
end
def send_dmail
body = "You have been selected as a test janitor. You can now approve pending posts and have access to the moderation interface.\n\nOver the next several weeks your approvals will be monitored. If the majority of them are quality uploads, then you will be promoted to full janitor status which grants you the ability to delete and undelete posts, ban users, and revert tag changes from vandals. If you fail the trial period, you will be demoted back to your original level and you'll receive a negative user record indicating you previously attempted and failed a test janitor trial.\n\nThere is a minimum quota of 5 approvals a week to indicate that you are being active. Remember, the goal isn't to approve as much as possible. It's to filter out borderline-quality art.\n\nIf you have any questions please respond to this message."

View File

@@ -3,7 +3,7 @@ class Post < ActiveRecord::Base
attr_accessor :old_tag_string, :old_parent_id
after_destroy :delete_files
after_save :update_history
after_save :create_version
after_save :update_parent_on_save
before_save :merge_old_tags
before_save :normalize_tags
@@ -16,8 +16,7 @@ class Post < ActiveRecord::Base
belongs_to :parent, :class_name => "Post"
has_one :unapproval, :dependent => :destroy
has_one :upload, :dependent => :destroy
has_one :moderation_detail, :class_name => "PostModerationDetail", :dependent => :destroy
has_one :history, :class_name => "PostHistory"
has_many :versions, :class_name => "PostVersion", :dependent => :destroy
has_many :votes, :class_name => "PostVote", :dependent => :destroy
has_many :notes, :dependent => :destroy
has_many :comments
@@ -240,24 +239,6 @@ class Post < ActiveRecord::Base
end
end
module HistoryMethods
def revisions
if history.nil?
update_history
end
history.revisions
end
def update_history
if history.nil?
create_history
end
history << self
end
end
module TagMethods
def tag_array
@tag_array ||= Tag.scan_tags(tag_string)
@@ -788,11 +769,31 @@ class Post < ActiveRecord::Base
end
end
module VersionMethods
def create_version
if created_at == updated_at
versions.create(
:rating => rating,
:source => source,
:add_tags => tag_string,
:parent_id => parent_id
)
else
versions.create(
:rating => rating_changed? ? rating : nil,
:source => source_changed? ? source : nil,
:add_tags => (tag_array - tag_array_was).join(" "),
:del_tags => (tag_array_was - tag_array).join(" "),
:parent_id => parent_id_changed? ? parent_id : nil
)
end
end
end
include FileMethods
include ImageMethods
include ApprovalMethods
include PresenterMethods
include HistoryMethods
include TagMethods
include FavoriteMethods
include UploaderMethods
@@ -803,6 +804,7 @@ class Post < ActiveRecord::Base
include CacheMethods
include ParentMethods
include RemovalMethods
include VersionMethods
def reload(options = nil)
super

View File

@@ -1,114 +0,0 @@
class PostHistory < ActiveRecord::Base
class Error < Exception ; end
class Revision
attr_accessor :prev, :hash, :diff, :tag_array
def initialize(hash)
@hash = hash
@diff = {}
@tag_array = Tag.scan_tags(@hash["tag_string"])
end
def calculate_diff
if prev.nil?
diff[:add] = tag_array
diff[:del] = []
diff[:rating] = rating
diff[:source] = source
diff[:parent_id] = parent_id
else
diff[:del] = prev.tag_array - tag_array
diff[:add] = tag_array - prev.tag_array
if prev.rating != rating
diff[:rating] = rating
end
if prev.source != source
diff[:source] = source
end
if prev.parent_id != parent_id
diff[:parent_id]= parent_id
end
end
end
def rating
hash["rating"]
end
def source
hash["source"]
end
def parent_id
hash["parent_id"]
end
def updated_at
hash["updated_at"]
end
def user_id
hash["user_id"]
end
def presenter
@presenter ||= PostHistoryRevisionPresenter.new(self)
end
end
before_validation :initialize_revisions, :on => :create
belongs_to :post
def self.build_revision_for_post(post)
hash = {
:source => post.source,
:rating => post.rating,
:tag_string => post.tag_string,
:parent_id => post.parent_id,
:user_id => CurrentUser.id,
:ip_addr => CurrentUser.ip_addr,
:updated_at => revision_time
}
end
def self.revision_time
Time.now
end
def initialize_revisions
write_attribute(:revisions, "[]")
end
def revisions
if read_attribute(:revisions).blank?
[]
else
JSON.parse(read_attribute(:revisions))
end
end
def <<(post)
revision = self.class.build_revision_for_post(post)
write_attribute(:revisions, (revisions << revision).to_json)
save
end
def each_revision(&block)
array = revisions.map {|x| Revision.new(x)}
link_revisions(array)
array.each {|x| x.calculate_diff}
array.each(&block)
end
private
def link_revisions(array)
1.upto(array.size - 1) do |i|
array[i].prev = array[i - 1]
end
end
end

View File

@@ -0,0 +1,36 @@
class PostVersion < ActiveRecord::Base
belongs_to :post
belongs_to :updater, :class_name => "User"
before_validation :initialize_updater
def self.create_from_post(post)
if post.created_at == post.updated_at
create_from_created_post(post)
else
create_from_updated_post(post)
end
end
def initialize_updater
self.updater_id = CurrentUser.id
self.updater_ip_addr = CurrentUser.ip_addr
end
def add_tag_array
@add_tag_array ||= add_tags.scan(/\S+/)
end
def del_tag_array
@del_tag_array ||= del_tags.scan(/\S+/)
end
def presenter
PostVersionPresenter.new(self)
end
def reload
@add_tag_array = nil
@del_tag_array = nil
super
end
end

View File

@@ -1,25 +0,0 @@
class PostHistoryRevisionPresenter < Presenter
attr_reader :revision
def initialize(revision)
@revision = revision
end
def changes
html = []
html << revision.diff[:del].map {|x| "<del>#{h(x)}</del>"}
html << revision.diff[:add].map {|x| "<ins>#{h(x)}</ins>"}
html << "<ins>source:#{h(revision.diff[:source])}</ins>" if revision.diff[:source].present?
html << "<ins>rating:#{h(revision.diff[:rating])}</ins>" if revision.diff[:rating].present?
html << "<ins>parent:#{revision.diff[:parent_id]}</ins>" if revision.diff[:parent_id].present?
html.join(" ").html_safe
end
def updated_at
Time.parse(revision.updated_at)
end
def updater_name
User.id_to_name(revision.user_id)
end
end

View File

@@ -0,0 +1,21 @@
class PostVersionPresenter < Presenter
attr_reader :post_version
def initialize(post_version)
@post_version = post_version
end
def changes
html = []
html << post_version.del_tag_array.map {|x| "<del>#{h(x)}</del>"}
html << post_version.add_tag_array.map {|x| "<ins>#{h(x)}</ins>"}
html << "<ins>source:#{h(post_version.source)}</ins>" if post_version.source
html << "<ins>rating:#{h(post_version.rating)}</ins>" if post_version.rating
html << "<ins>parent:#{post_version.parent_id}</ins>" if post_version.parent_id
html.join(" ").html_safe
end
def updater_name
User.id_to_name(post_version.updater_id)
end
end

View File

@@ -1,37 +0,0 @@
<div class="post_histories">
<div class="index">
<h1>Post History</h1>
<% @histories.each do |history| %>
<div class="post">
<div class="preview">
<%= history.post.presenter.preview_html %>
</div>
<div class="history">
<table class="striped">
<thead>
<tr>
<th>Date</th>
<th>Updater</th>
<th>Changes</th>
</tr>
</thead>
<tbody>
<% history.each_revision do |revision| %>
<tr>
<td><%= revision.presenter.updated_at %></td>
<td><%= revision.presenter.updater_name %></td>
<td><%= revision.presenter.changes %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<div class="clearfix"></div>
</div>
<% end %>
</div>
</div>

View File

@@ -0,0 +1,25 @@
<div class="post_versions">
<div class="index">
<h1>Post Versions</h1>
<table class="striped">
<thead>
<tr>
<th>Date</th>
<th>Updater</th>
<th>Changes</th>
</tr>
</thead>
<tbody>
<% @post_versions.each do |post_version| %>
<tr>
<td><%= time_ago_in_words post_version.updated_at %></td>
<td><%= post_version.presenter.updater_name %></td>
<td><%= post_version.presenter.changes %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>