Add ability to use nested only parameter

- The only string works much the same as before with its comma separation
-- Nested includes are indicated with square brackets "[ ]"
-- The nested include is the value immediately preceding the square brackets
-- The only string is the comma separated string inside those brackets
- Default includes are split between format types when necessary
-- This prevents unnecessary includes from being added on page load
- Available includes are those items which are allowed to be accessible to the user
-- Some aren't because they are sensitive, such as the creator of a flag
-- Some aren't because the number of associated items is too large
- The amount of times the same model can be included to prevent recursions
-- One exception is the root model may include the same model once
--- e.g. the user model can include the inviter which is also the user model
-- Another exception is if the include is a has_many association
--- e.g. artist urls can include the artist, and then artist urls again
This commit is contained in:
BrokenEagle
2020-02-12 23:46:36 +00:00
parent dd425830ca
commit 63b3503bfc
85 changed files with 634 additions and 85 deletions

View File

@@ -34,6 +34,25 @@ class ApplicationController < ActionController::Base
end
end
def model_includes(params, model = nil)
if params[:only] && ["json", "xml"].include?(params[:format])
includes_array = ParameterBuilder.includes_parameters(params[:only], model_name)
elsif params[:action] == "index"
includes_array = default_includes(params)
else
includes_array = []
end
includes_array
end
def default_includes(*)
[]
end
def model_name
controller_name.classify
end
def redirect_to_show(items)
redirect_to send("#{controller_path.singularize}_path", items.first, format: request.format.symbol)
end

View File

@@ -3,7 +3,7 @@ class ArtistCommentariesController < ApplicationController
before_action :member_only, only: [:create_or_update, :revert]
def index
@commentaries = ArtistCommentary.paginated_search(params)
@commentaries = ArtistCommentary.paginated_search(params).includes(model_includes(params))
respond_with(@commentaries)
end
@@ -36,6 +36,14 @@ class ArtistCommentariesController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[{post: [:uploader]}]
end
end
def commentary_params
params.fetch(:artist_commentary, {}).except(:post_id).permit(%i[
original_description original_title translated_description translated_title

View File

@@ -2,7 +2,7 @@ class ArtistCommentaryVersionsController < ApplicationController
respond_to :html, :xml, :json
def index
@commentary_versions = ArtistCommentaryVersion.paginated_search(params)
@commentary_versions = ArtistCommentaryVersion.paginated_search(params).includes(model_includes(params))
respond_with(@commentary_versions)
end
@@ -12,4 +12,14 @@ class ArtistCommentaryVersionsController < ApplicationController
format.html { redirect_to artist_commentary_versions_path(search: { post_id: @commentary_version.post_id }) }
end
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[{post: [:uploader]}, :updater]
end
end
end

View File

@@ -3,10 +3,10 @@ class ArtistUrlsController < ApplicationController
before_action :member_only, except: [:index]
def index
@artist_urls = ArtistUrl.includes(:artist).paginated_search(params)
@artist_urls = ArtistUrl.paginated_search(params).includes(model_includes(params))
respond_with(@artist_urls) do |format|
format.json { render json: @artist_urls.to_json(include: "artist") }
format.xml { render xml: @artist_urls.to_xml(include: "artist", root: "artist-urls") }
format.json { render json: @artist_urls.to_json(format_params) }
format.xml { render xml: @artist_urls.to_xml(format_params) }
end
end
@@ -18,6 +18,27 @@ class ArtistUrlsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[{artist: [:urls]}]
else
[:artist]
end
end
def format_params
param_hash = {}
if params[:only]
param_hash[:only] = params[:only]
else
param_hash[:include] = [:artist]
end
if request.format.symbol == :xml
param_hash[:root] = "artist-urls"
end
param_hash
end
def artist_url_params
permitted_params = %i[is_active]

View File

@@ -2,7 +2,7 @@ class ArtistVersionsController < ApplicationController
respond_to :html, :xml, :json
def index
@artist_versions = ArtistVersion.includes(:updater).paginated_search(params)
@artist_versions = ArtistVersion.paginated_search(params).includes(model_includes(params))
respond_with(@artist_versions)
end
@@ -12,4 +12,14 @@ class ArtistVersionsController < ApplicationController
format.html { redirect_to artist_versions_path(search: { artist_id: @artist_version.artist_id }) }
end
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:updater, {artist: [:urls]}]
end
end
end

View File

@@ -31,10 +31,7 @@ class ArtistsController < ApplicationController
# XXX
params[:search][:name] = params.delete(:name) if params[:name]
@artists = Artist.includes(:urls).paginated_search(params)
@artists = @artists.includes(:tag) if request.format.html?
@artists = @artists.includes(:urls) if !request.format.html?
@artists = Artist.paginated_search(params).includes(model_includes(params))
respond_with(@artists)
end
@@ -81,6 +78,14 @@ class ArtistsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[:urls]
else
[:urls, :tag]
end
end
def item_matches_params(artist)
if params[:search][:any_name_or_url_matches]
artist.name == Artist.normalize_name(params[:search][:any_name_or_url_matches])

View File

@@ -12,10 +12,8 @@ class BansController < ApplicationController
end
def index
@bans = Ban.paginated_search(params, count_pages: true)
respond_with(@bans) do |fmt|
fmt.html { @bans = @bans.includes(:user, :banner) }
end
@bans = Ban.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@bans)
end
def show
@@ -50,6 +48,14 @@ class BansController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:user, :banner]
end
end
def ban_params(context)
permitted_params = %i[reason duration expires_at]
permitted_params += %i[user_id user_name] if context == :create

