Dropped number from revision table. Also dropped timestamp. We will rely on autoincremented ID for sorting, and will for now store the time of last edit of the revision in revised_at. Later we will refactor content into a separate table (so as not to load the whole 300 kb of text and cached HTML every time we need page.revisions in code). Rake tests all pass, but watir tests indicate that some revision traversing links are still broken

This commit is contained in:
Alexey Verkhovsky 2005-08-14 22:26:54 +00:00
parent 476d7810f6
commit 052754b068
18 changed files with 116 additions and 112 deletions

View file

@ -140,7 +140,7 @@ class WikiController < ApplicationController
def pdf
page = wiki.read_page(@web_name, @page_name)
safe_page_name = @page.name.gsub(/\W/, '')
file_name = "#{safe_page_name}-#{@web.address}-#{@page.created_at.strftime('%Y-%m-%d-%H-%M-%S')}"
file_name = "#{safe_page_name}-#{@web.address}-#{@page.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}"
file_path = File.join(@wiki.storage_path, file_name)
export_page_to_tex("#{file_path}.tex") unless FileTest.exists?("#{file_path}.tex")
@ -274,7 +274,8 @@ class WikiController < ApplicationController
end
def get_page_and_revision
@revision = @page.revisions[@params['rev'].to_i]
@revision_number = @params['rev'].to_i
@revision = @page.revisions[@revision_number]
end
def parse_category
@ -312,8 +313,8 @@ class WikiController < ApplicationController
@pages_by_revision = @web.select.by_revision.first(limit)
else
@pages_by_revision = @web.select.by_revision
@pages_by_revision.reject! { |page| page.created_at < start_date } if start_date
@pages_by_revision.reject! { |page| page.created_at > end_date } if end_date
@pages_by_revision.reject! { |page| page.revised_on < start_date } if start_date
@pages_by_revision.reject! { |page| page.revised_on > end_date } if end_date
end
@hide_description = hide_description

View file

