From dcf8d0df4cc4010890e292c2741c1d68efb76ea3 Mon Sep 17 00:00:00 2001 From: albert Date: Wed, 17 Mar 2010 19:20:44 -0400 Subject: [PATCH] fixed upload->post converion process --- app/controllers/uploads_controller.rb | 5 ++ app/logical/favorite.rb | 4 +- app/logical/post_set.rb | 37 ++++---- app/models/post.rb | 45 ++++++++-- app/models/upload.rb | 20 +++++ app/presenters/paginator_presenter.rb | 2 +- app/presenters/post_presenter.rb | 14 +++ app/presenters/post_set_presenter.rb | 77 +++++++++++++++- app/presenters/upload_presenter.rb | 15 ++++ app/views/layouts/default.html.erb | 74 ++++++---------- .../_common_secondary_nav_links.html.erb | 4 +- app/views/posts/index.html.erb | 6 +- app/views/posts/show.html.erb | 87 +++++++++++++++++++ app/views/uploads/index.html.erb | 24 +++++ app/views/uploads/new.html.erb | 2 + app/views/uploads/show.html.erb | 4 + config/danbooru_default_config.rb | 5 ++ config/danbooru_local_config.rb | 4 + config/routes.rb | 1 + lib/cache.rb | 16 ---- 20 files changed, 346 insertions(+), 100 deletions(-) create mode 100644 app/presenters/post_presenter.rb create mode 100644 app/presenters/upload_presenter.rb create mode 100644 app/views/uploads/index.html.erb diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb index eb5409bfc..0033546c6 100644 --- a/app/controllers/uploads_controller.rb +++ b/app/controllers/uploads_controller.rb @@ -9,6 +9,11 @@ class UploadsController < ApplicationController end end + def index + @uploads = Upload.where("uploader_id = ?", @current_user.id).includes(:uploader).order("uploads.id desc").limit(10) + respond_with(@uploads) + end + def show @upload = Upload.find(params[:id]) end diff --git a/app/logical/favorite.rb b/app/logical/favorite.rb index 5f992fe66..1fe2dab49 100644 --- a/app/logical/favorite.rb +++ b/app/logical/favorite.rb @@ -12,7 +12,9 @@ class Favorite end def self.destroy_all_for_post(post) - ActiveRecord::Base.connection.execute("DELETE FROM #{table_name_for(user)} WHERE post_id = #{post.id}") + 0.upto(9) do |i| + ActiveRecord::Base.connection.execute("DELETE FROM favorites_#{i} WHERE post_id = #{post.id}") + end end def self.destroy_all_for_user(user) diff --git a/app/logical/post_set.rb b/app/logical/post_set.rb index 5a92bb53f..24dbfba68 100644 --- a/app/logical/post_set.rb +++ b/app/logical/post_set.rb @@ -1,7 +1,7 @@ class PostSet class Error < Exception ; end - attr_accessor :tags, :page, :current_user, :before_id, :errors + attr_accessor :tags, :page, :current_user, :before_id, :errors, :count attr_accessor :wiki_page, :artist, :posts, :suggestions def initialize(tags, page, current_user, before_id = nil) @@ -11,16 +11,24 @@ class PostSet @before_id = before_id @errors = [] load_associations - load_paginator + load_posts validate end + def use_sequential_paginator? + !use_numbered_paginator? + end + + def use_numbered_paginator? + before_id.nil? + end + def has_errors? errors.any? end def offset - x = (page - 1) * 20 + x = (page - 1) * limit if x < 0 x = 0 end @@ -28,7 +36,7 @@ class PostSet end def limit - 20 + Danbooru.config.posts_per_page end def is_single_tag? @@ -42,28 +50,13 @@ class PostSet end end - def load_paginator - if before_id - load_sequential_paginator - else - load_paginated_paginator - end - end - - def load_paginated_paginator + def load_posts + @count = Post.fast_count(tags) @posts = Post.find_by_tags(tags, :before_id => before_id).all(:order => "posts.id desc", :limit => limit, :offset => offset) end - def load_sequential_paginator - count = Post.fast_count(tags) - @posts = WillPaginate::Collection.create(page, limit, count) do |pager| - pager.replace(Post.find_by_sql(tags).all(:order => "posts.id desc", :limit => pager.per_page, :offset => pager.offset)) - end - load_suggestions(count) - end - def load_suggestions(count) - @suggestions = Tag.find_suggestions(tags) if count < 20 && is_single_tag? + @suggestions = Tag.find_suggestions(tags) if count < limit && is_single_tag? end def tag_array diff --git a/app/models/post.rb b/app/models/post.rb index 2f296c7b4..b86d82898 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -2,6 +2,7 @@ class Post < ActiveRecord::Base attr_accessor :updater_id, :updater_ip_addr, :old_tag_string after_destroy :delete_files after_destroy :delete_favorites + after_destroy :update_tag_post_counts after_save :create_version before_save :merge_old_tags before_save :normalize_tags @@ -9,6 +10,7 @@ class Post < ActiveRecord::Base before_save :update_tag_post_counts before_save :set_tag_counts belongs_to :updater, :class_name => "User" + belongs_to :approver, :class_name => "User" has_one :unapproval, :dependent => :destroy has_one :upload, :dependent => :destroy has_one :moderation_detail, :class_name => "PostModerationDetail", :dependent => :destroy @@ -16,6 +18,7 @@ class Post < ActiveRecord::Base has_many :votes, :class_name => "PostVote", :dependent => :destroy has_many :notes, :dependent => :destroy validates_presence_of :updater_id, :updater_ip_addr + validates_uniqueness_of :md5 attr_accessible :source, :rating, :tag_string, :old_tag_string, :updater_id, :updater_ip_addr, :last_noted_at module FileMethods @@ -74,6 +77,10 @@ class Post < ActiveRecord::Base file_url end end + + def is_image? + file_ext =~ /jpg|gif|png/ + end end module ImageMethods @@ -168,6 +175,12 @@ class Post < ActiveRecord::Base increment_tags = tag_array - tag_array_was execute_sql("UPDATE tags SET post_count = post_count - 1 WHERE name IN (?)", decrement_tags) if decrement_tags.any? execute_sql("UPDATE tags SET post_count = post_count + 1 WHERE name IN (?)", increment_tags) if increment_tags.any? + decrement_tags.each do |tag| + expire_cache(tag) + end + increment_tags.each do |tag| + expire_cache(tag) + end end def set_tag_counts @@ -501,15 +514,32 @@ class Post < ActiveRecord::Base module CountMethods def fast_count(tags) - Cache.get("pfc:#{Cache.sanitize(tags)}", 24.hours) do - Post.find_by_tags(tags).count - end + count = Cache.get("pfc:#{Cache.sanitize(tags)}") + return count unless count.nil? + count = Post.find_by_tags(tags).count + expiry = (count < 100) ? 0 : (count * 4).minutes + Cache.put("pfc:#{Cache.sanitize(tags)}", count, expiry) + count end def fast_delete_count(tags) - Cache.get("pfdc:#{Cache.sanitize(tags)}", 24.hours) do - Post.find_by_tags("#{tags} status:deleted").count + count = Cache.get("pfdc:#{Cache.sanitize(tags)}") + return count unless count.nil? + count = Post.find_by_tags("#{tags} status:deleted").count + expiry = (count < 100) ? 0 : (count * 4).minutes + Cache.put("pfc:#{Cache.sanitize(tags)}", count, expiry) + count + end + end + + module CacheMethods + def expire_cache(tag_name) + if Post.fast_count("") < 1000 + Cache.delete("pfc:") + Cache.delete("pfdc:") end + Cache.delete("pfc:#{Cache.sanitize(tag_name)}") + Cache.delete("pfdc:#{Cache.sanitize(tag_name)}") end end @@ -525,9 +555,14 @@ class Post < ActiveRecord::Base extend SearchMethods include VoteMethods extend CountMethods + include CacheMethods def reload(options = nil) super reset_tag_array_cache end + + def presenter + @presenter ||= PostPresenter.new(self) + end end diff --git a/app/models/upload.rb b/app/models/upload.rb index eb41d6951..841d924ce 100644 --- a/app/models/upload.rb +++ b/app/models/upload.rb @@ -18,6 +18,12 @@ class Upload < ActiveRecord::Base raise end end + + # Because uploads are processed serially, there's no race condition here. + def validate_md5_uniqueness + md5_post = Post.find_by_md5(md5) + merge_tags(md5_post) if md5_post + end def validate_file_exists unless File.exists?(file_path) @@ -51,6 +57,7 @@ class Upload < ActiveRecord::Base self.file_ext = content_type_to_file_ext(content_type) validate_file_content_type calculate_hash(file_path) + validate_md5_uniqueness validate_md5_confirmation calculate_file_size(file_path) calculate_dimensions(file_path) if has_dimensions? @@ -85,6 +92,15 @@ class Upload < ActiveRecord::Base end end end + + def merge_tags(post) + post.tag_string += " #{tag_string}" + post.updater_id = uploader_id + post.updater_ip_addr = uploader_ip_addr + post.save + update_attribute(:status, "duplicate: #{post.id}") + raise + end end module FileMethods @@ -274,4 +290,8 @@ class Upload < ActiveRecord::Base include FilePathMethods include CgiFileMethods include StatusMethods + + def presenter + @presenter ||= UploadPresenter.new(self) + end end \ No newline at end of file diff --git a/app/presenters/paginator_presenter.rb b/app/presenters/paginator_presenter.rb index aabd68dc6..48a747f61 100644 --- a/app/presenters/paginator_presenter.rb +++ b/app/presenters/paginator_presenter.rb @@ -1,2 +1,2 @@ -class PaginatorPresenter +class PaginatorPresenter < Presenter end diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb new file mode 100644 index 000000000..c07a7b51c --- /dev/null +++ b/app/presenters/post_presenter.rb @@ -0,0 +1,14 @@ +class PostPresenter < Presenter + def initialize(post) + @post = post + end + + def tag_list_html + end + + def image_html + end + + def note_html + end +end diff --git a/app/presenters/post_set_presenter.rb b/app/presenters/post_set_presenter.rb index 0a2f993c2..33a207eb8 100644 --- a/app/presenters/post_set_presenter.rb +++ b/app/presenters/post_set_presenter.rb @@ -1,3 +1,5 @@ +require 'pp' + class PostSetPresenter < Presenter attr_accessor :post_set @@ -17,7 +19,80 @@ class PostSetPresenter < Presenter "" end - def pagination_html + def pagination_html(template) + if @post_set.use_sequential_paginator? + sequential_pagination_html(template) + else + numbered_pagination_html(template) + end + end + + def sequential_pagination_html(template) + html = "" + prev_url = template.request.env["HTTP_REFERER"] + next_url = template.posts_path(:tags => template.params[:tags], before_id => @post_set.posts[-1].id, :page => nil) + html << %{
  • « Previous
  • } + if @post_set.posts.any? + html << %{
  • Next »
  • } + end + html << "
    " + html.html_safe + end + + def numbered_pagination_html(template) + total_pages = (@post_set.count.to_f / @post_set.limit.to_f).ceil + current_page = [1, @post_set.page].max + before_current_page = current_page - 1 + after_current_page = current_page + 1 + html = "" + + current_page_min = [1, current_page - 2].max + current_page_max = [total_pages, current_page + 2].min + + if current_page == 1 + # do nothing + elsif current_page_min == 1 + 1.upto(before_current_page) do |i| + html << numbered_pagination_item(template, i) + end + else + 1.upto(3) do |i| + html << numbered_pagination_item(template, i) + end + + html << "
  • ...
  • " + + current_page_min.upto(before_current_page) do |i| + html << numbered_pagination_item(template, i) + end + end + + html << %{
  • #{current_page}
  • } + + if current_page == total_pages + # do nothing + elsif current_page_max == total_pages + after_current_page.upto(total_pages) do|i| + html << numbered_pagination_item(template, i) + end + else + after_current_page.upto(after_current_page + 2) do |i| + html << numbered_pagination_item(template, i) + end + + html << "
  • ...
  • " + html << numbered_pagination_item(template, total_pages) + end + + html << "
    " + html.html_safe + end + + def numbered_pagination_item(template, page) + html = "
  • " + html << template.link_to(page, template.__send__(:posts_path, :tags => template.params[:tags], :page => page)) + html << "
  • " + html.html_safe end def post_previews_html diff --git a/app/presenters/upload_presenter.rb b/app/presenters/upload_presenter.rb new file mode 100644 index 000000000..085e2fa85 --- /dev/null +++ b/app/presenters/upload_presenter.rb @@ -0,0 +1,15 @@ +class UploadPresenter < Presenter + def initialize(upload) + @upload = upload + end + + def status(template) + case @upload.status + when /duplicate: (\d+)/ + template.link_to(@upload.status, template.__send__(:post_path, $1)) + + else + @upload.status + end + end +end diff --git a/app/views/layouts/default.html.erb b/app/views/layouts/default.html.erb index 044f7b859..7d12f46e0 100644 --- a/app/views/layouts/default.html.erb +++ b/app/views/layouts/default.html.erb @@ -13,63 +13,43 @@ <%= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" %> <%= javascript_include_tag "rails" %> <%= Danbooru.config.custom_html_header_content %> - <%= yield :html_header_content %> + <%= yield :html_header %> - - +
    + +
    + <% if flash[:notice] %>
    <%= flash[:notice] %>
    <% else %> <% end %> - - <% if @current_user.has_mail? %> -
    - <%= link_to "You have mail", dmails_path %> -
    - <% end %> - - <% if !@current_user.is_privileged? %> - - <% end %> - - <% if @current_user.is_banned? %> -
    - You have been banned. - <% if @current_user.ban %> - Reason: <%= @current_user.ban.reason %>. - Expires: <%= @current_user.ban.expires_at.strftime('%Y-%m-%d') %> - <% end %> -
    - <% end %>
    <%= yield :layout %>
    - - <%= yield :page_footer_content %> + + diff --git a/app/views/posts/_common_secondary_nav_links.html.erb b/app/views/posts/_common_secondary_nav_links.html.erb index 3d8fa6cb7..af167dac0 100644 --- a/app/views/posts/_common_secondary_nav_links.html.erb +++ b/app/views/posts/_common_secondary_nav_links.html.erb @@ -1,6 +1,6 @@ <% content_for(:secondary_nav_links) do %> -
  • Listing
  • +
  • <%= link_to "Listing", posts_path %>
  • <%= link_to "Upload", new_upload_path %>
  • Popular
  • Favorites
  • @@ -10,4 +10,4 @@
  • Moderate
  • Help
  • -<% end %> \ No newline at end of file +<% end %> diff --git a/app/views/posts/index.html.erb b/app/views/posts/index.html.erb index 9e94d99d3..42b527a39 100644 --- a/app/views/posts/index.html.erb +++ b/app/views/posts/index.html.erb @@ -71,14 +71,10 @@ <% content_for(:page_title) do %> - /<%= @post_set.tags %> -<% end %> - -<% content_for(:page_header) do %> / <%= @post_set.tags %> <% end %> diff --git a/app/views/posts/show.html.erb b/app/views/posts/show.html.erb index e69de29bb..5964f9522 100644 --- a/app/views/posts/show.html.erb +++ b/app/views/posts/show.html.erb @@ -0,0 +1,87 @@ + + +
    +

    Post

    + +
    +

    Image

    + <%= @post.presenter.image_html %> +
    + +
    +

    Notes

    + <%= @post.presenter.note_html %> +
    + +
    +

    Comments

    +
    + +
    +

    Edit

    +
    +
    + +<% content_for(:page_title) do %> + / <%= @post.tag_string %> +<% end %> + +<% content_for(:html_header) do %> + + + +<% end %> + +<%= render :partial => "posts/common_secondary_nav_links" %> diff --git a/app/views/uploads/index.html.erb b/app/views/uploads/index.html.erb new file mode 100644 index 000000000..8600e888a --- /dev/null +++ b/app/views/uploads/index.html.erb @@ -0,0 +1,24 @@ + + + + + + + + + + + + <% @uploads.each do |upload| %> + + + + + + + + <% end %> + +
    UploaderStatusDateTags
    <%= link_to upload.id, upload_path(upload) %><%= link_to upload.uploader.name, user_path(upload.uploader) %><%= upload.presenter.status(self) %><%= upload.created_at %><%= upload.tag_string %>
    + +<%= render :partial => "posts/common_secondary_nav_links" %> \ No newline at end of file diff --git a/app/views/uploads/new.html.erb b/app/views/uploads/new.html.erb index 9340d57ee..4fdbe6b6c 100644 --- a/app/views/uploads/new.html.erb +++ b/app/views/uploads/new.html.erb @@ -52,3 +52,5 @@ <% content_for(:page_title) do %> / Upload <% end %> + +<%= render :partial => "posts/common_secondary_nav_links" %> diff --git a/app/views/uploads/show.html.erb b/app/views/uploads/show.html.erb index bff822c9b..f32cd4c69 100644 --- a/app/views/uploads/show.html.erb +++ b/app/views/uploads/show.html.erb @@ -13,3 +13,7 @@ <% else %>

    An error occurred: <%= @upload.status %>

    <% end %> + +

    You can <%= link_to "upload another file", new_upload_path %> or <%= link_to "view your current uploads", uploads_path %>.

    + +<%= render :partial => "posts/common_secondary_nav_links" %> diff --git a/config/danbooru_default_config.rb b/config/danbooru_default_config.rb index e495b993c..ef0f1eb60 100644 --- a/config/danbooru_default_config.rb +++ b/config/danbooru_default_config.rb @@ -186,5 +186,10 @@ module Danbooru }.html_safe end + + # The number of posts displayed per page. + def posts_per_page + 20 + end end end diff --git a/config/danbooru_local_config.rb b/config/danbooru_local_config.rb index 794c519fb..ac3382c69 100644 --- a/config/danbooru_local_config.rb +++ b/config/danbooru_local_config.rb @@ -4,5 +4,9 @@ module Danbooru def app_name "f" end + + def posts_per_page + 1 + end end end diff --git a/config/routes.rb b/config/routes.rb index e674aa750..85dff4240 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -20,6 +20,7 @@ Danbooru::Application.routes.draw do |map| resources :janitor_trials resources :jobs resources :notes + resources :note_versions resources :pools do member do put :revert diff --git a/lib/cache.rb b/lib/cache.rb index fd29ea27e..796feddc2 100644 --- a/lib/cache.rb +++ b/lib/cache.rb @@ -1,19 +1,4 @@ module Cache - def expire(options = {}) - tags = options[:tags] - cache_version = Cache.get("$cache_version").to_i - - Cache.put("$cache_version", cache_version + 1) - - if tags - tags.scan(/\S+/).each do |x| - key = "tag:#{x}" - key_version = Cache.get(key).to_i - Cache.put(key, key_version + 1) - end - end - end - def incr(key, expiry = 0) val = Cache.get(key, expiry) Cache.put(key, val.to_i + 1) @@ -98,7 +83,6 @@ module Cache module_function :get module_function :get_multi - module_function :expire module_function :incr module_function :put module_function :delete