View File

@@ -42,12 +42,20 @@ class BulkUpdateRequestsController < ApplicationController
end
def index
@bulk_update_requests = BulkUpdateRequest.includes(:user, :approver, :forum_topic, forum_post: [:votes]).paginated_search(params, count_pages: true)
@bulk_update_requests = BulkUpdateRequest.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@bulk_update_requests)
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:user, :approver, :forum_topic, {forum_post: [:votes]}]
end
end
def load_bulk_update_request
@bulk_update_request = BulkUpdateRequest.find(params[:id])
end

View File

@@ -5,7 +5,7 @@ class CommentVotesController < ApplicationController
rescue_with CommentVote::Error, ActiveRecord::RecordInvalid, status: 422
def index
@comment_votes = CommentVote.includes(:user, comment: [:creator, :post]).paginated_search(params, count_pages: true)
@comment_votes = CommentVote.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@comment_votes)
end
@@ -20,4 +20,14 @@ class CommentVotesController < ApplicationController
@comment.unvote!
respond_with(@comment)
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:user, {comment: [:creator, {post: [:uploader]}]}]
end
end
end

View File

@@ -1,5 +1,5 @@
class CommentsController < ApplicationController
respond_to :html, :xml, :json
respond_to :html, :xml, :json, :atom
respond_to :js, only: [:new, :destroy, :undelete]
before_action :member_only, :except => [:index, :search, :show]
skip_before_action :api_check
@@ -74,6 +74,18 @@ class CommentsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[:creator, :updater]
elsif params[:format] == "atom"
[:creator, :post]
else
includes_array = [:creator, :updater, {post: [:uploader]}]
includes_array << :votes if CurrentUser.is_member?
includes_array
end
end
def index_for_post
@post = Post.find(params[:post_id])
@comments = @post.comments
@@ -90,12 +102,8 @@ class CommentsController < ApplicationController
end
def index_by_comment
@comments = Comment.includes(:creator, :updater).paginated_search(params)
respond_with(@comments) do |format|
format.atom do
@comments = @comments.includes(:post, :creator).load
end
end
@comments = Comment.paginated_search(params).includes(model_includes(params))
respond_with(@comments)
end
def check_privilege(comment)

View File

@@ -15,7 +15,7 @@ class DmailsController < ApplicationController
end
def index
@dmails = Dmail.visible.paginated_search(params, defaults: { folder: "received" }, count_pages: true)
@dmails = Dmail.visible.paginated_search(params, defaults: { folder: "received" }, count_pages: true).includes(model_includes(params))
respond_with(@dmails)
end
@@ -51,6 +51,14 @@ class DmailsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:owner, :to, :from]
end
end
def check_show_privilege(dmail)
raise User::PrivilegeError unless dmail.visible_to?(CurrentUser.user, params[:key])
end

View File

@@ -2,7 +2,17 @@ class DtextLinksController < ApplicationController
respond_to :html, :xml, :json
def index
@dtext_links = DtextLink.includes(:model).paginated_search(params)
@dtext_links = DtextLink.paginated_search(params).includes(model_includes(params))
respond_with(@dtext_links)
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:model]
end
end
end

View File

@@ -4,7 +4,7 @@ class FavoriteGroupsController < ApplicationController
def index
params[:search][:creator_id] ||= params[:user_id]
@favorite_groups = FavoriteGroup.paginated_search(params)
@favorite_groups = FavoriteGroup.paginated_search(params).includes(model_includes(params))
respond_with(@favorite_groups)
end
@@ -61,6 +61,14 @@ class FavoriteGroupsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:creator]
end
end
def check_write_privilege(favgroup)
raise User::PrivilegeError unless favgroup.editable_by?(CurrentUser.user)
end

View File

