major refactoring of post sets and pagination, incomplete
This commit is contained in:
@@ -4,7 +4,7 @@ class PostsController < ApplicationController
|
||||
respond_to :html, :xml, :json
|
||||
|
||||
def index
|
||||
@post_set = PostSets::Post.new(params[:tags], :page => params[:page], :before_id => params[:before_id])
|
||||
@post_set = PostSets::Post.new(params[:tags], params)
|
||||
respond_with(@post_set)
|
||||
end
|
||||
|
||||
|
||||
78
app/helpers/pagination_helper.rb
Normal file
78
app/helpers/pagination_helper.rb
Normal file
@@ -0,0 +1,78 @@
|
||||
module PaginationHelper
|
||||
def smart_paginator(set, &block)
|
||||
if set.page && set.page > 1000
|
||||
sequential_paginator(set)
|
||||
else
|
||||
numbered_paginator(set, &block)
|
||||
end
|
||||
end
|
||||
|
||||
def sequential_paginator(set)
|
||||
html = "<menu>"
|
||||
|
||||
unless set.first_page?
|
||||
html << '<li>' + link_to("« Previous", params.merge(:after_id => set.first_id)) + '</li>'
|
||||
end
|
||||
|
||||
unless set.last_page?
|
||||
html << '<li>' + link_to("Next »", params.merge(:before_id => set.last_id)) + '</li>'
|
||||
end
|
||||
|
||||
html << "</menu>"
|
||||
html.html_safe
|
||||
end
|
||||
|
||||
def numbered_paginator(set, &block)
|
||||
html = "<menu>"
|
||||
window = 3
|
||||
if set.total_pages <= (window * 2) + 5
|
||||
1.upto(set.total_pages) do |page|
|
||||
html << numbered_paginator_item(page, set.current_page, &block)
|
||||
end
|
||||
elsif set.current_page <= window + 2
|
||||
1.upto(set.current_page + window) do |page|
|
||||
html << numbered_paginator_item(page, set.current_page, &block)
|
||||
end
|
||||
html << numbered_paginator_item("...", set.current_page, &block)
|
||||
html << numbered_paginator_final_item(set.total_pages, set.current_page, &block)
|
||||
|
||||
elsif set.current_page >= set.total_pages - (window + 1)
|
||||
html << numbered_paginator_item(1, set.current_page, &block)
|
||||
html << numbered_paginator_item("...", set.current_page, &block)
|
||||
(set.current_page - window).upto(set.total_pages) do |page|
|
||||
html << numbered_paginator_item(page, set.current_page, &block)
|
||||
end
|
||||
else
|
||||
html << numbered_paginator_item(1, set.current_page, &block)
|
||||
html << numbered_paginator_item("...", set.current_page, &block)
|
||||
(set.current_page - window).upto(set.current_page + window) do |page|
|
||||
html << numbered_paginator_item(page, set.current_page, &block)
|
||||
end
|
||||
html << numbered_paginator_item("...", set.current_page, &block)
|
||||
html << numbered_paginator_final_item(set.total_pages, set.current_page, &block)
|
||||
end
|
||||
html << "</menu>"
|
||||
html.html_safe
|
||||
end
|
||||
|
||||
def numbered_paginator_final_item(total_pages, current_page, &block)
|
||||
if total_pages <= 1000
|
||||
numbered_paginator_item(total_pages, current_page, &block)
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
|
||||
def numbered_paginator_item(page, current_page, &block)
|
||||
html = "<li>"
|
||||
if page == "..."
|
||||
html << "..."
|
||||
elsif page == current_page
|
||||
html << page.to_s
|
||||
else
|
||||
html << capture(page, &block)
|
||||
end
|
||||
html << "</li>"
|
||||
html.html_safe
|
||||
end
|
||||
end
|
||||
@@ -5,6 +5,20 @@ class Favorite
|
||||
"favorites_#{user_id.to_i % 10}"
|
||||
end
|
||||
|
||||
def self.sql_order_clause(post_ids, posts_table_alias = "posts")
|
||||
if post_ids.empty?
|
||||
return "#{posts_table_alias}.id desc"
|
||||
end
|
||||
|
||||
conditions = []
|
||||
|
||||
post_ids.each_with_index do |post_id, n|
|
||||
conditions << "when #{post_id} then #{n}"
|
||||
end
|
||||
|
||||
"case #{posts_table_alias}.id " + conditions.join(" ") + " end"
|
||||
end
|
||||
|
||||
def self.create(attributes)
|
||||
user_id = attributes[:user_id]
|
||||
post_id = attributes[:post_id]
|
||||
@@ -26,6 +40,19 @@ class Favorite
|
||||
destroy_for_post(conditions[:post_id])
|
||||
end
|
||||
end
|
||||
|
||||
def self.find_post_ids(user_id, options)
|
||||
limit = options[:limit] || 1 || Danbooru.config.posts_per_page
|
||||
if options[:before_id]
|
||||
select_values_sql("SELECT post_id FROM #{table_name_for(user_id)} WHERE id < ? ORDER BY id DESC LIMIT ?", options[:before_id], limit)
|
||||
elsif options[:after_id]
|
||||
select_values_sql("SELECT post_id FROM #{table_name_for(user_id)} WHERE id > ? ORDER BY id ASC LIMIT ?", options[:after_id], limit).reverse
|
||||
elsif options[:offset]
|
||||
select_values_sql("SELECT post_id FROM #{table_name_for(user_id)} ORDER BY id DESC LIMIT ? OFFSET ?", limit, options[:offset])
|
||||
else
|
||||
select_values_sql("SELECT post_id FROM #{table_name_for(user_id)} ORDER BY id DESC LIMIT ?", limit)
|
||||
end
|
||||
end
|
||||
|
||||
def self.exists?(conditions)
|
||||
if conditions[:user_id] && conditions[:post_id]
|
||||
@@ -39,26 +66,30 @@ class Favorite
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def self.destroy_for_post_and_user(post_id, user_id)
|
||||
execute_sql("DELETE FROM #{table_name_for(user_id)} WHERE post_id = #{post_id} AND user_id = #{user_id}")
|
||||
end
|
||||
|
||||
def self.destroy_for_post(post)
|
||||
0.upto(9) do |i|
|
||||
execute_sql("DELETE FROM favorites_#{i} WHERE post_id = #{post.id}")
|
||||
end
|
||||
end
|
||||
|
||||
def self.destroy_for_user(user)
|
||||
execute_sql("DELETE FROM #{table_name_for(user)} WHERE user_id = #{user.id}")
|
||||
end
|
||||
|
||||
def self.select_value_sql(sql, *params)
|
||||
ActiveRecord::Base.select_value_sql(sql, *params)
|
||||
end
|
||||
|
||||
def self.execute_sql(sql, *params)
|
||||
ActiveRecord::Base.execute_sql(sql, *params)
|
||||
def self.destroy_for_post_and_user(post_id, user_id)
|
||||
execute_sql("DELETE FROM #{table_name_for(user_id)} WHERE post_id = #{post_id} AND user_id = #{user_id}")
|
||||
end
|
||||
|
||||
def self.destroy_for_post(post)
|
||||
0.upto(9) do |i|
|
||||
execute_sql("DELETE FROM favorites_#{i} WHERE post_id = #{post.id}")
|
||||
end
|
||||
end
|
||||
|
||||
def self.destroy_for_user(user)
|
||||
execute_sql("DELETE FROM #{table_name_for(user)} WHERE user_id = #{user.id}")
|
||||
end
|
||||
|
||||
def self.select_value_sql(sql, *params)
|
||||
ActiveRecord::Base.select_value_sql(sql, *params)
|
||||
end
|
||||
|
||||
def self.select_values_sql(sql, *params)
|
||||
ActiveRecord::Base.select_values_sql(sql, *params)
|
||||
end
|
||||
|
||||
def self.execute_sql(sql, *params)
|
||||
ActiveRecord::Base.execute_sql(sql, *params)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,45 +1,78 @@
|
||||
# A PostSet represents a paginated slice of posts. It is used in conjunction
|
||||
# with the helpers to render the paginator.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# @post_set = PostSets::Base.new(params)
|
||||
# @post_set.extend(PostSets::Sequential)
|
||||
# @post_set.extend(PostSets::Post)
|
||||
|
||||
module PostSets
|
||||
class Base
|
||||
attr_accessor :page, :before_id, :count, :posts
|
||||
|
||||
def initialize(options = {})
|
||||
@page = options[:page] ? options[:page].to_i : 1
|
||||
@before_id = options[:before_id]
|
||||
load_posts
|
||||
attr_reader :params, :posts
|
||||
delegate :to_xml, :to_json, :to => :posts
|
||||
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def has_wiki?
|
||||
false
|
||||
end
|
||||
|
||||
def use_sequential_paginator?
|
||||
!use_numbered_paginator?
|
||||
end
|
||||
|
||||
def use_numbered_paginator?
|
||||
before_id.nil?
|
||||
end
|
||||
|
||||
def load_posts
|
||||
# Should a return a paginated array of posts. This means it should have
|
||||
# at most <limit> elements.
|
||||
def posts
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def to_xml
|
||||
posts.to_xml
|
||||
|
||||
# Does this post set have a valid wiki page representation?
|
||||
def has_wiki?
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def to_json
|
||||
posts.to_json
|
||||
|
||||
# Should return an array of strings representing the tags.
|
||||
def tags
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
|
||||
# Given an ActiveRelation object, perform the necessary pagination to
|
||||
# extract at most <limit> elements. Should return an array.
|
||||
def slice(relation)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# For cases where we're not relying on the default pagination
|
||||
# implementation (for example, if the ids are cached in a string)
|
||||
# then pass in the offset/before_id/after_id parameters here.
|
||||
def pagination_options
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# This method should throw an exception if for whatever reason the query
|
||||
# is invalid or forbidden.
|
||||
def validate
|
||||
end
|
||||
|
||||
# Clear out any memoized instance variables.
|
||||
def reload
|
||||
@posts = nil
|
||||
@presenter = nil
|
||||
@tag_string = nil
|
||||
end
|
||||
|
||||
def tag_string
|
||||
@tag_string ||= tags.join(" ")
|
||||
end
|
||||
|
||||
def is_first_page?
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def is_last_page?
|
||||
posts.size == 0
|
||||
end
|
||||
|
||||
def presenter
|
||||
@presenter ||= PostSetPresenter.new(self)
|
||||
end
|
||||
|
||||
def offset
|
||||
((page < 1) ? 0 : (page - 1)) * count
|
||||
end
|
||||
|
||||
def limit
|
||||
Danbooru.config.posts_per_page
|
||||
end
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
module PostSets
|
||||
class Favorite < Base
|
||||
attr_accessor :user
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
super()
|
||||
module Favorite
|
||||
def user
|
||||
@user ||= User.find(params[:id])
|
||||
end
|
||||
|
||||
def tags
|
||||
"fav:#{user.name}"
|
||||
@tags ||= ["fav:#{user.name}"]
|
||||
end
|
||||
|
||||
def has_wiki?
|
||||
false
|
||||
end
|
||||
|
||||
def reload
|
||||
super
|
||||
@user = nil
|
||||
@count = nil
|
||||
end
|
||||
|
||||
def count
|
||||
@count ||= Favorite.count(user.id)
|
||||
end
|
||||
|
||||
def load_posts
|
||||
@posts = user.favorite_posts(:before_id => before_id)
|
||||
def posts
|
||||
@posts ||= user.favorites(pagination_options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
35
app/logical/post_sets/numbered.rb
Normal file
35
app/logical/post_sets/numbered.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
module PostSets
|
||||
module Numbered
|
||||
attr_reader :page
|
||||
|
||||
def initialize(params)
|
||||
super
|
||||
@page = options[:page] ? options[:page].to_i : 1
|
||||
end
|
||||
|
||||
def total_pages
|
||||
@total_pages ||= (count / limit.to_f).ceil.to_i
|
||||
end
|
||||
|
||||
def reload
|
||||
super
|
||||
@total_pages = nil
|
||||
end
|
||||
|
||||
def slice(relation)
|
||||
relation.offset(offset).all
|
||||
end
|
||||
|
||||
def pagination_options
|
||||
{:offset => offset}
|
||||
end
|
||||
|
||||
def is_first_page?
|
||||
offset == 0
|
||||
end
|
||||
|
||||
def offset
|
||||
((page < 1) ? 0 : (page - 1)) * limit
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,33 +1,30 @@
|
||||
# This only works with the numbered paginator because of the way
|
||||
# the association is stored.
|
||||
module PostSets
|
||||
class Pool < Base
|
||||
attr_reader :pool
|
||||
|
||||
def initialize(pool, options = {})
|
||||
@pool = pool
|
||||
@count = pool.post_id_array.size
|
||||
super(options)
|
||||
module Pool
|
||||
def pool
|
||||
@pool ||= Pool.find(params[:id])
|
||||
end
|
||||
|
||||
def tags
|
||||
"pool:#{pool.name}"
|
||||
["pool:#{pool.name}"]
|
||||
end
|
||||
|
||||
def has_wiki?
|
||||
true
|
||||
end
|
||||
|
||||
def count
|
||||
pool.post_count
|
||||
end
|
||||
|
||||
def load_posts
|
||||
@posts = pool.posts(:limit => limit, :offset => offset).order("posts.id")
|
||||
def posts
|
||||
@posts ||= pool.posts(pagination_options)
|
||||
end
|
||||
|
||||
def sorted_posts
|
||||
sort_posts(@posts)
|
||||
end
|
||||
|
||||
private
|
||||
def sort_posts(posts)
|
||||
posts_by_id = posts.inject({}) do |hash, post|
|
||||
hash[post.id] = post
|
||||
hash
|
||||
end
|
||||
|
||||
@pool.post_id_array.map {|x| posts_by_id[x]}
|
||||
def reload
|
||||
super
|
||||
@pool = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,78 +1,56 @@
|
||||
module PostSets
|
||||
class Post < Base
|
||||
module Post
|
||||
class Error < Exception ; end
|
||||
|
||||
attr_accessor :tags, :errors, :count
|
||||
attr_accessor :wiki_page, :artist, :suggestions
|
||||
|
||||
def initialize(tags, options = {})
|
||||
super(options)
|
||||
@tags = Tag.normalize(tags)
|
||||
@errors = []
|
||||
load_associations
|
||||
load_suggestions
|
||||
validate
|
||||
attr_accessor :tags, :count, :wiki_page, :artist, :suggestions
|
||||
|
||||
def tags
|
||||
@tags ||= Tag.normalize(params[:tags])
|
||||
end
|
||||
|
||||
def count
|
||||
@count ||= ::Post.fast_count(tag_string)
|
||||
end
|
||||
|
||||
def posts
|
||||
@posts ||= slice(::Post.tag_match(tags).limit(limit))
|
||||
end
|
||||
|
||||
def reload
|
||||
super
|
||||
@tags = nil
|
||||
@tag_string = nil
|
||||
@count = nil
|
||||
@wiki_page = nil
|
||||
@artist = nil
|
||||
end
|
||||
|
||||
def wiki_page
|
||||
@wiki_page ||= ::WikiPage.titled(tag_string).first
|
||||
end
|
||||
|
||||
def artist
|
||||
@artist ||= ::Artist.find_by_name(tag_string)
|
||||
end
|
||||
|
||||
def has_wiki?
|
||||
is_single_tag?
|
||||
end
|
||||
|
||||
def has_errors?
|
||||
errors.any?
|
||||
end
|
||||
|
||||
def offset
|
||||
x = (page - 1) * limit
|
||||
if x < 0
|
||||
x = 0
|
||||
end
|
||||
x
|
||||
end
|
||||
|
||||
def is_single_tag?
|
||||
tag_array.size == 1
|
||||
end
|
||||
|
||||
def date_tag
|
||||
tag_array.grep(/date:/).first
|
||||
end
|
||||
|
||||
def load_associations
|
||||
if is_single_tag?
|
||||
@wiki_page = ::WikiPage.titled(tags).first
|
||||
@artist = ::Artist.find_by_name(tags)
|
||||
end
|
||||
end
|
||||
|
||||
def load_posts
|
||||
@count = ::Post.fast_count(tags)
|
||||
@posts = ::Post.tag_match(tags).before_id(before_id).all(:order => "posts.id desc", :limit => limit, :offset => offset)
|
||||
end
|
||||
|
||||
def load_suggestions
|
||||
if count < limit && is_single_tag?
|
||||
@suggestions = Tag.find_suggestions(tags)
|
||||
else
|
||||
@suggestions = []
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def tag_array
|
||||
@tag_array ||= Tag.scan_query(tags)
|
||||
end
|
||||
|
||||
def tag
|
||||
tag_array.first
|
||||
end
|
||||
|
||||
def validate
|
||||
super
|
||||
validate_page
|
||||
validate_query_count
|
||||
rescue Error => x
|
||||
@errors << x.to_s
|
||||
end
|
||||
|
||||
|
||||
def validate_page
|
||||
if page > 1_000
|
||||
raise Error.new("You cannot explicitly specify the page after page 1000")
|
||||
|
||||
29
app/logical/post_sets/sequential.rb
Normal file
29
app/logical/post_sets/sequential.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
module PostSets
|
||||
module Sequential
|
||||
attr_reader :before_id, :after_id
|
||||
|
||||
def initialize(params)
|
||||
super
|
||||
@before_id = params[:before_id]
|
||||
@after_id = params[:after_id]
|
||||
end
|
||||
|
||||
def slice(relation)
|
||||
if before_id
|
||||
relation.where("id < ?", before_id).all
|
||||
elsif after_id
|
||||
relation.where("id > ?", after_id).order("id asc").all.reverse
|
||||
else
|
||||
relation.all
|
||||
end
|
||||
end
|
||||
|
||||
def pagination_options
|
||||
{:before_id => before_id, :after_id => after_id}
|
||||
end
|
||||
|
||||
def is_first_page?
|
||||
before_id.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,34 +1,29 @@
|
||||
module PostSets
|
||||
class WikiPage < Base
|
||||
attr_reader :tag_name
|
||||
|
||||
def initialize(tag_name)
|
||||
@tag_name = tag_name
|
||||
super()
|
||||
module WikiPage
|
||||
def wiki_page
|
||||
@wiki_page ||= begin
|
||||
if params[:id]
|
||||
::WikiPage.find(params[:id])
|
||||
elsif params[:tags]
|
||||
::WikiPage.titled(params[:tags]).first
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def load_posts
|
||||
@posts = ::Post.tag_match(tag_name).all(:order => "posts.id desc", :limit => limit, :offset => offset)
|
||||
end
|
||||
|
||||
def limit
|
||||
8
|
||||
end
|
||||
|
||||
def offset
|
||||
0
|
||||
def has_wiki?
|
||||
true
|
||||
end
|
||||
|
||||
def tags
|
||||
[@tag_name]
|
||||
@tags ||= Tag.normalize(wiki_page.title)
|
||||
end
|
||||
|
||||
def use_sequential_paginator?
|
||||
false
|
||||
|
||||
def posts
|
||||
@posts ||= slice(::Post.tag_match(tag_string))
|
||||
end
|
||||
|
||||
def use_numbered_paginator?
|
||||
false
|
||||
|
||||
def count
|
||||
@count ||= ::Post.fast_count(tag_string)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -72,9 +72,9 @@ class Pool < ActiveRecord::Base
|
||||
|
||||
def posts(options = {})
|
||||
offset = options[:offset] || 0
|
||||
limit = options[:limit] || 20
|
||||
limit = options[:limit] || Danbooru.config.posts_per_page
|
||||
ids = post_id_array[offset, limit]
|
||||
Post.where(["id IN (?)", ids])
|
||||
Post.where(["id IN (?)", ids]).order(Favorite.sql_order_clause(ids))
|
||||
end
|
||||
|
||||
def post_id_array
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
class Post < ActiveRecord::Base
|
||||
class ApprovalError < Exception ; end
|
||||
class DisapprovalError < Exception ; end
|
||||
class SearchError < Exception ; end
|
||||
|
||||
attr_accessor :old_tag_string, :old_parent_id
|
||||
after_destroy :delete_files
|
||||
@@ -39,6 +40,7 @@ class Post < ActiveRecord::Base
|
||||
scope :available_for_moderation, lambda {where(["id NOT IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id])}
|
||||
scope :hidden_from_moderation, lambda {where(["id IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id])}
|
||||
scope :before_id, lambda {|id| id.present? ? where(["posts.id < ?", id]) : where("TRUE")}
|
||||
scope :after_id, lambda {|id| id.present? ? where("posts.id > ?", id) : where("true")}
|
||||
scope :tag_match, lambda {|query| Post.tag_match_helper(query)}
|
||||
search_methods :tag_match
|
||||
|
||||
@@ -374,36 +376,33 @@ class Post < ActiveRecord::Base
|
||||
Favorite.destroy_for_post(self)
|
||||
end
|
||||
|
||||
def add_favorite(user)
|
||||
if user.is_a?(ActiveRecord::Base)
|
||||
user_id = user.id
|
||||
else
|
||||
user_id = user
|
||||
def favorited_by?(user_id)
|
||||
fav_string =~ /(?:\A| )fav:#{user_id}(?:\Z| )/
|
||||
end
|
||||
|
||||
def add_favorite(user_id)
|
||||
if user_id.is_a?(ActiveRecord::Base)
|
||||
user_id = user_id.id
|
||||
end
|
||||
|
||||
if favorited_by?(user_id)
|
||||
return false
|
||||
end
|
||||
|
||||
return false if fav_string =~ /(?:\A| )fav:#{user_id}(?:\Z| )/
|
||||
self.fav_string += " fav:#{user_id}"
|
||||
self.fav_string.strip!
|
||||
|
||||
# in order to avoid rerunning the callbacks, just update through raw sql
|
||||
execute_sql("UPDATE posts SET fav_string = ? WHERE id = ?", fav_string, id)
|
||||
|
||||
update_attribute(:fav_string, fav_string)
|
||||
Favorite.create(:user_id => user_id, :post_id => id)
|
||||
end
|
||||
|
||||
def remove_favorite(user)
|
||||
if user.is_a?(ActiveRecord::Base)
|
||||
user_id = user.id
|
||||
else
|
||||
user_id = user
|
||||
def remove_favorite(user_id)
|
||||
if user_id.is_a?(ActiveRecord::Base)
|
||||
user_id = user_id.id
|
||||
end
|
||||
|
||||
self.fav_string.gsub!(/(?:\A| )fav:#{user_id}(?:\Z| )/, " ")
|
||||
self.fav_string.strip!
|
||||
|
||||
# in order to avoid rerunning the callbacks, just update through raw sql
|
||||
execute_sql("UPDATE posts SET fav_string = ? WHERE id = ?", fav_string, id)
|
||||
|
||||
update_attribute(:fav_string, fav_string)
|
||||
Favorite.destroy(:user_id => user_id, :post_id => id)
|
||||
end
|
||||
|
||||
@@ -413,9 +412,9 @@ class Post < ActiveRecord::Base
|
||||
end
|
||||
|
||||
module SearchMethods
|
||||
class SearchError < Exception ; end
|
||||
|
||||
def add_range_relation(arr, field, relation)
|
||||
return relation if arr.nil?
|
||||
|
||||
case arr[0]
|
||||
when :eq
|
||||
relation.where(["#{field} = ?", arr[1]])
|
||||
@@ -513,10 +512,10 @@ class Post < ActiveRecord::Base
|
||||
relation = add_range_relation(q[:character_tag_count], "posts.tag_count_character", relation)
|
||||
relation = add_range_relation(q[:tag_count], "posts.tag_count", relation)
|
||||
|
||||
if q[:md5].any?
|
||||
if q[:md5]
|
||||
relation = relation.where(["posts.md5 IN (?)", q[:md5]])
|
||||
end
|
||||
|
||||
|
||||
if q[:status] == "pending"
|
||||
relation = relation.where("posts.is_pending = TRUE")
|
||||
elsif q[:status] == "flagged"
|
||||
@@ -525,11 +524,11 @@ class Post < ActiveRecord::Base
|
||||
relation = relation.where("posts.is_deleted = TRUE")
|
||||
end
|
||||
|
||||
if q[:source].is_a?(String)
|
||||
if q[:source]
|
||||
relation = relation.where(["posts.source LIKE ? ESCAPE E'\\\\'", q[:source]])
|
||||
end
|
||||
|
||||
if q[:subscriptions].any?
|
||||
if q[:subscriptions]
|
||||
relation = add_tag_subscription_relation(q[:subscriptions], relation)
|
||||
end
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ class Tag < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def parse_query(query, options = {})
|
||||
q = Hash.new {|h, k| h[k] = []}
|
||||
q = {}
|
||||
q[:tags] = {
|
||||
:related => [],
|
||||
:include => [],
|
||||
@@ -237,6 +237,7 @@ class Tag < ActiveRecord::Base
|
||||
q[:tags][:related] << "fav:#{User.name_to_id($2)}"
|
||||
|
||||
when "sub"
|
||||
q[:subscriptions] ||= []
|
||||
q[:subscriptions] << $2
|
||||
|
||||
when "md5"
|
||||
|
||||
@@ -117,16 +117,13 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
|
||||
module FavoriteMethods
|
||||
def favorite_posts(options = {})
|
||||
favorites_table = Favorite.table_name_for(id)
|
||||
if options[:before_id]
|
||||
before_id_sql_fragment = ["favorites.id < ?", options[:before_id]]
|
||||
def favorites(options = {})
|
||||
post_ids = Favorite.find_post_ids(id, options)
|
||||
if post_ids.any?
|
||||
Post.where("id in (?)", post_ids).order(Favorite.sql_order_clause(post_ids))
|
||||
else
|
||||
before_id_sql_fragment = "TRUE"
|
||||
Post.where("false")
|
||||
end
|
||||
limit = options[:limit] || 20
|
||||
|
||||
Post.joins("JOIN #{favorites_table} AS favorites ON favorites.post_id = posts.id").where("favorites.user_id = ?", id).where(before_id_sql_fragment).order("favorite_id DESC").limit(limit).select("posts.*, favorites.id AS favorite_id")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
58
app/presenters/paginators/numbered.rb
Normal file
58
app/presenters/paginators/numbered.rb
Normal file
@@ -0,0 +1,58 @@
|
||||
module Paginators
|
||||
class Numbered
|
||||
attr_reader :template, :source
|
||||
delegate :url, :total_pages, :current_page, :to => :source
|
||||
|
||||
def initialize(template, source)
|
||||
@template = template
|
||||
@source = source
|
||||
end
|
||||
|
||||
def pagination_html
|
||||
html = "<menu>"
|
||||
window = 3
|
||||
if total_pages <= (window * 2) + 5
|
||||
1.upto(total_pages) do |page|
|
||||
html << pagination_item(page, current_page)
|
||||
end
|
||||
elsif current_page <= window + 2
|
||||
1.upto(current_page + window) do |page|
|
||||
html << pagination_item(page, current_page)
|
||||
end
|
||||
html << pagination_item("...", current_page)
|
||||
html << pagination_item(total_pages, current_page)
|
||||
|
||||
elsif current_page >= total_pages - (window + 1)
|
||||
html << pagination_item(1, current_page)
|
||||
html << pagination_item("...", current_page)
|
||||
(current_page - window).upto(total_pages) do |page|
|
||||
html << pagination_item(page, current_page)
|
||||
end
|
||||
else
|
||||
html << pagination_item(1, current_page)
|
||||
html << pagination_item("...", current_page)
|
||||
(current_page - window).upto(current_page + window) do |page|
|
||||
html << pagination_item(page, current_page)
|
||||
end
|
||||
html << pagination_item("...", current_page)
|
||||
html << pagination_item(total_pages, current_page)
|
||||
end
|
||||
html << "</menu>"
|
||||
html.html_safe
|
||||
end
|
||||
|
||||
protected
|
||||
def pagination_item(page, current_page)
|
||||
html = "<li>"
|
||||
if page == "..."
|
||||
html << "..."
|
||||
elsif page == current_page
|
||||
html << page.to_s
|
||||
else
|
||||
html << template.link_to(page, url(template, :page => page))
|
||||
end
|
||||
html << "</li>"
|
||||
html.html_safe
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -15,6 +15,7 @@ module Paginators
|
||||
[1, post_set.page].max
|
||||
end
|
||||
|
||||
# TODO: this is not compatible with paginating favorites
|
||||
def sequential_link(template)
|
||||
template.posts_path(:tags => template.params[:tags], before_id => post_set.posts[-1].id, :page => nil)
|
||||
end
|
||||
|
||||
29
app/presenters/paginators/sequential.rb
Normal file
29
app/presenters/paginators/sequential.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
module Paginators
|
||||
class Sequential
|
||||
attr_reader :template, :source
|
||||
delegate :url, :to => :source
|
||||
|
||||
def initialize(template, source)
|
||||
@template = template
|
||||
@source = source
|
||||
end
|
||||
|
||||
def pagination_html
|
||||
html = "<menu>"
|
||||
html << '<li>' + template.link_to("« Previous", prev_url) + '</li>'
|
||||
if next_url
|
||||
html << '<li>' + template.link_to("Next »", next_url) + '</li>'
|
||||
end
|
||||
html << "</menu>"
|
||||
html.html_safe
|
||||
end
|
||||
|
||||
def prev_url
|
||||
template.request.env["HTTP_REFERER"]
|
||||
end
|
||||
|
||||
def next_url
|
||||
@next_url ||= url(template)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,11 +1,5 @@
|
||||
<div id="c-posts">
|
||||
<div id="a-index">
|
||||
<% if @post_set.suggestions.any? %>
|
||||
<div class="notice">
|
||||
Maybe you meant: <%= @post_set.suggestions.map {|x| link_to(x, posts_path(:tags => x), :class => "tag-type-#{Tag.type_name(x)}" )}.to_sentence(:last_word_connector => ", or ", :two_words_connector => " or ") %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<aside id="sidebar">
|
||||
<section id="search-box">
|
||||
<h1>Search</h1>
|
||||
|
||||
@@ -5,5 +5,7 @@
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<div class="paginator">
|
||||
<%= post_set.presenter.pagination_html(self) %>
|
||||
<%= smart_paginator(post_set) do |page| %>
|
||||
<%= link_to(page, posts_path(:page => page, :tags => params[:tags])) %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<div id="c-uploads">
|
||||
<div id="a-new">
|
||||
<h1>Upload Post</h1>
|
||||
|
||||
<div id="upload-guide-notice">
|
||||
<p>Before uploading, please read the <%= link_to "how to upload guide", wiki_pages_path(:title => "howto:upload") %>.</p>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,7 @@ class CreatePools < ActiveRecord::Migration
|
||||
t.column :description, :text
|
||||
t.column :is_active, :boolean, :null => false, :default => true
|
||||
t.column :post_ids, :text, :null => false, :default => ""
|
||||
t.column :post_count, :integer, :null => false, :default => 0
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user