Fix #3696: API: handle boolean params consistently

* Use ApplicationRecord#attribute_matches to handle boolean attributes
  consistently in search methods.

* Add support for searching various boolean attributes that previously
  weren't supported.
This commit is contained in:
evazion
2018-05-03 15:29:43 -05:00
parent c7492343ce
commit 216d735f24
15 changed files with 60 additions and 75 deletions

View File

@@ -5,10 +5,34 @@ class ApplicationRecord < ActiveRecord::Base
concerning :SearchMethods do
class_methods do
# range: "5", ">5", "<5", ">=5", "<=5", "5..10", "5,6,7"
def attribute_matches(attribute, range)
return all if range.blank?
def attribute_matches(attribute, value)
return all if value.nil?
column = column_for_attribute(attribute)
case column.sql_type_metadata.type
when :boolean
boolean_attribute_matches(attribute, value)
when :integer, :datetime
numeric_attribute_matches(attribute, value)
else
raise ArgumentError, "unhandled attribute type"
end
end
def boolean_attribute_matches(attribute, value)
if value.to_s.truthy?
value = true
elsif value.to_s.falsy?
value = false
else
raise ArgumentError, "value must be truthy or falsy"
end
where(attribute => value)
end
# range: "5", ">5", "<5", ">=5", "<=5", "5..10", "5,6,7"
def numeric_attribute_matches(attribute, range)
column = column_for_attribute(attribute)
qualified_column = "#{table_name}.#{column.name}"
parsed_range = Tag.parse_helper(range, column.type)

View File