@@ -3,7 +3,7 @@ class ForumPostVotesController < ApplicationController
before_action :member_only, only: [:create, :destroy]
def index
@forum_post_votes = ForumPostVote.includes(creator: [], forum_post: [:topic]).paginated_search(params, count_pages: true)
@forum_post_votes = ForumPostVote.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@forum_post_votes)
end
@@ -21,6 +21,14 @@ class ForumPostVotesController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:creator, {forum_post: [:topic]}]
end
end
def forum_post_vote_params
params.fetch(:forum_post_vote, {}).permit(:score)
end

View File

@@ -24,7 +24,7 @@ class ForumPostsController < ApplicationController
end
def index
@forum_posts = ForumPost.paginated_search(params).includes(:topic)
@forum_posts = ForumPost.paginated_search(params).includes(model_includes(params))
respond_with(@forum_posts)
end
@@ -68,6 +68,14 @@ class ForumPostsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:topic, :creator]
end
end
def load_post
@forum_post = ForumPost.find(params[:id])
@forum_topic = @forum_post.topic

View File

@@ -23,10 +23,7 @@ class ForumTopicsController < ApplicationController
params[:search][:order] ||= "sticky" if request.format == Mime::Type.lookup("text/html")
params[:limit] ||= 40
@forum_topics = ForumTopic.paginated_search(params)
@forum_topics = @forum_topics.includes(:creator, :updater, :forum_topic_visit_by_current_user).load if request.format.html?
@forum_topics = @forum_topics.includes(:creator, :original_post).load if request.format.atom?
@forum_topics = ForumTopic.paginated_search(params).includes(model_includes(params))
respond_with(@forum_topics)
end
@@ -80,6 +77,16 @@ class ForumTopicsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
elsif params[:format] == "atom"
[:creator, :original_post]
else
[:creator, :updater, :forum_topic_visit_by_current_user]
end
end
def normalize_search
if params[:title_matches]
params[:search] ||= {}

View File

@@ -3,16 +3,30 @@ class IpAddressesController < ApplicationController
before_action :moderator_only
def index
@ip_addresses = IpAddress.visible(CurrentUser.user).paginated_search(params)
@ip_addresses = IpAddress.visible(CurrentUser.user).paginated_search(params).includes(model_includes(params))
if search_params[:group_by] == "ip_addr"
@ip_addresses = @ip_addresses.group_by_ip_addr(search_params[:ipv4_masklen], search_params[:ipv6_masklen])
elsif search_params[:group_by] == "user"
@ip_addresses = @ip_addresses.group_by_user.includes(:user)
else
@ip_addresses = @ip_addresses.includes(:user, :model)
@ip_addresses = @ip_addresses.group_by_user
end
respond_with(@ip_addresses)
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
if params[:search][:group_by] == "user"
[:user]
elsif params[:search][:group_by] == "ip_addr"
[]
else
[:user, :model]
end
end
end
end

View File

@@ -12,7 +12,7 @@ class IpBansController < ApplicationController
end
def index
@ip_bans = IpBan.includes(:creator).paginated_search(params, count_pages: true)
@ip_bans = IpBan.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@ip_bans)
end
@@ -24,6 +24,14 @@ class IpBansController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:creator]
end
end
def ip_ban_params
params.fetch(:ip_ban, {}).permit(%i[ip_addr reason])
end

View File

@@ -3,6 +3,7 @@ class LegacyController < ApplicationController
def posts
@post_set = PostSets::Post.new(tag_query, params[:page], params[:limit], format: "json")
@post_set.posts = @post_set.posts.includes(:uploader)
@posts = @post_set.posts.map(&:legacy_attributes)
respond_with(@posts) do |format|

View File

@@ -2,7 +2,7 @@ class ModActionsController < ApplicationController
respond_to :html, :xml, :json
def index
@mod_actions = ModAction.includes(:creator).paginated_search(params)
@mod_actions = ModAction.paginated_search(params).includes(model_includes(params))
respond_with(@mod_actions)
end
@@ -12,4 +12,14 @@ class ModActionsController < ApplicationController
fmt.html { redirect_to mod_actions_path(search: { id: @mod_action.id }) }
end
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:creator]
end
end
end

View File

@@ -10,7 +10,7 @@ class ModerationReportsController < ApplicationController
end
def index
@moderation_reports = ModerationReport.paginated_search(params, count_pages: true).includes(:creator, :model)
@moderation_reports = ModerationReport.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@moderation_reports)
end
@@ -29,6 +29,14 @@ class ModerationReportsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:creator, :model]
end
end
def model_type
params.fetch(:moderation_report, {}).fetch(:model_type)
end

View File

@@ -12,12 +12,24 @@ module Moderator
end
def index
@post_disapprovals = PostDisapproval.includes(:user).paginated_search(params)
@post_disapprovals = PostDisapproval.paginated_search(params).includes(model_includes(params))
respond_with(@post_disapprovals)
end
private
def model_name
"PostDisapproval"
end
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:user]
end
end
def post_disapproval_params
params.require(:post_disapproval).permit(%i[post_id reason message])
end