@ -1,9 +1,9 @@
class Page < ActiveRecord::Base
belongs_to :web
has_many :revisions, :order => 'number'
has_one :current_revision, :class_name => 'Revision', :order => 'number DESC'
has_many :revisions, :order => 'id'
has_one :current_revision, :class_name => 'Revision', :order => 'id DESC'
def revise(content, created_at, author)
def revise(content, time, author)
revisions_size = new_record? ? 0 : revisions.size
if (revisions_size > 0) and content == current_revision.content
raise Instiki::ValidationError.new(
@ -13,37 +13,49 @@ class Page < ActiveRecord::Base
author = Author.new(author.to_s) unless author.is_a?(Author)
# Try to render content to make sure that markup engine can take it,
# before addin a revision to the page
Revision.new(:page => self, :content => content, :created_at => created_at, :author => author).force_rendering
Revision.new(:page => self, :content => content, :author => author, :revised_at => time).force_rendering
# A user may change a page, look at it and make some more changes - several times.
# Not to record every such iteration as a new revision, if the previous revision was done
# by the same author, not more than 30 minutes ago, then update the last revision instead of
# creating a new one
if (revisions_size > 0) && continous_revision?(created_at, author)
current_revision.update_attributes(:created_at => created_at, :content => content)
if (revisions_size > 1) && continous_revision?(time, author)
current_revision.update_attributes(:content => content, :revised_at => time)
else
Revision.create(:page => self, :content => content, :created_at => created_at, :author => author)
Revision.create(:page => self, :content => content, :author => author, :revised_at => time)
end
self.created_at = created_at
save
web.refresh_pages_with_references(name) if revisions_size == 0
self
end
def rollback(revision_number, created_at, author_ip = nil)
roll_back_revision = Revision.find(:first, :conditions => ['page_id = ? AND number = ?', id, revision_number])
revise(roll_back_revision.content, created_at, Author.new(roll_back_revision.author, author_ip))
def rollback(revision_number, time, author_ip = nil)
roll_back_revision = self.revisions[revision_number]
if roll_back_revision.nil?
raise Instiki::ValidationError.new("Revision #{revision_number} not found")
end
revise(roll_back_revision.content, time, Author.new(roll_back_revision.author, author_ip))
end
def revisions?
revisions.size > 1
end
def revised_on
created_on
def previous_revision(revision)
revision_index = revisions.each_with_index do |rev, index|
if rev.id == revision.id
break index
else
nil
end
end
if revision_index.nil? or revision_index == 0
nil
else
revisions[revision_index - 1]
end
end
def in_category?(cat)
@ -108,8 +120,8 @@ class Page < ActiveRecord::Base
private
def continous_revision?(created_at, author)
current_revision.author == author && current_revision.created_at + 30.minutes > created_at
def continous_revision?(time, author)
(current_revision.author == author) && (revised_on + 30.minutes > time)
end
# Forward method calls to the current revision, so the page responds to all revision calls

View file

@ -17,10 +17,9 @@ class PageSet < Array
end
def most_recent_revision
self.map { |page| page.created_at }.max || Time.at(0)
self.map { |page| page.revised_on }.max || Time.at(0)
end
def by_name
PageSet.new(@web, sort_by { |page| page.name })
end
@ -28,7 +27,7 @@ class PageSet < Array
alias :sort :by_name
def by_revision
PageSet.new(@web, sort_by { |page| page.created_at }).reverse
PageSet.new(@web, sort_by { |page| page.revised_on }).reverse
end
def pages_that_reference(page_name)

View file

@ -3,24 +3,13 @@ class Revision < ActiveRecord::Base
belongs_to :page
composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
def created_on
created_at.to_date
def revised_on
revised_at
end
def pretty_created_at
# Must use DateTime because Time doesn't support %e on at least some platforms
DateTime.new(
created_at.year, created_at.mon, created_at.day, created_at.hour, created_at.min
).strftime "%B %e, %Y %H:%M"
end
# todo: drop next_revision, previuous_revision and number from here - unused code
def next_revision
Revision.find_by_number_and_page_id(number+1, page_id)
end
def previous_revision
@previous_revions ||= number > 0 ? Revision.find_by_number_and_page_id(number-1, page_id) : nil
# TODO this method belongs in the view helpers (only views use it)
def pretty_created_on
revised_on.to_date.strftime "%B %e, %Y %H:%M:%S"
end
# Returns an array of all the WikiIncludes present in the content of this revision.
@ -30,7 +19,7 @@ class Revision < ActiveRecord::Base
@wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
end
@wiki_includes_cache
end
end
# Returns an array of all the WikiReferences present in the content of this revision.
def wiki_references
@ -72,8 +61,14 @@ class Revision < ActiveRecord::Base
@display_cache
end
# TODO this probably doesn't belong in revision (because it has to call back the page)
def display_diff
previous_revision ? HTMLDiff.diff(previous_revision.display_content, display_content) : display_content
previous_revision = page.previous_revision(self)
if previous_revision
HTMLDiff.diff(previous_revision.display_content, display_content)
else
display_content
end
end
def clear_display_cache
@ -112,18 +107,8 @@ class Revision < ActiveRecord::Base
end
protected
before_create :set_revision_number, :set_timestamp
after_create :force_rendering
after_save :clear_display_cache
# TODO Refactor this away. Revisions collection should not rely on the revision number for
# sorting etc - revisions must be easy to delete (this helps fighting wiki spam)
def set_revision_number
self.number = self.class.count(['page_id = ?', page_id]) + 1
end
def set_timestamp
self.timestamp = (Time.now.to_f * 1000).to_i.to_s
end
end

View file

@ -17,9 +17,9 @@ class Web < ActiveRecord::Base
self.brackets_only != brackets_only
end
def add_page(name, content, created_at, author)
def add_page(name, content, time, author)
page = page(name) || Page.new(:web => self, :name => name)
page.revise(content, created_at, author)
page.revise(content, time, author)
end
def authors

View file

@ -64,9 +64,9 @@ class Wiki
page.revise(content, revised_on, author)
end
def rollback_page(web_address, page_name, revision_number, created_at, author_id = nil)
def rollback_page(web_address, page_name, revision_number, time, author_id = nil)
page = read_page(web_address, page_name)
page.rollback(revision_number, created_at, author_id)
page.rollback(revision_number, time, author_id)
end
def setup(password, web_name, web_address)

View file

@ -12,7 +12,7 @@
<div id="changes" style="display: none">
<p style="background: #eee; padding: 3px; border: 1px solid silver">
<small>
Showing changes from revision #<%= @page.number - 1 %> to #<%= @page.number %>:
Showing changes from revision #<%= @page.revisions.size - 1 %> to #<%= @page.revisions.size %>:
<ins class="diffins">Added</ins> | <del class="diffdel">Removed</del>
</small>
</p>
@ -22,7 +22,7 @@
<% end %>
<div class="byline">
<%= @page.revisions? ? "Revised" : "Created" %> on <%= @page.pretty_created_at %>
<%= @page.revisions? ? "Revised" : "Created" %> on <%= @page.pretty_created_on %>
by <%= @page.author_link %>
<%= "(#{@page.author.ip})" if @page.author.respond_to?(:ip) %>
<% if @web.count_pages? %>

View file

@ -8,7 +8,7 @@
<%= @page.display_content_for_export %>
<div class="byline">
<%= @page.revisions? ? "Revised" : "Created" %> on <%= @page.pretty_created_at %>
<%= @page.revisions? ? "Revised" : "Created" %> on <%= @page.pretty_created_on %>
by
<%= @page.author_link({ :mode => (@link_mode || :show) }) %>
</div>

View file

@ -17,7 +17,7 @@
<%= link_to_existing_page page %>
<div class="byline" style="margin-bottom: 0px">
by <%= link_to_page(page.author) %>
at <%= page.created_at.strftime "%H:%M" %>
at <%= page.current_revision.pretty_created_on %>
<%= "from #{page.author.ip}" if page.author.respond_to?(:ip) %>
</div>
</li>

View file

@ -1,4 +1,4 @@
<% @title = "#{@page.plain_name} (Rev ##{@revision.number})" %>
<% @title = "#{@page.plain_name} (Rev ##{@revision_number})" %>
<div id="revision">
<%= @revision.display_content %>
@ -7,7 +7,7 @@
<div id="changes" style="display: none">
<p style="background: #eee; padding: 3px; border: 1px solid silver">
<small>
Showing changes from revision #<%= @revision.number - 1 %> to #<%= @revision.number %>:
Showing changes from revision #<%= @revision_number - 1 %> to #<%= @revision_number %>:
<ins class="diffins">Added</ins> | <del class="diffdel">Removed</del>
</small>
</p>
@ -17,17 +17,17 @@
<div class="byline">
<%= "Revision from #{@revision.pretty_created_at} by" %>
<%= "Revision from #{@revision.pretty_created_on} by" %>
<%= link_to_page @revision.author %>
</div>
<div class="navigation">
<% if @revision.next_revision %>
<% if @revision.next_revision.number < (@page.revisions.length - 1) %>
<% if @revision_number < @page.revisions.length - 1 %>
<% if @revision_number < @page.revisions.length - 2 %>
<%= link_to('Forward in time',
{:web => @web.address, :action => 'revision', :id => @page.name,
:rev => @revision.next_revision.number},
:rev => @revision_number + 1},
{:class => 'navlink', :name => 'to_next_revision'})
%>
<% else %>
@ -36,20 +36,20 @@
{:class => 'navlink', :name => 'to_next_revision'})
%>
<% end %>
<small>(<%= @revision.page.revisions.length - @revision.next_revision.number %> more)</small>
<small>(<%= @revision.page.revisions.length - @revision_number - 1 %> more)</small>
<% end %>
<% if @revision.next_revision && @revision.previous_revision %>
<% if @revision_number > 0 && @revision_number < @page.revisions.size - 1 %>
|
<% end %>
<% if @revision.previous_revision %>
<% if @revision_number > 0 %>
<%= link_to('Back in time',
{:web => @web.address, :action => 'revision', :id => @page.name,
:rev => @revision.previous_revision.number},
:rev => @revision_number - 1},
{:class => 'navlink', :name => 'to_previous_revision'})
%>
<small>(<%= @revision.previous_revision.number + 1 %> more)</small>
<small>(<%= @revision_number %> more)</small>
<% end %>
|
@ -57,7 +57,7 @@
{:class => 'navlink', :name => 'to_current_revision'})
%>
<% if @revision.previous_revision %>
<% if @revision_number > 0 %>
<span id="show_changes">
| <a href="#" onClick="toggleChanges(); return false;">See changes</a>
</span>
@ -69,7 +69,7 @@
|
<%= link_to('Rollback',
{:web => @web.address, :action => 'rollback', :id => @page.name, :rev => @revision.number},
{:web => @web.address, :action => 'rollback', :id => @page.name, :rev => @revision_number},
{:class => 'navlink', :name => 'rollback'})
%>

View file

@ -1,5 +1,5 @@
<%
@title = "Rollback to #{@page.plain_name} Rev ##{@revision.number}"
@title = "Rollback to #{@page.plain_name} Rev ##{@revision_number}"
@content_width = 720
@hide_navigation = true
%>

View file

@ -12,7 +12,7 @@
<% unless @hide_description %>
<description><%= h page.display_content %></description>
<% end %>
<pubDate><%= page.created_at.getgm.strftime "%a, %d %b %Y %H:%M:%S Z" %></pubDate>
<pubDate><%= page.revised_on.getgm.strftime "%a, %d %b %Y %H:%M:%S Z" %></pubDate>
<guid><%= url_for :only_path => false, :web => @web_name, :action => @link_action, :id => page.name %></guid>
<link><%= url_for :only_path => false, :web => @web_name, :action => @link_action, :id => page.name %></link>
<dc:creator><%= WikiWords.separate(page.author) %></dc:creator>