@@ -566,17 +566,8 @@ class Artist < ApplicationRecord
q = q.url_matches(params[:url_matches])
end
if params[:is_active] == "true"
q = q.active
elsif params[:is_active] == "false"
q = q.deleted
end
if params[:is_banned] == "true"
q = q.banned
elsif params[:is_banned] == "false"
q = q.unbanned
end
q = q.attribute_matches(:is_active, params[:is_active])
q = q.attribute_matches(:is_banned, params[:is_banned])
if params[:creator_name].present?
q = q.where("artists.creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].tr(" ", "_").mb_chars.downcase)

View File

@@ -31,17 +31,8 @@ class ArtistVersion < ApplicationRecord
q = q.where(artist_id: params[:artist_id].split(",").map(&:to_i))
end
if params[:is_active] == "true"
q = q.where("is_active = true")
elsif params[:is_active] == "false"
q = q.where("is_active = false")
end
if params[:is_banned] == "true"
q = q.where("is_banned = true")
elsif params[:is_banned] == "false"
q = q.where("is_banned = false")
end
q = q.attribute_matches(:is_active, params[:is_active])
q = q.attribute_matches(:is_banned, params[:is_banned])
params[:order] ||= params.delete(:sort)
if params[:order] == "name"

View File

@@ -59,22 +59,6 @@ class Comment < ApplicationRecord
where("comments.is_deleted = false")
end
def sticky
where("comments.is_sticky = true")
end
def unsticky
where("comments.is_sticky = false")
end
def bumping
where("comments.do_not_bump_post = false")
end
def nonbumping
where("comments.do_not_bump_post = true")
end
def post_tags_match(query)
PostQueryBuilder.new(query).build(self.joins(:post)).reorder("")
end
@@ -110,14 +94,9 @@ class Comment < ApplicationRecord
q = q.for_creator(params[:creator_id].to_i)
end
q = q.deleted if params[:is_deleted] == "true"
q = q.undeleted if params[:is_deleted] == "false"
q = q.sticky if params[:is_sticky] == "true"
q = q.unsticky if params[:is_sticky] == "false"
q = q.nonbumping if params[:do_not_bump_post] == "true"
q = q.bumping if params[:do_not_bump_post] == "false"
q = q.attribute_matches(:is_deleted, params[:is_deleted])
q = q.attribute_matches(:is_sticky, params[:is_sticky])
q = q.attribute_matches(:do_not_bump_post, params[:do_not_bump_post])
case params[:order]
when "post_id", "post_id_desc"

View File

@@ -218,11 +218,10 @@ class Dmail < ApplicationRecord
q = q.where("from_id = ?", params[:from_id].to_i)
end
if params[:is_spam].present?
q = q.where("is_spam = ?", true)
else
q = q.where("is_spam = ?", false)
end
params[:is_spam] = false unless params[:is_spam].present?
q = q.attribute_matches(:is_spam, params[:is_spam])
q = q.attribute_matches(:is_read, params[:is_read])
q = q.attribute_matches(:is_deleted, params[:is_deleted])
q = q.read if params[:read].to_s.truthy?
q = q.unread if params[:read].to_s.falsy?

View File

@@ -65,6 +65,8 @@ class FavoriteGroup < ApplicationRecord
q = q.name_matches(params[:name_matches])
end
q = q.attribute_matches(:is_public, params[:is_public])
q.apply_default_order(params)
end
end

View File

@@ -92,6 +92,8 @@ class ForumPost < ApplicationRecord
q = q.joins(:topic).where("forum_topics.category_id = ?", params[:topic_category_id].to_i)
end
q = q.attribute_matches(:is_deleted, params[:is_deleted])
q.apply_default_order(params)
end
end

View File

@@ -95,6 +95,10 @@ class ForumTopic < ApplicationRecord
q = q.where("title = ?", params[:title])
end
q = q.attribute_matches(:is_sticky, params[:is_sticky])
q = q.attribute_matches(:is_locked, params[:is_locked])
q = q.attribute_matches(:is_deleted, params[:is_deleted])
case params[:order]
when "sticky"
q = q.sticky_first

View File

@@ -47,11 +47,7 @@ class Note < ApplicationRecord
q = q.body_matches(params[:body_matches])
end
if params[:is_active] == "true"
q = q.active
elsif params[:is_active] == "false"
q = q.where("is_active = false")
end
q = q.attribute_matches(:is_active, params[:is_active])
if params[:post_id].present?
q = q.where(post_id: params[:post_id].split(",").map(&:to_i))

View File

@@ -17,6 +17,8 @@ class NoteVersion < ApplicationRecord
q = q.where(note_id: params[:note_id].split(",").map(&:to_i))
end
q = q.attribute_matches(:is_active, params[:is_active])
q.apply_default_order(params)
end

View File

@@ -70,23 +70,14 @@ class Pool < ApplicationRecord
q = q.where(creator_id: params[:creator_id].split(",").map(&:to_i))
end
if params[:is_active] == "true"
q = q.where("pools.is_active = true")
elsif params[:is_active] == "false"
q = q.where("pools.is_active = false")
end
if params[:category] == "series"
q = q.series
elsif params[:category] == "collection"
q = q.collection
end
if params[:is_deleted] == "true"
q = q.deleted
else
q = q.undeleted
end
q = q.attribute_matches(:is_active, params[:is_active])
q = q.attribute_matches(:is_deleted, params[:is_deleted])
params[:order] ||= params.delete(:sort)
case params[:order]

View File

@@ -98,11 +98,7 @@ class PostFlag < ApplicationRecord
q = q.post_tags_match(params[:post_tags_match])
end
if params[:is_resolved] == "true"
q = q.resolved
elsif params[:is_resolved] == "false"
q = q.unresolved
end
q = q.attribute_matches(:is_resolved, params[:is_resolved])
case params[:category]
when "normal"

View File

@@ -903,6 +903,8 @@ class Tag < ApplicationRecord
q = q.joins("LEFT JOIN artists ON tags.name = artists.name").where("artists.name IS NULL OR artists.is_active = false")
end
q = q.attribute_matches(:is_locked, params[:is_locked])
params[:order] ||= params.delete(:sort)
case params[:order]
when "name"

View File

@@ -92,6 +92,9 @@ class WikiPage < ApplicationRecord
q = q.where("other_names is null or other_names = ''")
end
q = q.attribute_matches(:is_locked, params[:is_locked])
q = q.attribute_matches(:is_deleted, params[:is_deleted])
params[:order] ||= params.delete(:sort)
case params[:order]
when "title"

View File

@@ -20,6 +20,9 @@ class WikiPageVersion < ApplicationRecord
q = q.where("wiki_page_id = ?", params[:wiki_page_id].to_i)
end
q = q.attribute_matches(:is_locked, params[:is_locked])
q = q.attribute_matches(:is_deleted, params[:is_deleted])
q.apply_default_order(params)
end
end