View File

@@ -2,8 +2,7 @@ class NoteVersionsController < ApplicationController
respond_to :html, :xml, :json
def index
@note_versions = NoteVersion.paginated_search(params)
@note_versions = @note_versions.includes(:updater) if request.format.html?
@note_versions = NoteVersion.paginated_search(params).includes(model_includes(params))
respond_with(@note_versions)
end
@@ -13,4 +12,14 @@ class NoteVersionsController < ApplicationController
format.html { redirect_to note_versions_path(search: { note_id: @note_version.note_id }) }
end
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:updater]
end
end
end

View File

@@ -6,8 +6,7 @@ class NotesController < ApplicationController
end
def index
@notes = Note.includes(:creator).paginated_search(params)
@notes = @notes.includes(:creator) if request.format.html?
@notes = Note.paginated_search(params).includes(model_includes(params))
respond_with(@notes)
end
@@ -60,6 +59,14 @@ class NotesController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[:creator]
else
[:creator, :post]
end
end
def note_params(context)
permitted_params = %i[x y width height body]
permitted_params += %i[post_id html_id] if context == :create

View File

@@ -8,7 +8,7 @@ class PoolVersionsController < ApplicationController
@pool = Pool.find(params[:search][:pool_id])
end
@pool_versions = PoolArchive.paginated_search(params).includes(:updater, :pool)
@pool_versions = PoolArchive.paginated_search(params).includes(model_includes(params))
respond_with(@pool_versions)
end
@@ -27,6 +27,18 @@ class PoolVersionsController < ApplicationController
private
def model_name
"PoolArchive"
end
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:updater, :pool]
end
end
def set_timeout
PoolArchive.connection.execute("SET statement_timeout = #{CurrentUser.user.statement_timeout}")
yield

View File

@@ -17,7 +17,7 @@ class PoolsController < ApplicationController
end
def index
@pools = Pool.includes(:creator).paginated_search(params, count_pages: true)
@pools = Pool.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@pools)
end
@@ -90,6 +90,10 @@ class PoolsController < ApplicationController
private
def default_includes(params)
[:creator]
end
def item_matches_params(pool)
if params[:search][:name_matches]
Pool.normalize_name_for_search(pool.name) == Pool.normalize_name_for_search(params[:search][:name_matches])

View File

@@ -8,7 +8,7 @@ class PostAppealsController < ApplicationController
end
def index
@post_appeals = PostAppeal.includes(:creator).paginated_search(params).includes(post: [:appeals, :uploader, :approver])
@post_appeals = PostAppeal.paginated_search(params).includes(model_includes(params))
respond_with(@post_appeals)
end
@@ -26,6 +26,14 @@ class PostAppealsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[:post]
else
[:creator, {post: [:appeals, :uploader, :approver]}]
end
end
def post_appeal_params
params.fetch(:post_appeal, {}).permit(%i[post_id reason])
end

View File

@@ -2,7 +2,17 @@ class PostApprovalsController < ApplicationController
respond_to :html, :xml, :json
def index
@post_approvals = PostApproval.includes(:post, :user).paginated_search(params)
@post_approvals = PostApproval.paginated_search(params).includes(model_includes(params))
respond_with(@post_approvals)
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:user, {post: [:uploader]}]
end
end
end

View File

@@ -8,7 +8,7 @@ class PostFlagsController < ApplicationController
end
def index
@post_flags = PostFlag.paginated_search(params).includes(:creator, post: [:flags, :uploader, :approver])
@post_flags = PostFlag.paginated_search(params).includes(model_includes(params))
respond_with(@post_flags)
end
@@ -26,6 +26,16 @@ class PostFlagsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[:post]
else
includes_array = [{post: [:flags, :uploader, :approver]}]
includes_array << :creator if CurrentUser.is_moderator?
includes_array
end
end
def post_flag_params
params.fetch(:post_flag, {}).permit(%i[post_id reason])
end

View File

@@ -24,13 +24,21 @@ class PostReplacementsController < ApplicationController
def index
params[:search][:post_id] = params.delete(:post_id) if params.key?(:post_id)
@post_replacements = PostReplacement.paginated_search(params)
@post_replacements = PostReplacement.paginated_search(params).includes(model_includes(params))
respond_with(@post_replacements)
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:creator, {post: [:uploader]}]
end
end
def create_params
params.require(:post_replacement).permit(:replacement_url, :replacement_file, :final_source, :tags)
end

View File

