fixed tests, implemented sql based partitioning for favorites

This commit is contained in:
albert
2011-07-16 20:16:34 -04:00
parent fc9755b748
commit 469ae14805
10 changed files with 1291 additions and 4555 deletions

View File

@@ -4,7 +4,7 @@ module PostSets
def initialize(user_id, page = 1)
@user = ::User.find(user_id)
@favorites = ::Favorite.model_for(user.id).for_user(user.id).paginate(page)
@favorites = ::Favorite.for_user(user.id).paginate(page)
end
def tag_array
@@ -16,7 +16,7 @@ module PostSets
end
def posts
favorites.map(&:post)
favorites.order("favorites.id desc").includes(:post).map(&:post)
end
def presenter

View File

@@ -1,22 +1,4 @@
class Favorite < ActiveRecord::Base
TABLE_COUNT = 100
belongs_to :post
scope :for_user, lambda {|user_id| where("user_id = ?", user_id)}
def self.model_for(user_id)
mod = user_id.to_i % TABLE_COUNT
Object.const_get("Favorite#{mod}")
end
def self.delete_post(post_id)
0.upto(TABLE_COUNT - 1) do |i|
model_for(i).destroy_all(:post_id => post_id)
end
end
end
0.upto(Favorite::TABLE_COUNT - 1) do |i|
Object.const_set("Favorite#{i}", Class.new(Favorite))
Object.const_get("Favorite#{i}").set_table_name("favorites_#{i}")
end

View File

@@ -389,7 +389,7 @@ class Post < ActiveRecord::Base
module FavoriteMethods
def delete_favorites
Favorite.delete_post(id)
Favorite.delete_all(:post_id => id)
end
def favorited_by?(user_id)

View File

@@ -5,12 +5,12 @@ class User < ActiveRecord::Base
class PrivilegeError < Exception ; end
module Levels
MEMBER = 0
PRIVILEGED = 100
CONTRIBUTOR = 200
JANITOR = 300
MODERATOR = 400
ADMIN = 500
MEMBER = 20
PRIVILEGED = 30
CONTRIBUTOR = 33
JANITOR = 35
MODERATOR = 40
ADMIN = 50
end
attr_accessor :password, :old_password
@@ -128,18 +128,18 @@ class User < ActiveRecord::Base
module FavoriteMethods
def favorites
Favorite.model_for(id).where("user_id = ?", id).order("id desc")
Favorite.where("user_id = ?", id).order("id desc")
end
def add_favorite!(post)
return if Favorite.model_for(id).exists?(:user_id => id, :post_id => post.id)
Favorite.model_for(id).create(:user_id => id, :post_id => post.id)
return if Favorite.exists?(:user_id => id, :post_id => post.id)
Favorite.create(:user_id => id, :post_id => post.id)
post.add_favorite!(self)
end
def remove_favorite!(post)
return unless Favorite.model_for(id).exists?(:user_id => id, :post_id => post.id)
Favorite.model_for(id).destroy_all(:user_id => id, :post_id => post.id)
return unless Favorite.exists?(:user_id => id, :post_id => post.id)
Favorite.destroy_all(:user_id => id, :post_id => post.id)
post.remove_favorite!(self)
end
end

View File

