* Denormalized post versions. Testing has shown it reduces the size
of the table 66%.
This commit is contained in:
@@ -34,7 +34,7 @@ class DateTag
|
|||||||
end
|
end
|
||||||
|
|
||||||
def next_week
|
def next_week
|
||||||
DateTag.new_from_range(1.week.since(start_date)), 1.week.since(end_date)
|
DateTag.new_from_range(1.week.since(start_date), 1.week.since(end_date))
|
||||||
end
|
end
|
||||||
|
|
||||||
def previous_month
|
def previous_month
|
||||||
@@ -42,7 +42,7 @@ class DateTag
|
|||||||
end
|
end
|
||||||
|
|
||||||
def next_month
|
def next_month
|
||||||
DateTag.new_from_range(1.month.since(start_date)), 1.month.since(end_date)
|
DateTag.new_from_range(1.month.since(start_date), 1.month.since(end_date))
|
||||||
end
|
end
|
||||||
|
|
||||||
def date
|
def date
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
class Post < ActiveRecord::Base
|
class Post < ActiveRecord::Base
|
||||||
attr_accessor :old_tag_string, :old_parent_id
|
attr_accessor :old_tag_string, :old_parent_id
|
||||||
after_destroy :delete_files
|
after_destroy :delete_files
|
||||||
after_save :create_version
|
after_save :update_history
|
||||||
after_save :update_parent_on_save
|
after_save :update_parent_on_save
|
||||||
before_save :merge_old_tags
|
before_save :merge_old_tags
|
||||||
before_save :normalize_tags
|
before_save :normalize_tags
|
||||||
@@ -15,7 +15,7 @@ class Post < ActiveRecord::Base
|
|||||||
has_one :unapproval, :dependent => :destroy
|
has_one :unapproval, :dependent => :destroy
|
||||||
has_one :upload, :dependent => :destroy
|
has_one :upload, :dependent => :destroy
|
||||||
has_one :moderation_detail, :class_name => "PostModerationDetail", :dependent => :destroy
|
has_one :moderation_detail, :class_name => "PostModerationDetail", :dependent => :destroy
|
||||||
has_many :versions, :class_name => "PostVersion", :dependent => :destroy
|
has_one :history, :class_name => "PostHistory"
|
||||||
has_many :votes, :class_name => "PostVote", :dependent => :destroy
|
has_many :votes, :class_name => "PostVote", :dependent => :destroy
|
||||||
has_many :notes, :dependent => :destroy
|
has_many :notes, :dependent => :destroy
|
||||||
has_many :comments
|
has_many :comments
|
||||||
@@ -233,24 +233,21 @@ class Post < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module VersionMethods
|
module HistoryMethods
|
||||||
def create_version
|
def revisions
|
||||||
version = versions.create(
|
if history.nil?
|
||||||
:source => source,
|
update_history
|
||||||
:rating => rating,
|
end
|
||||||
:tag_string => tag_string,
|
|
||||||
:updater_id => CurrentUser.user.id,
|
|
||||||
:updater_ip_addr => CurrentUser.ip_addr
|
|
||||||
)
|
|
||||||
|
|
||||||
raise PostVersion::Error.new(version.errors.full_messages.join("; ")) if version.errors.any?
|
history.revisions
|
||||||
end
|
end
|
||||||
|
|
||||||
def revert_to!(version)
|
def update_history
|
||||||
self.source = version.source
|
if history.nil?
|
||||||
self.rating = version.rating
|
create_history
|
||||||
self.tag_string = version.tag_string
|
end
|
||||||
save!
|
|
||||||
|
history << self
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -788,7 +785,7 @@ class Post < ActiveRecord::Base
|
|||||||
include ImageMethods
|
include ImageMethods
|
||||||
include ApprovalMethods
|
include ApprovalMethods
|
||||||
include PresenterMethods
|
include PresenterMethods
|
||||||
include VersionMethods
|
include HistoryMethods
|
||||||
include TagMethods
|
include TagMethods
|
||||||
include FavoriteMethods
|
include FavoriteMethods
|
||||||
include UploaderMethods
|
include UploaderMethods
|
||||||
|
|||||||
40
app/models/post_history.rb
Normal file
40
app/models/post_history.rb
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
class PostHistory < ActiveRecord::Base
|
||||||
|
class Error < Exception ; 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
|
||||||
|
end
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
class PostVersion < ActiveRecord::Base
|
|
||||||
class Error < Exception ; end
|
|
||||||
|
|
||||||
validates_presence_of :updater_id, :updater_ip_addr
|
|
||||||
belongs_to :post
|
|
||||||
end
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<div id="search-form" style="margin-bottom: 1em;">
|
<div id="search-form" style="margin-bottom: 1em;">
|
||||||
<% form_tag(artists_path, :method => :get) do %>
|
<%= form_tag(artists_path, :method => :get) do %>
|
||||||
<%= text_field_tag "name", params[:name], :size => 40 %>
|
<%= text_field_tag "name", params[:name], :size => 40 %>
|
||||||
<%= submit_tag "Search" %>
|
<%= submit_tag "Search" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1013,6 +1013,38 @@ CREATE SEQUENCE pools_id_seq
|
|||||||
ALTER SEQUENCE pools_id_seq OWNED BY pools.id;
|
ALTER SEQUENCE pools_id_seq OWNED BY pools.id;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: post_histories; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE post_histories (
|
||||||
|
id integer NOT NULL,
|
||||||
|
created_at timestamp without time zone,
|
||||||
|
updated_at timestamp without time zone,
|
||||||
|
post_id integer NOT NULL,
|
||||||
|
revisions text NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: post_histories_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE SEQUENCE post_histories_id_seq
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MAXVALUE
|
||||||
|
NO MINVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: post_histories_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER SEQUENCE post_histories_id_seq OWNED BY post_histories.id;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: post_moderation_details; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
-- Name: post_moderation_details; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
@@ -1045,42 +1077,6 @@ CREATE SEQUENCE post_moderation_details_id_seq
|
|||||||
ALTER SEQUENCE post_moderation_details_id_seq OWNED BY post_moderation_details.id;
|
ALTER SEQUENCE post_moderation_details_id_seq OWNED BY post_moderation_details.id;
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: post_versions; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE post_versions (
|
|
||||||
id integer NOT NULL,
|
|
||||||
created_at timestamp without time zone,
|
|
||||||
updated_at timestamp without time zone,
|
|
||||||
post_id integer NOT NULL,
|
|
||||||
source character varying(255),
|
|
||||||
rating character(1) DEFAULT 'q'::bpchar NOT NULL,
|
|
||||||
tag_string text NOT NULL,
|
|
||||||
updater_id integer NOT NULL,
|
|
||||||
updater_ip_addr inet NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: post_versions_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE SEQUENCE post_versions_id_seq
|
|
||||||
START WITH 1
|
|
||||||
INCREMENT BY 1
|
|
||||||
NO MAXVALUE
|
|
||||||
NO MINVALUE
|
|
||||||
CACHE 1;
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: post_versions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
|
||||||
--
|
|
||||||
|
|
||||||
ALTER SEQUENCE post_versions_id_seq OWNED BY post_versions.id;
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: post_votes; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
-- Name: post_votes; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
@@ -1812,14 +1808,14 @@ ALTER TABLE pools ALTER COLUMN id SET DEFAULT nextval('pools_id_seq'::regclass);
|
|||||||
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
||||||
ALTER TABLE post_moderation_details ALTER COLUMN id SET DEFAULT nextval('post_moderation_details_id_seq'::regclass);
|
ALTER TABLE post_histories ALTER COLUMN id SET DEFAULT nextval('post_histories_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
||||||
ALTER TABLE post_versions ALTER COLUMN id SET DEFAULT nextval('post_versions_id_seq'::regclass);
|
ALTER TABLE post_moderation_details ALTER COLUMN id SET DEFAULT nextval('post_moderation_details_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
@@ -2137,6 +2133,14 @@ ALTER TABLE ONLY pools
|
|||||||
ADD CONSTRAINT pools_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT pools_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: post_histories_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY post_histories
|
||||||
|
ADD CONSTRAINT post_histories_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: post_moderation_details_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
-- Name: post_moderation_details_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
@@ -2145,14 +2149,6 @@ ALTER TABLE ONLY post_moderation_details
|
|||||||
ADD CONSTRAINT post_moderation_details_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT post_moderation_details_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: post_versions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
|
||||||
--
|
|
||||||
|
|
||||||
ALTER TABLE ONLY post_versions
|
|
||||||
ADD CONSTRAINT post_versions_pkey PRIMARY KEY (id);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: post_votes_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
-- Name: post_votes_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
@@ -2712,6 +2708,13 @@ CREATE INDEX index_pools_on_creator_id ON pools USING btree (creator_id);
|
|||||||
CREATE INDEX index_pools_on_name ON pools USING btree (name);
|
CREATE INDEX index_pools_on_name ON pools USING btree (name);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: index_post_histories_on_post_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX index_post_histories_on_post_id ON post_histories USING btree (post_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: index_post_moderation_details_on_post_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
-- Name: index_post_moderation_details_on_post_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
@@ -2726,20 +2729,6 @@ CREATE INDEX index_post_moderation_details_on_post_id ON post_moderation_details
|
|||||||
CREATE INDEX index_post_moderation_details_on_user_id ON post_moderation_details USING btree (user_id);
|
CREATE INDEX index_post_moderation_details_on_user_id ON post_moderation_details USING btree (user_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: index_post_versions_on_post_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE INDEX index_post_versions_on_post_id ON post_versions USING btree (post_id);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: index_post_versions_on_updater_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE INDEX index_post_versions_on_updater_id ON post_versions USING btree (updater_id);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: index_posts_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
-- Name: index_posts_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
|
|||||||
16
db/migrate/20100205163027_create_post_histories.rb
Normal file
16
db/migrate/20100205163027_create_post_histories.rb
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
class CreatePostHistories < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
create_table :post_histories do |t|
|
||||||
|
t.timestamps
|
||||||
|
|
||||||
|
t.column :post_id, :integer, :null => false
|
||||||
|
t.column :revisions, :text, :null => false
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :post_histories, :post_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
drop_table :post_histories
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
class CreatePostVersions < ActiveRecord::Migration
|
|
||||||
def self.up
|
|
||||||
create_table :post_versions do |t|
|
|
||||||
t.timestamps
|
|
||||||
|
|
||||||
# Post
|
|
||||||
t.column :post_id, :integer, :null => false
|
|
||||||
|
|
||||||
# Versioned
|
|
||||||
t.column :source, :string
|
|
||||||
t.column :rating, :character, :null => false, :default => 'q'
|
|
||||||
t.column :tag_string, :text, :null => false
|
|
||||||
|
|
||||||
# Updater
|
|
||||||
t.column :updater_id, :integer, :null => false
|
|
||||||
t.column :updater_ip_addr, "inet", :null => false
|
|
||||||
end
|
|
||||||
|
|
||||||
add_index :post_versions, :post_id
|
|
||||||
add_index :post_versions, :updater_id
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.down
|
|
||||||
drop_table :post_versions
|
|
||||||
end
|
|
||||||
end
|
|
||||||
33
test/unit/post_history_test.rb
Normal file
33
test/unit/post_history_test.rb
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
require_relative '../test_helper'
|
||||||
|
|
||||||
|
class PostHistoryTest < ActiveSupport::TestCase
|
||||||
|
context "A post" do
|
||||||
|
setup do
|
||||||
|
@user = Factory.create(:user)
|
||||||
|
CurrentUser.user = @user
|
||||||
|
CurrentUser.ip_addr = "127.0.0.1"
|
||||||
|
MEMCACHE.flush_all
|
||||||
|
end
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
CurrentUser.user = nil
|
||||||
|
CurrentUser.ip_addr = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
should "create a revision after creation" do
|
||||||
|
PostHistory.stubs(:revision_time).returns("TIME")
|
||||||
|
post = Factory.create(:post, :tag_string => "aaa bbb ccc")
|
||||||
|
assert_equal(1, post.revisions.size)
|
||||||
|
assert_equal({"source"=>nil, "rating"=>"q", "tag_string"=>"aaa bbb ccc", "parent_id"=>nil, "user_id"=>1, "ip_addr"=>"127.0.0.1", "updated_at"=>"TIME"}, post.revisions.last)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "create additional revisions after updating" do
|
||||||
|
PostHistory.stubs(:revision_time).returns("TIME")
|
||||||
|
post = Factory.create(:post, :tag_string => "aaa bbb ccc")
|
||||||
|
post.update_attributes(:tag_string => "bbb ccc ddd")
|
||||||
|
post.reload
|
||||||
|
assert_equal(2, post.revisions.size)
|
||||||
|
assert_equal({"source"=>nil, "rating"=>"q", "tag_string"=>"bbb ccc ddd", "parent_id"=>nil, "user_id"=>3, "ip_addr"=>"127.0.0.1", "updated_at"=>"TIME"}, post.revisions.last)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user