@@ -6,7 +6,7 @@ class PostVersionsController < ApplicationController
respond_to :js, only: [:undo]
def index
@post_versions = PostArchive.includes(:updater, post: [:versions]).paginated_search(params)
@post_versions = PostArchive.paginated_search(params).includes(model_includes(params))
respond_with(@post_versions)
end
@@ -22,6 +22,18 @@ class PostVersionsController < ApplicationController
private
def model_name
"PostArchive"
end
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[:updater, {post: [:versions]}]
else
[:updater, {post: [:uploader, :versions]}]
end
end
def set_timeout
PostArchive.connection.execute("SET statement_timeout = #{CurrentUser.user.statement_timeout}")
yield

View File

@@ -5,7 +5,7 @@ class PostVotesController < ApplicationController
rescue_with PostVote::Error, status: 422
def index
@post_votes = PostVote.includes(:user, post: [:uploader]).paginated_search(params, count_pages: true)
@post_votes = PostVote.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@post_votes)
end
@@ -22,4 +22,14 @@ class PostVotesController < ApplicationController
respond_with(@post)
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:user, {post: [:uploader]}]
end
end
end

View File

@@ -11,7 +11,7 @@ class PostsController < ApplicationController
end
else
@post_set = PostSets::Post.new(tag_query, params[:page], params[:limit], raw: params[:raw], random: params[:random], format: params[:format])
@posts = @post_set.posts
@posts = @post_set.posts = @post_set.posts.includes(model_includes(params)) if !@post_set.is_random?
respond_with(@posts) do |format|
format.atom
end
@@ -96,6 +96,14 @@ class PostsController < ApplicationController
private
def default_includes(params)
if ["json", "xml", "atom"].include?(params[:format])
[:uploader]
else
(CurrentUser.user.is_moderator? ? [:uploader] : [])
end
end
def tag_query
params[:tags] || (params[:post] && params[:post][:tags])
end

View File

@@ -2,7 +2,7 @@ class SavedSearchesController < ApplicationController
respond_to :html, :xml, :json, :js
def index
@saved_searches = saved_searches.paginated_search(params, count_pages: true)
@saved_searches = saved_searches.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@saved_searches)
end

View File

@@ -22,7 +22,7 @@ class TagAliasesController < ApplicationController
end
def index
@tag_aliases = TagAlias.includes(:antecedent_tag, :consequent_tag, :approver).paginated_search(params, count_pages: true)
@tag_aliases = TagAlias.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@tag_aliases)
end
@@ -42,6 +42,14 @@ class TagAliasesController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:antecedent_tag, :consequent_tag, :approver]
end
end
def tag_alias_params
params.require(:tag_alias).permit(%i[antecedent_name consequent_name forum_topic_id skip_secondary_validations])
end

View File

@@ -22,7 +22,7 @@ class TagImplicationsController < ApplicationController
end
def index
@tag_implications = TagImplication.includes(:antecedent_tag, :consequent_tag, :approver).paginated_search(params, count_pages: true)
@tag_implications = TagImplication.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@tag_implications)
end
@@ -42,6 +42,14 @@ class TagImplicationsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:antecedent_tag, :consequent_tag, :approver]
end
end
def tag_implication_params
params.require(:tag_implication).permit(%i[antecedent_name consequent_name forum_topic_id skip_secondary_validations])
end

View File

@@ -9,7 +9,7 @@ class TagsController < ApplicationController
end
def index
@tags = Tag.paginated_search(params)
@tags = Tag.paginated_search(params).includes(model_includes(params))
respond_with(@tags)
end

View File

@@ -23,7 +23,7 @@ class UploadsController < ApplicationController
end
def index
@uploads = Upload.paginated_search(params, count_pages: true).includes(:post, :uploader)
@uploads = Upload.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@uploads)
end
@@ -58,6 +58,14 @@ class UploadsController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[:uploader]
else
[:uploader, {post: [:uploader]}]
end
end
def upload_params
permitted_params = %i[
file source tag_string rating status parent_id artist_commentary_title

View File

@@ -19,7 +19,7 @@ class UserFeedbacksController < ApplicationController
end
def index
@user_feedbacks = UserFeedback.includes(:user, :creator).paginated_search(params, count_pages: true)
@user_feedbacks = UserFeedback.paginated_search(params, count_pages: true).includes(model_includes(params))
respond_with(@user_feedbacks)
end
@@ -37,6 +37,14 @@ class UserFeedbacksController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:user, :creator]
end
end
def check_privilege(user_feedback)
raise User::PrivilegeError unless user_feedback.editable_by?(CurrentUser.user)
end

View File

@@ -31,7 +31,7 @@ class UsersController < ApplicationController
return
end
@users = User.paginated_search(params)
@users = User.paginated_search(params).includes(model_includes(params))
respond_with(@users)
end
@@ -94,6 +94,14 @@ class UsersController < ApplicationController
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:inviter]
end
end
def item_matches_params(user)
if params[:search][:name_matches]
User.normalize_name(user.name) == User.normalize_name(params[:search][:name_matches])