@@ -8,13 +8,13 @@ Bundler.require(:default, Rails.env) if defined?(Bundler)
module Danbooru
class Application < Rails::Application
config.active_record.schema_format = :sql
config.encoding = "utf-8"
config.filter_parameters += [:password]
config.assets.enabled = true
config.autoload_paths += %W(#{config.root}/app/presenters #{config.root}/app/logical)
config.plugins = [:all]
config.time_zone = 'Eastern Time (US & Canada)'
config.active_record.schema_format = :sql
# config.action_view.javascript_expansions[:defaults] = [
# "src/lib/jquery-1.6.0.min.js",
# "src/lib/jquery-ui-1.8.9.custom.min.js",

File diff suppressed because it is too large Load Diff

View File

@@ -9,14 +9,44 @@ class CreateFavorites < ActiveRecord::Migration
end
0.upto(TABLE_COUNT - 1) do |i|
create_table "favorites_#{i}" do |t|
t.column :user_id, :integer
t.column :post_id, :integer
end
execute <<-EOS
create table favorites_#{i} (
check (user_id % 100 = #{i})
) inherits (favorites)
EOS
add_index "favorites_#{i}", :user_id
add_index "favorites_#{i}", :post_id
end
fragment = []
1.upto(TABLE_COUNT - 1) do |i|
fragment << <<-EOS
elsif (NEW.user_id % 100 = #{i}) then
insert into favorites_#{i} values (NEW.*);
EOS
end
execute <<-EOS
create or replace function favorites_insert_trigger()
returns trigger as $$
begin
if (NEW.user_id % 100 = 0) then
insert into favorites_0 values (NEW.*);
#{fragment.join("\n")}
end if;
return NULL;
end;
$$
language plpgsql
EOS
execute <<-EOS
create trigger insert_favorites_trigger
before insert on favorites
for each row execute procedure favorites_insert_trigger()
EOS
end
def self.down

View File

@@ -1,6 +0,0 @@
namespace :db do
namespace :test do
task :reset => [:environment, "db:drop", "db:create", "db:migrate", "db:structure:dump", "db:test:clone_structure"] do
end
end
end

View File

@@ -24,8 +24,8 @@ module PostSets
context "a favorite set for before the most recent post" do
setup do
id = ::Favorite.model_for(@user.id).where(:user_id => @user.id, :post_id => @post_3.id).first.id
::Favorite.model_for(@user.id).stubs(:records_per_page).returns(1)
id = ::Favorite.where(:user_id => @user.id, :post_id => @post_3.id).first.id
::Favorite.stubs(:records_per_page).returns(1)
@set = PostSets::Favorite.new(@user.id, "b#{id}")
end
@@ -39,8 +39,8 @@ module PostSets
context "a favorite set for after the second most recent post" do
setup do
id = ::Favorite.model_for(@user.id).where(:user_id => @user.id, :post_id => @post_2.id).first.id
::Favorite.model_for(@user.id).stubs(:records_per_page).returns(1)
id = ::Favorite.where(:user_id => @user.id, :post_id => @post_2.id).first.id
::Favorite.stubs(:records_per_page).returns(1)
@set = PostSets::Favorite.new(@user.id, "a#{id}")
end
@@ -54,7 +54,7 @@ module PostSets
context "a favorite set for page 2" do
setup do
::Favorite.model_for(@user.id).stubs(:records_per_page).returns(1)
::Favorite.stubs(:records_per_page).returns(1)
@set = PostSets::Favorite.new(@user.id, 2)
end
@@ -68,7 +68,7 @@ module PostSets
context "a favorite set with no page specified" do
setup do
::Favorite.model_for(@user.id).stubs(:records_per_page).returns(1)
::Favorite.stubs(:records_per_page).returns(1)
@set = PostSets::Favorite.new(@user.id)
end

View File

@@ -85,8 +85,8 @@ class PostTest < ActiveSupport::TestCase
c1.add_favorite!(user)
c1.delete!
p1.reload
assert(!Favorite.model_for(user.id).exists?(:post_id => c1.id, :user_id => user.id))
assert(Favorite.model_for(user.id).exists?(:post_id => p1.id, :user_id => user.id))
assert(!Favorite.exists?(:post_id => c1.id, :user_id => user.id))
assert(Favorite.exists?(:post_id => p1.id, :user_id => user.id))
end
should "update the parent's has_children flag" do
@@ -335,22 +335,22 @@ class PostTest < ActiveSupport::TestCase
post.add_favorite!(user)
post.reload
assert_equal("fav:#{user.id}", post.fav_string)
assert(Favorite.model_for(user.id).exists?(:user_id => user.id, :post_id => post.id))
assert(Favorite.exists?(:user_id => user.id, :post_id => post.id))
post.add_favorite!(user)
post.reload
assert_equal("fav:#{user.id}", post.fav_string)
assert(Favorite.model_for(user.id).exists?(:user_id => user.id, :post_id => post.id))
assert(Favorite.exists?(:user_id => user.id, :post_id => post.id))
post.remove_favorite!(user)
post.reload
assert_equal("", post.fav_string)
assert(!Favorite.model_for(user.id).exists?(:user_id => user.id, :post_id => post.id))
assert(!Favorite.exists?(:user_id => user.id, :post_id => post.id))
post.remove_favorite!(user)
post.reload
assert_equal("", post.fav_string)
assert(!Favorite.model_for(user.id).exists?(:user_id => user.id, :post_id => post.id))
assert(!Favorite.exists?(:user_id => user.id, :post_id => post.id))
end
end
end