pools: allow searching pools by post id or post count.

All pools containing post #1:

    https://danbooru.donmai.us/pools?search[post_ids_include]=1

All pools containing either post #1 or #2:

    https://danbooru.donmai.us/pools?search[post_ids_include]=1,2
    https://danbooru.donmai.us/pools?search[post_ids_include]=1+2

Pools with 1-100 posts:

    https://danbooru.donmai.us/pools?search[post_id_count]=1..100

Pools with no posts (empty pools):

    https://danbooru.donmai.us/pools?search[post_id_count]=0
This commit is contained in:
evazion
2019-09-06 16:18:29 -05:00
parent 7d07b5f289
commit a9b7503aa7
3 changed files with 54 additions and 3 deletions

View File

@@ -35,6 +35,18 @@ class ApplicationRecord < ActiveRecord::Base
where.not("#{qualified_column_for(attr)} ~ ?", "(?e)" + value)
end
def where_array_includes(attr, values)
where("#{qualified_column_for(attr)} && ARRAY[?]", values)
end
def where_array_count(attr, value)
relation = all
qualified_column = "cardinality(#{qualified_column_for(attr)})"
parsed_range = Tag.parse_helper(value, :integer)
PostQueryBuilder.new(nil).add_range_relation(parsed_range, qualified_column, relation)
end
def search_boolean_attribute(attribute, params)
return all unless params[attribute]
@@ -81,7 +93,8 @@ class ApplicationRecord < ActiveRecord::Base
end
def search_attribute(name, params)
type = type_for_attribute(name).type || reflect_on_association(name)&.class_name
column = column_for_attribute(name)
type = column.type || reflect_on_association(name)&.class_name
case type
when "User"
@@ -93,7 +106,11 @@ class ApplicationRecord < ActiveRecord::Base
when :boolean
search_boolean_attribute(name, params)
when :integer, :datetime
numeric_attribute_matches(name, params[name])
if column.array?
search_array_attribute(name, type, params)
else
numeric_attribute_matches(name, params[name])
end
else
raise NotImplementedError, "unhandled attribute type"
end
@@ -149,6 +166,21 @@ class ApplicationRecord < ActiveRecord::Base
relation
end
def search_array_attribute(name, type, params)
relation = all
if params[:"#{name}_include"] && type == :integer
items = params[:"#{name}_include"].to_s.scan(/\d+/).map(&:to_i)
relation = relation.where_array_includes(name, items)
end
if params[:"#{name.to_s.singularize}_count"]
relation = relation.where_array_count(name, params[:"#{name.to_s.singularize}_count"])
end
relation
end
def apply_default_order(params)
if params[:order] == "custom"
parse_ids = Tag.parse_helper(params[:id])

View File

@@ -57,7 +57,7 @@ class Pool < ApplicationRecord
def search(params)
q = super
q = q.search_attributes(params, :creator, :is_active, :is_deleted, :name, :description)
q = q.search_attributes(params, :creator, :is_active, :is_deleted, :name, :description, :post_ids)
q = q.text_attribute_matches(:description, params[:description_matches])
if params[:name_matches].present?