View File

@@ -3,7 +3,7 @@ class WikiPageVersionsController < ApplicationController
layout "sidebar"
def index
@wiki_page_versions = WikiPageVersion.paginated_search(params)
@wiki_page_versions = WikiPageVersion.paginated_search(params).includes(model_includes(params))
respond_with(@wiki_page_versions)
end
@@ -27,4 +27,14 @@ class WikiPageVersionsController < ApplicationController
respond_with([@thispage, @otherpage])
end
private
def default_includes(params)
if ["json", "xml"].include?(params[:format])
[]
else
[:updater]
end
end
end

View File

@@ -15,7 +15,7 @@ class WikiPagesController < ApplicationController
end
def index
@wiki_pages = WikiPage.paginated_search(params)
@wiki_pages = WikiPage.paginated_search(params).includes(model_includes(params))
respond_with(@wiki_pages)
end

View File

@@ -17,7 +17,7 @@ class ApplicationResponder < ActionController::Responder
options[:root] ||= resource.table_name.dasherize if resource.respond_to?(:table_name)
end
options[:only] ||= params["only"].scan(/\w+/) if params["only"]
options[:only] ||= params["only"] if params["only"]
super
end

View File

@@ -109,15 +109,13 @@ module PostSets
else
temp = ::Post.tag_match(tag_string).where("true /* PostSets::Post#posts:2 */").paginate(page, :count => post_count, :limit => per_page)
end
# HACK: uploader_name is needed in api responses and in data-uploader attribs (visible to mods only).
temp = temp.includes(:uploader) if !is_random? && (format.to_sym != :html || CurrentUser.is_moderator?)
temp.each # hack to force rails to eager load
temp
end
end
def posts=(set_posts)
@posts = set_posts
end
def unknown_post_count?
post_count == Danbooru.config.blank_tag_search_fast_count
end

View File

@@ -322,6 +322,26 @@ class ApplicationRecord < ActiveRecord::Base
@api_attributes += including
@api_attributes
end
def available_includes
[]
end
def multiple_includes
reflections.reject { |k,v| v.macro != :has_many }.keys.map(&:to_sym)
end
def associated_models(name)
if reflections[name].options[:polymorphic]
associated_models = reflections[name].active_record.try(:model_types) || []
else
associated_models = [reflections[name].class_name]
end
end
end
def available_includes
self.class.available_includes
end
def api_attributes
@@ -338,25 +358,24 @@ class ApplicationRecord < ActiveRecord::Base
def serializable_hash(options = {})
options ||= {}
options[:only] ||= []
options[:include] ||= []
options[:methods] ||= []
if options[:only] && options[:only].is_a?(String)
options.delete(:methods)
options.delete(:include)
options.merge!(ParameterBuilder.serial_parameters(options[:only], self))
else
options[:methods] ||= []
attributes, methods = api_attributes.partition { |attr| has_attribute?(attr) }
methods += options[:methods]
options[:only] ||= attributes + methods
options[:only] = options[:only].map(&:to_sym)
attributes, methods = api_attributes.partition { |attr| has_attribute?(attr) }
methods += options[:methods]
includes = options[:include]
if options[:only].present?
attributes &= options[:only]
methods &= options[:only]
includes &= options[:only]
end
options[:only] = attributes
options[:methods] = methods
options[:include] = includes
options[:only] = attributes
options[:methods] = methods
options.delete(:methods) if options[:methods].empty?
end
hash = super(options)
hash.transform_keys { |key| key.delete("?") }

View File

@@ -508,4 +508,8 @@ class Artist < ApplicationRecord
"Deleted"
end
end
def self.available_includes
[:creator, :members, :urls, :wiki_page, :tag_alias, :tag]
end
end

View File

@@ -144,4 +144,8 @@ class ArtistCommentary < ApplicationRecord
extend SearchMethods
include VersionMethods
def self.available_includes
[:post]
end
end

View File

@@ -27,4 +27,8 @@ class ArtistCommentaryVersion < ApplicationRecord
def unchanged_empty?(field)
self[field].strip.empty? && (previous.nil? || previous[field].strip.empty?)
end
def self.available_includes
[:post, :updater]
end
end

View File

@@ -126,4 +126,8 @@ class ArtistUrl < ApplicationRecord
rescue Addressable::URI::InvalidURIError => error
errors[:url] << "'#{uri}' is malformed: #{error}"
end
def self.available_includes
[:artist]
end
end

View File

@@ -66,4 +66,8 @@ class ArtistVersion < ApplicationRecord
def was_unbanned
!is_banned && previous.is_banned
end
def self.available_includes
[:updater, :artist]
end
end

