Fix various rubocop warnings.

This commit is contained in:
evazion
2021-09-27 00:44:41 -05:00
parent a2a4ab887d
commit 79fdfa86ae
39 changed files with 149 additions and 154 deletions

View File

@@ -83,7 +83,7 @@ class PostsController < ApplicationController
@error_message = @post.errors.full_messages.join("; ") @error_message = @post.errors.full_messages.join("; ")
render :json => {:success => false, :reason => @error_message}.to_json, :status => 400 render :json => {:success => false, :reason => @error_message}.to_json, :status => 400
else else
head :no_content head 204
end end
end end

View File

@@ -29,9 +29,9 @@ module ApplicationHelper
return type == "previous" ? "New" : "" return type == "previous" ? "New" : ""
end end
changed_fields = record.class.status_fields.select do |field, status| changed_fields = record.class.status_fields.select do |field, _status|
(record.has_attribute?(field) && record[field] != other[field]) || (record.has_attribute?(field) && record[field] != other[field]) ||
(!record.has_attribute?(field) && record.send(field, type)) (!record.has_attribute?(field) && record.send(field, type))
end end
statuses = changed_fields.map { |field, status| status } statuses = changed_fields.map { |field, status| status }
@@ -52,7 +52,7 @@ module ApplicationHelper
html = [] html = []
%w[previous subsequent current].each do |type| %w[previous subsequent current].each do |type|
if type == params[:type] if type == params[:type]
html << %(<span>#{type}</span>) html << %{<span>#{type}</span>}
else else
html << tag.li(link_to(type, params.except(:controller, :action).merge(type: type).permit!)) html << tag.li(link_to(type, params.except(:controller, :action).merge(type: type).permit!))
end end
@@ -106,7 +106,7 @@ module ApplicationHelper
if number >= 10_000 if number >= 10_000
"#{number / 1_000}k" "#{number / 1_000}k"
elsif number >= 1_000 elsif number >= 1_000
"%.1fk" % (number / 1_000.0) format("%.1fk", number / 1_000.0)
else else
number.to_s number.to_s
end end
@@ -142,11 +142,11 @@ module ApplicationHelper
end end
def external_link_to(url, text = url, truncate: nil, strip: false, **link_options) def external_link_to(url, text = url, truncate: nil, strip: false, **link_options)
text = text.gsub(%r!\Ahttps?://!i, "") if strip == :scheme text = text.gsub(%r{\Ahttps?://}i, "") if strip == :scheme
text = text.gsub(%r!\Ahttps?://(?:www\.)?!i, "") if strip == :subdomain text = text.gsub(%r{\Ahttps?://(?:www\.)?}i, "") if strip == :subdomain
text = text.truncate(truncate) if truncate text = text.truncate(truncate) if truncate
if url =~ %r!\Ahttps?://!i if url =~ %r{\Ahttps?://}i
link_to text, url, rel: "external noreferrer nofollow", **link_options link_to text, url, rel: "external noreferrer nofollow", **link_options
else else
url url
@@ -369,37 +369,37 @@ module ApplicationHelper
def nav_link_match(controller, url) def nav_link_match(controller, url)
url =~ case controller url =~ case controller
when "sessions", "users", "admin/users" when "sessions", "users", "admin/users"
/^\/(session|users)/ %r{^/(session|users)}
when "comments" when "comments"
/^\/comments/ %r{^/comments}
when "notes", "note_versions" when "notes", "note_versions"
/^\/notes/ %r{^/notes}
when "posts", "uploads", "post_versions", "explore/posts", "moderator/post/dashboards", "favorites" when "posts", "uploads", "post_versions", "explore/posts", "moderator/post/dashboards", "favorites"
/^\/post/ %r{^/post}
when "artists", "artist_versions" when "artists", "artist_versions"
/^\/artist/ %r{^/artist}
when "tags", "tag_aliases", "tag_implications" when "tags", "tag_aliases", "tag_implications"
/^\/tags/ %r{^/tags}
when "pools", "pool_versions" when "pools", "pool_versions"
/^\/pools/ %r{^/pools}
when "moderator/dashboards" when "moderator/dashboards"
/^\/moderator/ %r{^/moderator}
when "wiki_pages", "wiki_page_versions" when "wiki_pages", "wiki_page_versions"
/^\/wiki_pages/ %r{^/wiki_pages}
when "forum_topics", "forum_posts" when "forum_topics", "forum_posts"
/^\/forum_topics/ %r{^/forum_topics}
else else
/^\/static/ %r{^/static}
end end
end end
end end

View File

@@ -43,7 +43,7 @@ module ArtistVersionsHelper
else else
name_diff = diff_name_html(other.name, artist_version.name) name_diff = diff_name_html(other.name, artist_version.name)
end end
%(<br><br><b>Rename:</b><br>&ensp;#{name_diff}</p>).html_safe %{<br><br><b>Rename:</b><br>&ensp;#{name_diff}</p>}.html_safe
else else
"" ""
end end
@@ -58,7 +58,7 @@ module ArtistVersionsHelper
else else
group_name_diff = diff_name_html(other_group_name, artist_version.group_name) group_name_diff = diff_name_html(other_group_name, artist_version.group_name)
end end
%(<b>Group:</b><br>&ensp;#{group_name_diff}<br><br>).html_safe %{<b>Group:</b><br>&ensp;#{group_name_diff}<br><br>}.html_safe
else else
"" ""
end end

View File

@@ -8,7 +8,7 @@ module ForumTopicsHelper
end end
def new_forum_topic?(topic, read_forum_topics) def new_forum_topic?(topic, read_forum_topics)
!read_forum_topics.map(&:id).include?(topic.id) read_forum_topics.map(&:id).exclude?(topic.id)
end end
def forum_topic_status(topic) def forum_topic_status(topic)
@@ -24,9 +24,10 @@ module ForumTopicsHelper
end end
def forum_post_vote_icon(vote) def forum_post_vote_icon(vote)
if vote.score == 1 case vote.score
when 1
upvote_icon upvote_icon
elsif vote.score == -1 when -1
downvote_icon downvote_icon
else else
meh_icon meh_icon

View File

@@ -25,12 +25,12 @@ module PostVersionsHelper
html = '<span class="diff-list">' html = '<span class="diff-list">'
added_tags.each do |tag| added_tags.each do |tag|
obsolete_class = (obsolete_added_tags.include?(tag) ? "diff-obsolete" : ""); obsolete_class = (obsolete_added_tags.include?(tag) ? "diff-obsolete" : "")
html << %(<ins class="#{obsolete_class}">#{link_to(wordbreakify(tag), posts_path(:tags => tag))}</ins> ) html << %{<ins class="#{obsolete_class}">#{link_to(wordbreakify(tag), posts_path(:tags => tag))}</ins> }
end end
removed_tags.each do |tag| removed_tags.each do |tag|
obsolete_class = (obsolete_removed_tags.include?(tag) ? "diff-obsolete" : ""); obsolete_class = (obsolete_removed_tags.include?(tag) ? "diff-obsolete" : "")
html << %(<del class="#{obsolete_class}">#{link_to(wordbreakify(tag), posts_path(:tags => tag))}</del> ) html << %{<del class="#{obsolete_class}">#{link_to(wordbreakify(tag), posts_path(:tags => tag))}</del> }
end end
html << "</span>" html << "</span>"
@@ -42,7 +42,7 @@ module PostVersionsHelper
prefix = (field == :parent_id ? "parent" : field.to_s) prefix = (field == :parent_id ? "parent" : field.to_s)
search = "#{prefix}:#{value}" search = "#{prefix}:#{value}"
display = (field == :rating ? post_version.pretty_rating : value) display = (field == :rating ? post_version.pretty_rating : value)
%(<b>#{field.to_s.titleize}:</b> #{link_to(display, posts_path(:tags => search))}).html_safe %{<b>#{field.to_s.titleize}:</b> #{link_to(display, posts_path(:tags => search))}}.html_safe
end end
def post_version_value(value) def post_version_value(value)

View File

@@ -35,7 +35,7 @@ module PostsHelper
def post_source_tag(source, normalized_source = source) def post_source_tag(source, normalized_source = source)
# Only allow http:// and https:// links. Disallow javascript: links. # Only allow http:// and https:// links. Disallow javascript: links.
if source =~ %r!\Ahttps?://!i if source =~ %r{\Ahttps?://}i
external_link_to(normalized_source, strip: :subdomain) + "&nbsp;".html_safe + link_to("»", source, rel: "external noreferrer nofollow") external_link_to(normalized_source, strip: :subdomain) + "&nbsp;".html_safe + link_to("»", source, rel: "external noreferrer nofollow")
else else
source source

View File

@@ -17,11 +17,11 @@ module SeoHelper
json_ld_tag({ json_ld_tag({
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": "VideoObject", "@type": "VideoObject",
"name": page_title, name: page_title,
"description": meta_description, description: meta_description,
"uploadDate": post.created_at.iso8601, uploadDate: post.created_at.iso8601,
"thumbnailUrl": post.preview_file_url, thumbnailUrl: post.preview_file_url,
"contentUrl": post.file_url, contentUrl: post.file_url,
}) })
end end
@@ -30,7 +30,7 @@ module SeoHelper
Danbooru.config.twitter_url, Danbooru.config.twitter_url,
Danbooru.config.discord_server_url, Danbooru.config.discord_server_url,
Danbooru.config.source_code_url, Danbooru.config.source_code_url,
"https://en.wikipedia.org/wiki/Danbooru" "https://en.wikipedia.org/wiki/Danbooru",
].compact ].compact
json_ld_tag({ json_ld_tag({
@@ -41,18 +41,18 @@ module SeoHelper
url: root_url(host: Danbooru.config.hostname), url: root_url(host: Danbooru.config.hostname),
name: Danbooru.config.app_name, name: Danbooru.config.app_name,
logo: "#{root_url(host: Danbooru.config.hostname)}images/danbooru-logo-500x500.png", logo: "#{root_url(host: Danbooru.config.hostname)}images/danbooru-logo-500x500.png",
sameAs: urls sameAs: urls,
}, },
{ {
"@type": "WebSite", "@type": "WebSite",
"@id": root_url(anchor: "website", host: Danbooru.config.hostname), "@id": root_url(anchor: "website", host: Danbooru.config.hostname),
"url": root_url(host: Danbooru.config.hostname), url: root_url(host: Danbooru.config.hostname),
"name": Danbooru.config.app_name, name: Danbooru.config.app_name,
"description": site_description, description: site_description,
"potentialAction": [{ potentialAction: [{
"@type": "SearchAction", "@type": "SearchAction",
"target": "#{posts_url(host: Danbooru.config.hostname)}?tags={search_term_string}", target: "#{posts_url(host: Danbooru.config.hostname)}?tags={search_term_string}",
"query-input": "required name=search_term_string" "query-input": "required name=search_term_string",
}] }]
} }
] ]

View File

@@ -23,7 +23,7 @@ module WikiPageVersionsHelper
else else
name_diff = diff_name_html(other.title, wiki_page_version.title) name_diff = diff_name_html(other.title, wiki_page_version.title)
end end
%((<b>Rename:</b>&ensp;#{name_diff})).html_safe %{(<b>Rename:</b>&ensp;#{name_diff})}.html_safe
else else
"" ""
end end

View File

@@ -23,8 +23,7 @@ class ApiKey < ApplicationRecord
def self.search(params) def self.search(params)
q = search_attributes(params, :id, :created_at, :updated_at, :key, :user) q = search_attributes(params, :id, :created_at, :updated_at, :key, :user)
q = q.apply_default_order(params) q.apply_default_order(params)
q
end end
concerning :PermissionMethods do concerning :PermissionMethods do
@@ -59,9 +58,11 @@ class ApiKey < ApplicationRecord
end end
def permissions_list def permissions_list
Rails.application.routes.routes.select do |route| routes = Rails.application.routes.routes.select do |route|
route.defaults[:controller].present? && !route.internal route.defaults[:controller].present? && !route.internal
end.map do |route| end
routes.map do |route|
"#{route.defaults[:controller]}:#{route.defaults[:action]}" "#{route.defaults[:controller]}:#{route.defaults[:action]}"
end.uniq.sort end.uniq.sort
end end

View File

@@ -26,7 +26,7 @@ class ApplicationRecord < ActiveRecord::Base
concerning :PrivilegeMethods do concerning :PrivilegeMethods do
class_methods do class_methods do
def visible(user) def visible(_user)
all all
end end
@@ -47,14 +47,14 @@ class ApplicationRecord < ActiveRecord::Base
end end
def multiple_includes def multiple_includes
reflections.reject { |k,v| v.macro != :has_many }.keys.map(&:to_sym) reflections.select { |_, v| v.macro == :has_many }.keys.map(&:to_sym)
end end
def associated_models(name) def associated_models(name)
if reflections[name].options[:polymorphic] if reflections[name].options[:polymorphic]
associated_models = reflections[name].active_record.try(:model_types) || [] reflections[name].active_record.try(:model_types) || []
else else
associated_models = [reflections[name].class_name] [reflections[name].class_name]
end end
end end
end end
@@ -77,7 +77,7 @@ class ApplicationRecord < ActiveRecord::Base
def serializable_hash(options = {}) def serializable_hash(options = {})
options ||= {} options ||= {}
if options[:only] && options[:only].is_a?(String) if options[:only].is_a?(String)
options.delete(:methods) options.delete(:methods)
options.delete(:include) options.delete(:include)
options.merge!(ParameterBuilder.serial_parameters(options[:only], self)) options.merge!(ParameterBuilder.serial_parameters(options[:only], self))
@@ -116,20 +116,20 @@ class ApplicationRecord < ActiveRecord::Base
concerning :ActiveRecordExtensions do concerning :ActiveRecordExtensions do
class_methods do class_methods do
def without_timeout def without_timeout
connection.execute("SET STATEMENT_TIMEOUT = 0") unless Rails.env == "test" connection.execute("SET STATEMENT_TIMEOUT = 0") unless Rails.env.test?
yield yield
ensure ensure
connection.execute("SET STATEMENT_TIMEOUT = #{CurrentUser.user.try(:statement_timeout) || 3_000}") unless Rails.env == "test" connection.execute("SET STATEMENT_TIMEOUT = #{CurrentUser.user.try(:statement_timeout) || 3_000}") unless Rails.env.test?
end end
def with_timeout(n, default_value = nil, new_relic_params = {}) def with_timeout(n, default_value = nil, new_relic_params = {})
connection.execute("SET STATEMENT_TIMEOUT = #{n}") unless Rails.env == "test" connection.execute("SET STATEMENT_TIMEOUT = #{n}") unless Rails.env.test?
yield yield
rescue ::ActiveRecord::StatementInvalid => x rescue ::ActiveRecord::StatementInvalid => e
DanbooruLogger.log(x, expected: false, **new_relic_params) DanbooruLogger.log(e, expected: false, **new_relic_params)
return default_value default_value
ensure ensure
connection.execute("SET STATEMENT_TIMEOUT = #{CurrentUser.user.try(:statement_timeout) || 3_000}") unless Rails.env == "test" connection.execute("SET STATEMENT_TIMEOUT = #{CurrentUser.user.try(:statement_timeout) || 3_000}") unless Rails.env.test?
end end
def update!(*args) def update!(*args)
@@ -161,7 +161,7 @@ class ApplicationRecord < ActiveRecord::Base
end end
concerning :DtextMethods do concerning :DtextMethods do
def dtext_shortlink(**options) def dtext_shortlink(**_options)
"#{self.class.name.underscore.tr("_", " ")} ##{id}" "#{self.class.name.underscore.tr("_", " ")} ##{id}"
end end
end end

View File

@@ -61,7 +61,7 @@ class Artist < ApplicationRecord
concerning :NameMethods do concerning :NameMethods do
class_methods do class_methods do
def normalize_name(name) def normalize_name(name)
name.to_s.mb_chars.downcase.strip.gsub(/ /, '_').to_s name.to_s.mb_chars.downcase.strip.gsub(/ /, "_").to_s
end end
def normalize_other_names(other_names) def normalize_other_names(other_names)
@@ -216,7 +216,7 @@ class Artist < ApplicationRecord
end end
def any_name_matches(query) def any_name_matches(query)
if query =~ %r!\A/(.*)/\z! if query =~ %r{\A/(.*)/\z}
where_regex(:name, $1).or(any_other_name_matches($1)).or(where_regex(:group_name, $1)) where_regex(:name, $1).or(any_other_name_matches($1)).or(where_regex(:group_name, $1))
else else
normalized_name = normalize_name(query) normalized_name = normalize_name(query)
@@ -228,11 +228,11 @@ class Artist < ApplicationRecord
def url_matches(query) def url_matches(query)
query = query.strip query = query.strip
if query =~ %r!\A/(.*)/\z! if query =~ %r{\A/(.*)/\z}
where(id: ArtistUrl.where_regex(:url, $1).select(:artist_id)) where(id: ArtistUrl.where_regex(:url, $1).select(:artist_id))
elsif query.include?("*") elsif query.include?("*")
where(id: ArtistUrl.where_like(:url, query).select(:artist_id)) where(id: ArtistUrl.where_like(:url, query).select(:artist_id))
elsif query =~ %r!\Ahttps?://!i elsif query =~ %r{\Ahttps?://}i
ArtistFinder.find_artists(query) ArtistFinder.find_artists(query)
else else
where(id: ArtistUrl.where_like(:url, "*#{query}*").select(:artist_id)) where(id: ArtistUrl.where_like(:url, "*#{query}*").select(:artist_id))
@@ -242,7 +242,7 @@ class Artist < ApplicationRecord
def any_name_or_url_matches(query) def any_name_or_url_matches(query)
query = query.strip query = query.strip
if query =~ %r!\Ahttps?://!i if query =~ %r{\Ahttps?://}i
url_matches(query) url_matches(query)
else else
any_name_matches(query) any_name_matches(query)

View File

@@ -1,10 +1,15 @@
class ArtistCommentary < ApplicationRecord class ArtistCommentary < ApplicationRecord
class RevertError < StandardError; end class RevertError < StandardError; end
attr_accessor :remove_commentary_tag, :remove_commentary_request_tag, :remove_commentary_check_tag, :remove_partial_commentary_tag attr_accessor(
attr_accessor :add_commentary_tag, :add_commentary_request_tag, :add_commentary_check_tag, :add_partial_commentary_tag :remove_commentary_tag, :remove_commentary_request_tag,
:remove_commentary_check_tag, :remove_partial_commentary_tag,
:add_commentary_tag, :add_commentary_request_tag, :add_commentary_check_tag,
:add_partial_commentary_tag
)
before_validation :trim_whitespace before_validation :trim_whitespace
validates_uniqueness_of :post_id validates :post_id, uniqueness: true
belongs_to :post belongs_to :post
has_many :versions, -> {order("artist_commentary_versions.id ASC")}, :class_name => "ArtistCommentaryVersion", :dependent => :destroy, :foreign_key => :post_id, :primary_key => :post_id has_many :versions, -> {order("artist_commentary_versions.id ASC")}, :class_name => "ArtistCommentaryVersion", :dependent => :destroy, :foreign_key => :post_id, :primary_key => :post_id
has_one :previous_version, -> {order(id: :desc)}, :class_name => "ArtistCommentaryVersion", :foreign_key => :post_id, :primary_key => :post_id has_one :previous_version, -> {order(id: :desc)}, :class_name => "ArtistCommentaryVersion", :foreign_key => :post_id, :primary_key => :post_id
@@ -126,7 +131,7 @@ class ArtistCommentary < ApplicationRecord
def revert_to(version) def revert_to(version)
if post_id != version.post_id if post_id != version.post_id
raise RevertError.new("You cannot revert to a previous artist commentary of another post.") raise RevertError, "You cannot revert to a previous artist commentary of another post."
end end
self.original_description = version.original_description self.original_description = version.original_description

View File

@@ -22,23 +22,17 @@ class ArtistCommentaryVersion < ApplicationRecord
end end
def previous def previous
@previous ||= begin @previous ||= ArtistCommentaryVersion.where("post_id = ? and updated_at < ?", post_id, updated_at).order("updated_at desc").limit(1).to_a
ArtistCommentaryVersion.where("post_id = ? and updated_at < ?", post_id, updated_at).order("updated_at desc").limit(1).to_a
end
@previous.first @previous.first
end end
def subsequent def subsequent
@subsequent ||= begin @subsequent ||= ArtistCommentaryVersion.where("post_id = ? and updated_at > ?", post_id, updated_at).order("updated_at asc").limit(1).to_a
ArtistCommentaryVersion.where("post_id = ? and updated_at > ?", post_id, updated_at).order("updated_at asc").limit(1).to_a
end
@subsequent.first @subsequent.first
end end
def current def current
@current ||= begin @current ||= ArtistCommentaryVersion.where(post_id: post_id).order("updated_at desc").limit(1).to_a
ArtistCommentaryVersion.where("post_id = ?", post_id).order("updated_at desc").limit(1).to_a
end
@current.first @current.first
end end

View File

@@ -20,22 +20,22 @@ class ArtistUrl < ApplicationRecord
if url.nil? if url.nil?
nil nil
else else
url = url.sub(%r!^https://!, "http://") url = url.sub(%r{^https://}, "http://")
url = url.sub(%r!^http://blog-imgs-\d+\.fc2!, "http://blog.fc2") url = url.sub(%r{^http://blog-imgs-\d+\.fc2}, "http://blog.fc2")
url = url.sub(%r!^http://blog-imgs-\d+-\w+\.fc2!, "http://blog.fc2") url = url.sub(%r{^http://blog-imgs-\d+-\w+\.fc2}, "http://blog.fc2")
url = url.sub(%r!^http://blog\d*\.fc2\.com/(?:\w/){,3}(\w+)!, "http://\\1.blog.fc2.com") url = url.sub(%r{^http://blog\d*\.fc2\.com/(?:\w/){,3}(\w+)}, "http://\\1.blog.fc2.com")
url = url.sub(%r!^http://pictures.hentai-foundry.com//!, "http://pictures.hentai-foundry.com/") url = url.sub(%r{^http://pictures.hentai-foundry.com//}, "http://pictures.hentai-foundry.com/")
# the strategy won't always work for twitter because it looks for a status # the strategy won't always work for twitter because it looks for a status
url = url.downcase if url =~ %r!^https?://(?:mobile\.)?twitter\.com! url = url.downcase if url =~ %r{^https?://(?:mobile\.)?twitter\.com}
url = Sources::Strategies.find(url).normalize_for_artist_finder url = Sources::Strategies.find(url).normalize_for_artist_finder
# XXX the Pixiv strategy should implement normalize_for_artist_finder and return the correct url directly. # XXX the Pixiv strategy should implement normalize_for_artist_finder and return the correct url directly.
url = url.sub(%r!\Ahttps?://www\.pixiv\.net/(?:en/)?users/(\d+)\z!i, 'https://www.pixiv.net/member.php?id=\1') url = url.sub(%r{\Ahttps?://www\.pixiv\.net/(?:en/)?users/(\d+)\z}i, 'https://www.pixiv.net/member.php?id=\1')
url = url.gsub(/\/+\Z/, "") url = url.gsub(%r{/+\Z}, "")
url = url.gsub(%r!^https://!, "http://") url = url.gsub(%r{^https://}, "http://")
url + "/" url + "/"
end end
end end
@@ -60,7 +60,7 @@ class ArtistUrl < ApplicationRecord
def self.url_attribute_matches(attr, url) def self.url_attribute_matches(attr, url)
if url.blank? if url.blank?
all all
elsif url =~ %r!\A/(.*)/\z! elsif url =~ %r{\A/(.*)/\z}
where_regex(attr, $1) where_regex(attr, $1)
elsif url.include?("*") elsif url.include?("*")
where_ilike(attr, url) where_ilike(attr, url)
@@ -83,21 +83,21 @@ class ArtistUrl < ApplicationRecord
# usually because it's redundant with the primary profile URL. # usually because it's redundant with the primary profile URL.
def secondary_url? def secondary_url?
case url case url
when %r!pixiv\.net/stacc!i when %r{pixiv\.net/stacc}i
true true
when %r!pixiv\.net/fanbox!i when %r{pixiv\.net/fanbox}i
true true
when %r!twitter\.com/intent!i when %r{twitter\.com/intent}i
true true
when %r!lohas\.nicoseiga\.jp!i when %r{lohas\.nicoseiga\.jp}i
true true
when %r!(?:www|com|dic)\.nicovideo\.jp!i when %r{(?:www|com|dic)\.nicovideo\.jp}i
true true
when %r!pawoo\.net/web/accounts!i when %r{pawoo\.net/web/accounts}i
true true
when %r!www\.artstation\.com!i when %r{www\.artstation\.com}i
true true
when %r!blogimg\.jp!i, %r!image\.blog\.livedoor\.jp!i when %r{blogimg\.jp}i, %r{image\.blog\.livedoor\.jp}i
true true
else else
false false
@@ -145,15 +145,15 @@ class ArtistUrl < ApplicationRecord
end end
def validate_hostname(uri) def validate_hostname(uri)
errors.add(:url, "'#{uri}' has a hostname '#{uri.host}' that does not contain a dot") unless uri.host&.include?('.') errors.add(:url, "'#{uri}' has a hostname '#{uri.host}' that does not contain a dot") unless uri.host&.include?(".")
end end
def validate_url_format def validate_url_format
uri = Addressable::URI.parse(url) uri = Addressable::URI.parse(url)
validate_scheme(uri) validate_scheme(uri)
validate_hostname(uri) validate_hostname(uri)
rescue Addressable::URI::InvalidURIError => error rescue Addressable::URI::InvalidURIError => e
errors.add(:url, "'#{uri}' is malformed: #{error}") errors.add(:url, "'#{uri}' is malformed: #{e}")
end end
def self.available_includes def self.available_includes

View File

@@ -42,9 +42,7 @@ class ArtistVersion < ApplicationRecord
end end
def current def current
@previous ||= begin @previous ||= ArtistVersion.where(artist_id: artist_id).order("created_at desc").limit(1).to_a
ArtistVersion.where(artist_id: artist_id).order("created_at desc").limit(1).to_a
end
@previous.first @previous.first
end end

View File

@@ -9,8 +9,8 @@ class Dmail < ApplicationRecord
has_many :moderation_reports, as: :model, dependent: :destroy has_many :moderation_reports, as: :model, dependent: :destroy
before_create :autoreport_spam before_create :autoreport_spam
after_save :update_unread_dmail_count
after_destroy :update_unread_dmail_count after_destroy :update_unread_dmail_count
after_save :update_unread_dmail_count
after_commit :send_email, on: :create after_commit :send_email, on: :create
deletable deletable

View File

@@ -47,7 +47,7 @@ class DtextLink < ApplicationRecord
# postgres will raise an error if the link is more than 2712 bytes long # postgres will raise an error if the link is more than 2712 bytes long
# because it can't index values that take up more than 1/3 of an 8kb page. # 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: "") self.link_target = link_target.truncate(2048, omission: "")
end end
def self.attribute_restriction(*) def self.attribute_restriction(*)

View File

@@ -48,9 +48,8 @@ class EmailAddress < ApplicationRecord
q = search_attributes(params, :id, :created_at, :updated_at, :user, :address, :normalized_address, :is_verified, :is_deliverable) q = search_attributes(params, :id, :created_at, :updated_at, :user, :address, :normalized_address, :is_verified, :is_deliverable)
q = q.restricted(params[:is_restricted]) q = q.restricted(params[:is_restricted])
q = q.apply_default_order(params)
q q.apply_default_order(params)
end end
def validate_deliverable def validate_deliverable

View File

@@ -77,7 +77,7 @@ class FavoriteGroup < ApplicationRecord
errors.add(:base, "Cannot add invalid post(s) to favgroup: #{nonexisting_post_ids.to_sentence}") errors.add(:base, "Cannot add invalid post(s) to favgroup: #{nonexisting_post_ids.to_sentence}")
end end
duplicate_post_ids = post_ids.group_by(&:itself).transform_values(&:size).select { |id, count| count > 1 }.keys duplicate_post_ids = post_ids.group_by(&:itself).transform_values(&:size).select { |_id, count| count > 1 }.keys
if duplicate_post_ids.present? if duplicate_post_ids.present?
errors.add(:base, "Favgroup already contains post #{duplicate_post_ids.to_sentence}") errors.add(:base, "Favgroup already contains post #{duplicate_post_ids.to_sentence}")
end end
@@ -117,7 +117,7 @@ class FavoriteGroup < ApplicationRecord
def posts def posts
favgroup_posts = FavoriteGroup.where(id: id).joins("CROSS JOIN unnest(favorite_groups.post_ids) WITH ORDINALITY AS row(post_id, favgroup_index)").select(:post_id, :favgroup_index) favgroup_posts = FavoriteGroup.where(id: id).joins("CROSS JOIN unnest(favorite_groups.post_ids) WITH ORDINALITY AS row(post_id, favgroup_index)").select(:post_id, :favgroup_index)
posts = Post.joins("JOIN (#{favgroup_posts.to_sql}) favgroup_posts ON favgroup_posts.post_id = posts.id").order("favgroup_posts.favgroup_index ASC") Post.joins("JOIN (#{favgroup_posts.to_sql}) favgroup_posts ON favgroup_posts.post_id = posts.id").order("favgroup_posts.favgroup_index ASC")
end end
def add!(post) def add!(post)

View File

@@ -179,7 +179,7 @@ class ForumPost < ApplicationRecord
end end
end end
def dtext_shortlink(**options) def dtext_shortlink(**_options)
"forum ##{id}" "forum ##{id}"
end end

View File

@@ -94,11 +94,12 @@ class ForumTopic < ApplicationRecord
q = q.public_only q = q.public_only
end end
if params[:status] == "pending" case params[:status]
when "pending"
q = q.pending q = q.pending
elsif params[:status] == "approved" when "approved"
q = q.approved q = q.approved
elsif params[:status] == "rejected" when "rejected"
q = q.rejected q = q.rejected
end end

View File

@@ -20,7 +20,7 @@ class IpAddress < ApplicationRecord
ipv4_masklen ||= 32 ipv4_masklen ||= 32
ipv6_masklen ||= 128 ipv6_masklen ||= 128
q = select(sanitize_sql([<<~SQL, ipv4_masklen, ipv6_masklen])) q = select(sanitize_sql([<<~SQL.squish, ipv4_masklen, ipv6_masklen]))
CASE CASE
WHEN family(ip_addr) = 4 WHEN family(ip_addr) = 4
THEN network(set_masklen(ip_addr, ?)) THEN network(set_masklen(ip_addr, ?))

View File

@@ -16,8 +16,7 @@ class IpGeolocation < ApplicationRecord
def self.search(params) def self.search(params)
q = search_attributes(params, :id, :created_at, :updated_at, :ip_addr, :network, :asn, :is_proxy, :latitude, :longitude, :organization, :time_zone, :continent, :country, :region, :city, :carrier) q = search_attributes(params, :id, :created_at, :updated_at, :ip_addr, :network, :asn, :is_proxy, :latitude, :longitude, :organization, :time_zone, :continent, :country, :region, :city, :carrier)
q = q.apply_default_order(params) q.apply_default_order(params)
q
end end
def self.create_or_update!(ip) def self.create_or_update!(ip)

View File

@@ -12,8 +12,7 @@ class MediaAsset < ApplicationRecord
def self.search(params) def self.search(params)
q = search_attributes(params, :id, :created_at, :updated_at, :md5, :file_ext, :file_size, :image_width, :image_height) q = search_attributes(params, :id, :created_at, :updated_at, :md5, :file_ext, :file_size, :image_width, :image_height)
q = q.apply_default_order(params) q.apply_default_order(params)
q
end end
def file=(file_or_path) def file=(file_or_path)

View File

@@ -16,8 +16,7 @@ class MediaMetadata < ApplicationRecord
def self.search(params) def self.search(params)
q = search_attributes(params, :id, :created_at, :updated_at, :media_asset, :metadata) q = search_attributes(params, :id, :created_at, :updated_at, :media_asset, :metadata)
q = q.apply_default_order(params) q.apply_default_order(params)
q
end end
def file=(file_or_path) def file=(file_or_path)

View File

@@ -41,7 +41,7 @@ class ModerationReport < ApplicationRecord
if topic.nil? if topic.nil?
CurrentUser.scoped(User.system) do CurrentUser.scoped(User.system) do
topic = ForumTopic.create!(creator: User.system, title: forum_topic_title, category_id: 0, min_level: User::Levels::MODERATOR) topic = ForumTopic.create!(creator: User.system, title: forum_topic_title, category_id: 0, min_level: User::Levels::MODERATOR)
forum_post = ForumPost.create!(creator: User.system, body: forum_topic_body, topic: topic) ForumPost.create!(creator: User.system, body: forum_topic_body, topic: topic)
end end
end end
topic topic

View File

@@ -13,7 +13,6 @@ class NewsUpdate < ApplicationRecord
def self.search(params) def self.search(params)
q = search_attributes(params, :id, :created_at, :updated_at, :message, :creator, :updater) q = search_attributes(params, :id, :created_at, :updated_at, :message, :creator, :updater)
q = q.apply_default_order(params) q.apply_default_order(params)
q
end end
end end

View File

@@ -48,7 +48,7 @@ class Note < ApplicationRecord
end end
def update_post def update_post
if self.saved_changes? if saved_changes?
if post.notes.active.exists? if post.notes.active.exists?
post.update_columns(last_noted_at: updated_at) post.update_columns(last_noted_at: updated_at)
else else

View File

@@ -178,7 +178,7 @@ class Pool < ApplicationRecord
# XXX unify with PostQueryBuilder ordpool search # XXX unify with PostQueryBuilder ordpool search
def posts def posts
pool_posts = Pool.where(id: id).joins("CROSS JOIN unnest(pools.post_ids) WITH ORDINALITY AS row(post_id, pool_index)").select(:post_id, :pool_index) pool_posts = Pool.where(id: id).joins("CROSS JOIN unnest(pools.post_ids) WITH ORDINALITY AS row(post_id, pool_index)").select(:post_id, :pool_index)
posts = Post.joins("JOIN (#{pool_posts.to_sql}) pool_posts ON pool_posts.post_id = posts.id").order("pool_posts.pool_index ASC") Post.joins("JOIN (#{pool_posts.to_sql}) pool_posts ON pool_posts.post_id = posts.id").order("pool_posts.pool_index ASC")
end end
def synchronize def synchronize

View File

@@ -78,7 +78,7 @@ class PoolVersion < ApplicationRecord
name: pool.name, name: pool.name,
is_active: pool.is_active?, is_active: pool.is_active?,
is_deleted: pool.is_deleted?, is_deleted: pool.is_deleted?,
category: pool.category category: pool.category,
} }
msg = "add pool version\n#{json.to_json}" msg = "add pool version\n#{json.to_json}"
sqs_service.send_message(msg, message_group_id: "pool:#{pool.id}") sqs_service.send_message(msg, message_group_id: "pool:#{pool.id}")

View File

@@ -444,7 +444,7 @@ class Post < ApplicationRecord
invalid_tags = tag_names.map { |name| Tag.new(name: name) }.select { |tag| tag.invalid?(:name) } invalid_tags = tag_names.map { |name| Tag.new(name: name) }.select { |tag| tag.invalid?(:name) }
invalid_tags.each do |tag| invalid_tags.each do |tag|
tag.errors.messages.each do |attribute, messages| tag.errors.messages.each do |_attribute, messages|
warnings.add(:base, "Couldn't add tag: #{messages.join(';')}") warnings.add(:base, "Couldn't add tag: #{messages.join(';')}")
end end
end end
@@ -524,7 +524,7 @@ class Post < ApplicationRecord
when /^newpool:(.+)$/i when /^newpool:(.+)$/i
pool = Pool.find_by_name($1) pool = Pool.find_by_name($1)
if pool.nil? if pool.nil?
pool = Pool.create(name: $1, description: "This pool was automatically generated") Pool.create(name: $1, description: "This pool was automatically generated")
end end
end end
end end
@@ -1073,7 +1073,7 @@ class Post < ApplicationRecord
"tags" => tag_string, "tags" => tag_string,
"height" => image_height, "height" => image_height,
"file_size" => file_size, "file_size" => file_size,
"id" => id "id" => id,
} }
if visible? if visible?
@@ -1148,7 +1148,7 @@ class Post < ApplicationRecord
def with_flag_stats def with_flag_stats
relation = left_outer_joins(:flags).group(:id).select("posts.*") relation = left_outer_joins(:flags).group(:id).select("posts.*")
relation = relation.select("COUNT(post_flags.id) AS flag_count") relation.select("COUNT(post_flags.id) AS flag_count")
relation relation
end end
@@ -1308,14 +1308,14 @@ class Post < ApplicationRecord
image_width: media_file.width, image_width: media_file.width,
image_height: media_file.height, image_height: media_file.height,
file_size: media_file.file_size, file_size: media_file.file_size,
file_ext: media_file.file_ext, file_ext: media_file.file_ext
) )
media_asset.update!( media_asset.update!(
image_width: media_file.width, image_width: media_file.width,
image_height: media_file.height, image_height: media_file.height,
file_size: media_file.file_size, file_size: media_file.file_size,
file_ext: media_file.file_ext, file_ext: media_file.file_ext
) )
purge_cached_urls! purge_cached_urls!
@@ -1328,7 +1328,7 @@ class Post < ApplicationRecord
def purge_cached_urls! def purge_cached_urls!
urls = [ urls = [
preview_file_url, crop_file_url, large_file_url, file_url, preview_file_url, crop_file_url, large_file_url, file_url,
tagged_file_url(tagged_filenames: true), tagged_large_file_url(tagged_filenames: true) tagged_file_url(tagged_filenames: true), tagged_large_file_url(tagged_filenames: true),
] ]
CloudflareService.new.purge_cache(urls) CloudflareService.new.purge_cache(urls)
@@ -1519,8 +1519,10 @@ class Post < ApplicationRecord
def self.available_includes def self.available_includes
# attributes accessible through the ?only= parameter # attributes accessible through the ?only= parameter
[:uploader, :updater, :approver, :upload, :flags, :appeals, %i[
:parent, :children, :notes, :comments, :approvals, :disapprovals, uploader updater approver upload flags appeals parent children notes
:replacements, :pixiv_ugoira_frame_data, :artist_commentary] comments approvals disapprovals replacements pixiv_ugoira_frame_data
artist_commentary
]
end end
end end

View File

@@ -11,7 +11,7 @@ class PostFlag < ApplicationRecord
validates :reason, presence: true, length: { in: 1..140 } validates :reason, presence: true, length: { in: 1..140 }
validate :validate_creator_is_not_limited, on: :create validate :validate_creator_is_not_limited, on: :create
validate :validate_post, on: :create validate :validate_post, on: :create
validates_uniqueness_of :creator_id, scope: :post_id, on: :create, unless: :is_deletion, message: "have already flagged this post" validates :creator_id, uniqueness: { scope: :post_id, on: :create, unless: :is_deletion, message: "have already flagged this post" }
before_save :update_post before_save :update_post
attr_accessor :is_deletion attr_accessor :is_deletion

View File

@@ -238,7 +238,7 @@ class PostVersion < ApplicationRecord
end end
def truncated_source def truncated_source
source.gsub(/^http:\/\//, "").sub(/\/.+/, "") source.gsub(%r{^http://}, "").sub(%r{/.+}, "")
end end
def undo! def undo!

View File

@@ -17,8 +17,7 @@ class RateLimit < ApplicationRecord
def self.search(params) def self.search(params)
q = search_attributes(params, :id, :created_at, :updated_at, :limited, :points, :action, :key) q = search_attributes(params, :id, :created_at, :updated_at, :limited, :points, :action, :key)
q = q.apply_default_order(params) q.apply_default_order(params)
q
end end
# `action` is the action being limited. Usually a controller endpoint. # `action` is the action being limited. Usually a controller endpoint.
@@ -31,7 +30,7 @@ class RateLimit < ApplicationRecord
key_params = keys.map.with_index { |key, i| [:"key#{i}", key] }.to_h key_params = keys.map.with_index { |key, i| [:"key#{i}", key] }.to_h
# (created_at, updated_at, action, keyN, points) # (created_at, updated_at, action, keyN, points)
values = keys.map.with_index { |key, i| "(:now, :now, :action, :key#{i}, :points)" } values = keys.map.with_index { |_key, i| "(:now, :now, :action, :key#{i}, :points)" }
# Do an upsert, creating a new rate limit object for each key that doesn't # Do an upsert, creating a new rate limit object for each key that doesn't
# already exist, and updating the limit for each limit that already exists. # already exist, and updating the limit for each limit that already exists.
@@ -43,7 +42,7 @@ class RateLimit < ApplicationRecord
# the point count and subtract the cost of the call. # the point count and subtract the cost of the call.
# #
# https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT # https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT
sql = <<~SQL sql = <<~SQL.squish
INSERT INTO rate_limits (created_at, updated_at, action, key, points) INSERT INTO rate_limits (created_at, updated_at, action, key, points)
VALUES #{values.join(", ")} VALUES #{values.join(", ")}
ON CONFLICT (action, key) DO UPDATE SET ON CONFLICT (action, key) DO UPDATE SET
@@ -67,10 +66,9 @@ class RateLimit < ApplicationRecord
cost: cost, cost: cost,
points: burst - cost, points: burst - cost,
minimum_points: minimum_points, minimum_points: minimum_points,
**key_params **key_params,
} }
rate_limits = RateLimit.find_by_sql([sql, sql_params]) RateLimit.find_by_sql([sql, sql_params])
rate_limits
end end
end end

View File

@@ -74,7 +74,7 @@ class Tag < ApplicationRecord
# fix tags where the post count is non-zero but the tag isn't present on any posts. # fix tags where the post count is non-zero but the tag isn't present on any posts.
def regenerate_nonexistent_post_counts! def regenerate_nonexistent_post_counts!
Tag.find_by_sql(<<~SQL) Tag.find_by_sql(<<~SQL.squish)
UPDATE tags UPDATE tags
SET post_count = 0 SET post_count = 0
WHERE WHERE
@@ -90,7 +90,7 @@ class Tag < ApplicationRecord
# fix tags where the stored post count doesn't match the true post count. # fix tags where the stored post count doesn't match the true post count.
def regenerate_incorrect_post_counts! def regenerate_incorrect_post_counts!
Tag.find_by_sql(<<~SQL) Tag.find_by_sql(<<~SQL.squish)
UPDATE tags UPDATE tags
SET post_count = true_count SET post_count = true_count
FROM ( FROM (
@@ -223,7 +223,7 @@ class Tag < ApplicationRecord
module SearchMethods module SearchMethods
def autocorrect_matches(name) def autocorrect_matches(name)
tags = fuzzy_name_matches(name).order_similarity(name) fuzzy_name_matches(name).order_similarity(name)
end end
# ref: https://www.postgresql.org/docs/current/static/pgtrgm.html#idm46428634524336 # ref: https://www.postgresql.org/docs/current/static/pgtrgm.html#idm46428634524336

View File

@@ -1,7 +1,7 @@
class TagAlias < TagRelationship class TagAlias < TagRelationship
# Validate that the alias doesn't exist yet when it's created or when a BUR # Validate that the alias doesn't exist yet when it's created or when a BUR
# is requested, but not when a BUR is approved (to allow failed BURs to be reapproved) # is requested, but not when a BUR is approved (to allow failed BURs to be reapproved)
validates_uniqueness_of :antecedent_name, scope: :status, conditions: -> { active }, on: %i[create update request] validates :antecedent_name, uniqueness: { scope: :status, conditions: -> { active }, on: %i[create update request] }
validate :absence_of_transitive_relation validate :absence_of_transitive_relation
before_create :delete_conflicting_relationships before_create :delete_conflicting_relationships

View File

@@ -215,7 +215,9 @@ class Upload < ApplicationRecord
end end
def assign_rating_from_tags def assign_rating_from_tags
if rating = PostQueryBuilder.new(tag_string).find_metatag(:rating) rating = PostQueryBuilder.new(tag_string).find_metatag(:rating)
if rating.present?
self.rating = rating.downcase.first self.rating = rating.downcase.first
end end
end end

View File

@@ -33,8 +33,7 @@ class UserEvent < ApplicationRecord
def self.search(params) def self.search(params)
q = search_attributes(params, :id, :created_at, :updated_at, :category, :user, :user_session) q = search_attributes(params, :id, :created_at, :updated_at, :category, :user, :user_session)
q = q.apply_default_order(params) q.apply_default_order(params)
q
end end
def self.available_includes def self.available_includes

View File

@@ -97,8 +97,7 @@ class UserUpgrade < ApplicationRecord
q = q.self_upgrade q = q.self_upgrade
end end
q = q.apply_default_order(params) q.apply_default_order(params)
q
end end
concerning :UpgradeMethods do concerning :UpgradeMethods do