Files
danbooru/app/models/user_feedback.rb
evazion 59b277ead1 users: drop id_to_name, name_to_id caching.
Changes:

* Drop Users.id_to_name.
* Don't cache Users.name_to_id.
* Replace calls to name_to_id with find_by_name when possible.
* Don't autodefine creator_name in belongs_to_creator.
* Don't autodefine updater_name in belongs_to_updater.
* Instead manually define creator_name / updater_name only on models that need
  to return these fields in the api.

id_to_name was cached to reduce the impact of N+1 query patterns in
certain places, especially in api responses that return creator_name /
updater_name fields. But it still meant we were doing N calls to
memcache. Using `includes` to prefetch users avoids this N+1 pattern.

name_to_id had no need be cached, it was never used in any performance-
sensitive contexts.

Avoiding caching also avoids the need to keep these caches consistent.
2019-08-18 11:24:42 -05:00

114 lines
3.9 KiB
Ruby

class UserFeedback < ApplicationRecord
self.table_name = "user_feedback"
belongs_to :user
belongs_to_creator
attr_accessor :disable_dmail_notification
validates_presence_of :body, :category
validates_inclusion_of :category, :in => %w(positive negative neutral)
validate :creator_is_gold
validate :user_is_not_creator
after_create :create_dmail, unless: :disable_dmail_notification
after_update(:if => ->(rec) { CurrentUser.id != rec.creator_id}) do |rec|
ModAction.log(%{#{CurrentUser.name} updated user feedback for "#{rec.user.name}":/users/#{rec.user_id}},:user_feedback_update)
end
after_destroy(:if => ->(rec) { CurrentUser.id != rec.creator_id}) do |rec|
ModAction.log(%{#{CurrentUser.name} deleted user feedback for "#{rec.user.name}":/users/#{rec.user_id}},:user_feedback_delete)
end
module SearchMethods
def positive
where("category = ?", "positive")
end
def neutral
where("category = ?", "neutral")
end
def negative
where("category = ?", "negative")
end
def for_user(user_id)
where("user_id = ?", user_id)
end
def visible(viewer = CurrentUser.user)
if viewer.is_admin?
all
else
# joins(:user).merge(User.undeleted).or(where("body !~ 'Name changed from [^\s:]+ to [^\s:]+'"))
joins(:user).where.not("users.name ~ 'user_[0-9]+~*' AND user_feedback.body ~ 'Name changed from [^\s:]+ to [^\s:]+'")
end
end
def default_order
order(created_at: :desc)
end
def search(params)
q = super
q = q.attribute_matches(:body, params[:body_matches])
if params[:user_id].present?
q = q.for_user(params[:user_id].to_i)
end
if params[:user_name].present?
q = q.where("user_id = (select _.id from users _ where lower(_.name) = ?)", params[:user_name].mb_chars.downcase.strip.tr(" ", "_"))
end
if params[:creator_id].present?
q = q.where("creator_id = ?", params[:creator_id].to_i)
end
if params[:creator_name].present?
q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].mb_chars.downcase.strip.tr(" ", "_"))
end
if params[:category].present?
q = q.where("category = ?", params[:category])
end
q.apply_default_order(params)
end
end
extend SearchMethods
def user_name=(name)
self.user = User.find_by_name(name)
end
def disclaimer
if category != "negative"
return nil
end
"The purpose of feedback is to help you become a valuable member of the site by highlighting adverse behaviors. The author, #{creator.name}, should have sent you a message in the recent past as a warning. The fact that you're receiving this feedback now implies you've ignored their advice.\n\nYou can protest this feedback by petitioning the mods and admins in the forum. If #{creator.name} fails to provide sufficient evidence, you can have the feedback removed. However, if you fail to defend yourself against the accusations, you will likely earn yourself another negative feedback.\n\nNegative feedback generally doesn't affect your usability of the site. But it does mean other users may trust you less and give you less benefit of the doubt.\n\n"
end
def create_dmail
body = %{#{disclaimer}@#{creator.name} created a "#{category} record":/user_feedbacks?search[user_id]=#{user_id} for your account:\n\n#{self.body}}
Dmail.create_automated(:to_id => user_id, :title => "Your user record has been updated", :body => body)
end
def creator_is_gold
if !creator.is_gold?
errors[:creator] << "must be gold"
elsif creator.no_feedback?
errors[:creator] << "cannot submit feedback"
end
end
def user_is_not_creator
if user_id == creator_id
errors[:creator] << "cannot submit feedback for yourself"
end
end
def editable_by?(editor)
(editor.is_moderator? && editor != user) || creator == editor
end
end