View File

@@ -115,4 +115,8 @@ class Ban < ApplicationRecord
def create_unban_mod_action
ModAction.log(%{Unbanned <@#{user_name}>}, :user_unban)
end
def self.available_includes
[:user, :banner]
end
end

View File

@@ -216,4 +216,8 @@ class BulkUpdateRequest < ApplicationRecord
forum_topic_id
)
end
def self.available_includes
[:user, :forum_topic, :forum_post, :approver]
end
end

View File

@@ -174,4 +174,10 @@ class Comment < ApplicationRecord
def quoted_response
DText.quote(body, creator.name)
end
def self.available_includes
includes_array = [:post, :creator, :updater]
includes_array << :moderation_reports if CurrentUser.is_moderator?
includes_array
end
end

View File

@@ -51,4 +51,8 @@ class CommentVote < ApplicationRecord
def initialize_user
self.user_id = CurrentUser.user.id
end
def self.available_includes
[:comment, :user]
end
end

View File

@@ -195,4 +195,10 @@ class Dmail < ApplicationRecord
def dtext_shortlink(key: false, **options)
key ? "dmail ##{id}/#{self.key}" : "dmail ##{id}"
end
def self.available_includes
includes_array = [:owner, :to, :from]
includes_array << :moderation_reports if CurrentUser.is_moderator?
includes_array
end
end

View File

@@ -8,6 +8,10 @@ class DtextLink < ApplicationRecord
scope :wiki_page, -> { where(model_type: "WikiPage") }
scope :forum_post, -> { where(model_type: "ForumPost") }
def self.model_types
%w[WikiPage ForumPost]
end
def self.new_from_dtext(dtext)
links = []
@@ -71,4 +75,8 @@ class DtextLink < ApplicationRecord
# because it can't index values that take up more than 1/3 of an 8kb page.
self.link_target = self.link_target.truncate(2048, omission: "")
end
def self.available_includes
[:model]
end
end

View File

@@ -168,4 +168,8 @@ class FavoriteGroup < ApplicationRecord
def viewable_by?(user)
creator_id == user.id || is_public
end
def self.available_includes
[:creator]
end
end

View File

@@ -223,4 +223,10 @@ class ForumPost < ApplicationRecord
def dtext_shortlink
"forum ##{id}"
end
def self.available_includes
includes_array = [:creator, :updater, :topic, :dtext_links, :votes, :tag_alias, :tag_implication, :bulk_update_request]
includes_array << :moderation_reports if CurrentUser.is_moderator?
includes_array
end
end

View File

@@ -53,4 +53,8 @@ class ForumPostVote < ApplicationRecord
raise
end
end
def self.available_includes
[:creator]
end
end

View File

@@ -177,4 +177,10 @@ class ForumTopic < ApplicationRecord
def update_orignal_post
original_post&.update_columns(:updater_id => updater.id, :updated_at => Time.now)
end
def self.available_includes
includes_array = [:creator, :updater, :original_post]
includes_array << :moderation_reports if CurrentUser.is_moderator?
includes_array
end
end

View File

@@ -49,4 +49,8 @@ class IpAddress < ApplicationRecord
def html_data_attributes
super & attributes.keys.map(&:to_sym)
end
def self.available_includes
[:user, :model]
end
end

View File

@@ -42,4 +42,8 @@ class IpBan < ApplicationRecord
str += "/" + ip_addr.prefix.to_s if has_subnet?
str
end
def self.available_includes
[:creator]
end
end

View File

@@ -83,4 +83,8 @@ class ModAction < ApplicationRecord
def initialize_creator
self.creator_id = CurrentUser.id
end
def self.available_includes
[:creator]
end
end

View File

@@ -19,6 +19,10 @@ class ModerationReport < ApplicationRecord
!Rails.env.production?
end
def self.model_types
%w[User Dmail Comment ForumPost]
end
def forum_topic_title
"Reports requiring moderation"
end
@@ -83,4 +87,8 @@ class ModerationReport < ApplicationRecord
q.apply_default_order(params)
end
def self.available_includes
[:creator, :model]
end
end

View File

@@ -158,4 +158,8 @@ class Note < ApplicationRecord
end
end
end
def self.available_includes
[:creator, :post]
end
end

View File

@@ -44,4 +44,8 @@ class NoteVersion < ApplicationRecord
def was_undeleted
is_active && !previous.is_active
end
def self.available_includes
[:updater, :note, :post]
end
end

View File

@@ -312,4 +312,8 @@ class Pool < ApplicationRecord
errors[:base] << "You cannot removes posts from pools within the first week of sign up"
end
end
def self.available_includes
[:creator]
end
end

View File

@@ -148,4 +148,8 @@ class PoolArchive < ApplicationRecord
def pretty_name
name.tr("_", " ")
end
def self.available_includes
[:updater, :pool]
end
end

View File

@@ -1787,4 +1787,11 @@ class Post < ApplicationRecord
save
end
def self.available_includes
includes_array = [:uploader, :updater, :approver, :parent, :upload, :artist_commentary, :flags, :appeals, :notes, :comments, :children, :approvals, :replacements]
includes_array << :moderation_reports if CurrentUser.is_moderator?
includes_array << :disapprovals if CurrentUser.user.is_approver?
includes_array
end
end

View File

@@ -62,4 +62,8 @@ class PostAppeal < ApplicationRecord
def appeal_count_for_creator
creator.post_appeals.recent.count
end
def self.available_includes
[:creator, :post]
end
end

View File

@@ -40,4 +40,8 @@ class PostApproval < ApplicationRecord
q = q.search_attributes(params, :user, :post)
q.apply_default_order(params)
end
def self.available_includes
[:user, :post]
end
end

View File

@@ -274,5 +274,9 @@ class PostArchive < ApplicationRecord
super + [:obsolete_added_tags, :obsolete_removed_tags, :unchanged_tags, :updater_name]
end
def self.available_includes
[:updater, :post]
end
memoize :previous, :tag_array, :changes, :added_tags_with_fields, :removed_tags_with_fields, :obsolete_removed_tags, :obsolete_added_tags, :unchanged_tags
end

View File

@@ -67,4 +67,8 @@ class PostDisapproval < ApplicationRecord
end
end
end
def self.available_includes
[:user, :post]
end
end

View File

@@ -161,4 +161,10 @@ class PostFlag < ApplicationRecord
def not_uploaded_by?(userid)
uploader_id != userid
end
def self.available_includes
includes_array = [:post]
includes_array << :creator if CurrentUser.user.is_moderator?
includes_array
end
end

View File

@@ -33,4 +33,8 @@ class PostReplacement < ApplicationRecord
tags = tags.map { |tag| "-#{tag}" }
tags.join(" ")
end
def self.available_includes
[:creator, :post]
end
end

View File

@@ -68,4 +68,8 @@ class PostVote < ApplicationRecord
1
end
end
def self.available_includes
[:user, :post]
end
end

View File

@@ -171,4 +171,8 @@ class SavedSearch < ApplicationRecord
def disable_labels=(value)
CurrentUser.update(disable_categorized_saved_searches: true) if value.to_s.truthy?
end
def self.available_includes
[:user]
end
end

View File

@@ -918,6 +918,10 @@ class Tag < ApplicationRecord
Post.tag_match(name)
end
def self.available_includes
[:wiki_page, :artist, :antecedent_alias, :consequent_aliases, :antecedent_implications, :consequent_implications]
end
include ApiMethods
include CountMethods
include CategoryMethods

View File

@@ -219,6 +219,10 @@ class TagRelationship < ApplicationRecord
)
end
def self.available_includes
[:creator, :approver, :forum_post, :forum_topic, :antecedent_tag, :consequent_tag, :antecedent_wiki, :consequent_wiki]
end
extend SearchMethods
include MessageMethods
end

