* Add search[order]=post_count param to /artists.
* Make autocomplete do a prefix match ordered by post count, so that it
works the same way that tag autocomplete does elsewhere.
Using `search[empty_only]=true` caused certain queries to throw an
exception due to ambiguous column references after joining on the tags
table.
Example:
https://danbooru.donmai.us/artists?search[empty_only]=true&search[name]=hammer*
PG::AmbiguousColumn exception raised
ERROR: column reference "name" is ambiguous LINE 1: ...ags"."name" = "artists"."name" WHERE (true) AND ((name LIKE ... ^
lib/danbooru/paginator/active_record_extension.rb:108:in `total_count'
lib/danbooru/paginator/active_record_extension.rb:63:in `block in paginate_numbered'
lib/danbooru/paginator/active_record_extension.rb:60:in `tap'
lib/danbooru/paginator/active_record_extension.rb:60:in `paginate_numbered'
lib/danbooru/paginator/active_record_extension.rb:15:in `paginate'
app/controllers/artists_controller.rb:41:in `index'
* The /artists page issued a `SELECT count(*) FROM artists` because
.paginate was missing search_count.
* /artists.json had an N+1 problem on artist urls. This slowed down
autocomplete.
The inactive flag marks series pools that are finished (no more posts
will be added), not pools that are deleted. Finished series should still
be autocompleted.
Fixes this exception caused by the animated_gif autotagger trying to access the
image file, which fails if the image is not hosted on the webserver.
Magick::ImageMagickError exception raised
unable to open image `/var/www/danbooru2/releases/20170322212609/public/data/f0e32c0e2d906c4932858866346f98b5.gif': No such file or directory @ error/blob.c/OpenBlob/2712
app/models/post.rb:177:in `ping'
app/models/post.rb:177:in `is_animated_gif?'
app/models/post.rb:684:in `add_automatic_tags'
app/models/post.rb:638:in `normalize_tags'
app/controllers/posts_controller.rb:49:in `update'
Bug: when moving favorites, the parent is given an upvote for each gold+
favoriter, but the magnitude of these upvotes was based on the
CurrentUser, rather than the upvoter. This meant that upvotes for
supervoter favorites weren't given correctly.
To fix this, `magnitude` is changed to use the voting `user` instead of
CurrentUser.
New problem: when setting the score, `score=` calls `magnitude`, but
`user` isn't initialized yet. So we also refactor so that
1. `initialize_attributes` initializes `user` before setting `score`
2. the vote direction is given by `vote`, so it's separate from `score`
3. updating the score on the post happens in a callback instead of
directly in `score=`.
Bug: when an approver moves the favorites of a post, each favorite is
removed from the child post and added to the parent post. For gold+
users, this triggers an upvote, but these upvotes were performed by the
approver rather than the favoriter.
* Converts queries to use active record instead of raw sql. This ensures
that user objects are loaded by rails in the join, so that we
don't have to issue `User.find` calls to load users one-by-one.
* Use `.includes` to preload associations used in the view, to avoid
additional N+1 query problems (primarily, calls to link_to_user
also causing users to be loaded one-by-one).
/posts/:id/events incorrectly lists appeals as always being resolved.
This is because events UNION together appeals and flags, which doesn't
quite work because for appeals is_resolved is a method, not an
attribute. is_resolved was hardcoded to true so it'd work in the UNION.
This changes PostEvent to be a wrapper object around PostFlag /
PostAppeal, instead of a UNION. PostEvent delegates everything to the
inner flag/appeals object, so that is_resolved works correctly.
Also, this incidentally fixes a problem with /posts/:id/event.xml not
serializing correctly.
Regens simple form config using `rails generate simple_form:install`.
Seems to fix#2913 (erroneous minlength validations being enforced as of
simple_form 3.4.0).
Rendering the updater name at post_versions/_listing.html:25 caused
this for each post version:
SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1
PostArchive#diff caused this for each post version:
SELECT "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT 1
post_version.post.versions.first.id caused an extra query for each post version:
SELECT "post_versions".* FROM "post_versions" WHERE "post_versions"."post_id" = $1 ORDER BY updated_at ASC, id asc LIMIT 1
@post_versions.empty? caused this query:
SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM "post_versions" WHERE (true) LIMIT 20 OFFSET 0) subquery_for_count
which is unnecessary since @post_versions can be counted directly.
Bug introduced in 1400f64; that commit changed dmails so that
creator_ip_addr defaulted to CurrentUser.ip_addr like this:
after_initialize :initialize_attributes, if: :new_record?
def initialize_attributes
self.from_id ||= CurrentUser.id
self.creator_ip_addr ||= CurrentUser.ip_addr
end
...but creator_ip_addr already defaulted to 127.0.0.1 from the database,
so the ||= assignment didn't work. Remove the database default so we
always default to CurrentUser.ip_addr.
coffee-rails and daemons are unused.
kgio, net-ssh, and nokogiri are pulled in by other gems, but they aren't
used by us directly, so they shouldn't need to be listed in the Gemfile.
The template looks like this:
Subject:
#{creator_name} mentioned you in a comment on post ##{post_id}
Body:
@#{creator_name} mentioned you in a \"comment\":/posts/#{post_id}#comment-#{id} on post ##{post_id}:
[quote]
#{DText.excerpt(body, "@"+user_name)}
[/quote]
There's not much sense in saving copies of everything DanbooruBot sends
in DanbooruBot's inbox. They probably won't be checked so it just bloats
the dmails table.
Fixes an N+1 queries problem in the /moderator/post/queue view by
prefetching disapprovals and uploaders.
Also the way disapproval messages were previously rendered triggered a bunch
of sql queries for each post:
SELECT COUNT(*) FROM "post_disapprovals" WHERE "post_disapprovals"."post_id" = $1 [["post_id", 52]]
SELECT COUNT(*) FROM "post_disapprovals" WHERE "post_disapprovals"."post_id" = $1 AND "post_disapprovals"."reason" = $2 [["post_id", 52], ["reason", "breaks_rules"]]
SELECT COUNT(*) FROM "post_disapprovals" WHERE "post_disapprovals"."post_id" = $1 AND "post_disapprovals"."reason" = $2 [["post_id", 52], ["reason", "poor_quality"]]
SELECT COUNT(*) FROM "post_disapprovals" WHERE "post_disapprovals"."post_id" = $1 AND "post_disapprovals"."reason" IN ('disinterest', 'legacy') [["post_id", 52]]
SELECT COUNT(*) FROM "post_disapprovals" WHERE "post_disapprovals"."post_id" = $1 AND (message is not null and message <> '') [["post_id", 52]]
SELECT "post_disapprovals".* FROM "post_disapprovals" WHERE "post_disapprovals"."post_id" = $1 AND (message is not null and message <> '') [["post_id", 52]]
This refactors to bring it down to one:
SELECT "post_disapprovals".* FROM "post_disapprovals" WHERE "post_disapprovals"."post_id" = $1 [["post_id", 52]]