View File

@@ -247,4 +247,8 @@ class Upload < ApplicationRecord
def upload_as_pending?
as_pending.to_s.truthy?
end
def self.available_includes
[:uploader, :post]
end
end

View File

@@ -754,4 +754,8 @@ class User < ApplicationRecord
def dtext_shortlink(**options)
"<@#{name}>"
end
def self.available_includes
[:inviter]
end
end

View File

@@ -85,4 +85,8 @@ class UserFeedback < ApplicationRecord
def editable_by?(editor)
(editor.is_moderator? && editor != user) || (creator == editor && !is_deleted?)
end
def self.available_includes
[:creator, :user]
end
end

View File

@@ -250,4 +250,8 @@ class WikiPage < ApplicationRecord
title
end
end
def self.available_includes
[:tag, :artist, :dtext_links]
end
end

View File

@@ -54,4 +54,8 @@ class WikiPageVersion < ApplicationRecord
def category_name
Tag.category_for(title)
end
def self.available_includes
[:updater, :wiki_page, :artist]
end
end

View File

@@ -7,7 +7,7 @@
<%= f.submit "Search" %>
<% end %>
<%= table_for @favorite_groups.includes(:creator), width: "100%" do |t| %>
<%= table_for @favorite_groups, width: "100%" do |t| %>
<% t.column "Name", {width: "60%"} do |favgroup| %>
<%= link_to favgroup.pretty_name, favorite_group_path(favgroup) %>
<% if favgroup.post_count > CurrentUser.user.per_page %>