Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Please teach me to fish: how do I navigate the edit/suggested-edit code to apply the same error check to both? Question

+2
−0

I was trying to fix what I thought was an easy bug: suggested edits can add restricted tags (the ones only moderators can apply), which creates a suggested edit that most reviewers can't approve. We already prevent you from adding those tags when you directly edit a post, so I figured -- how hard could it be to apply that same logic to suggested edits?

Harder than I thought, apparently. I don't know if my mental block is due to insufficient Ruby/Rails knowledge, insufficient MVC clues, or something about the QPixel code in particular.

Editing through either path leads to the same form, in app/views/posts/edit.html.erb. For direct saves, there's this check:

<% if @post.errors.any? %>
  <div class="notice is-danger is-filled">
    <p>The following errors prevented your post from being saved:</p>
    <ul>
      <% @post.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
    </ul>
  </div>
<% end %>

Ok, I said -- how do the errors get there? This question led me to app/controllers/posts_controller.rb and specifically the update function. I'm having a little trouble following the logic, but the outline seems to be (in pseudocode):

if current user can edit
  if current user can push to network
    (lots of stuff we don't care about here)
  else (do an edit in a transaction)
else // current user cannot edit
  create suggested edit and send notification to owner

That last part, in a little more detail:

        data = {
          post: @post,
          user: current_user,
          body: body_rendered == @post.body ? nil : body_rendered,
          title: params[:post][:title] == @post.title ? nil : params[:post][:title],
          tags_cache: new_tags_cache == @post.tags_cache ? @post.tags_cache : new_tags_cache,
          body_markdown: params[:post][:body_markdown] == @post.body_markdown ? nil : params[:post][:body_markdown],
          comment: params[:edit_comment],
          active: true, accepted: false
        }
// NOTE the absence of any error checks here
        edit = SuggestedEdit.new(data)

This seems to be the place where I should check for errors, same as we do for direct edits. The first block of code I quoted in this question is how we report errors to the user, but where do they get checked and set?

I grepped for the text of the error message, which led me to app/models/post.rb, in a function called moderator_tags. A comment in the source code says "intended to be used for validation" -- sounds like just what I need! So then I grepped for that function name, looking for where it's called.

That's where I got stuck:

$ grep -r moderator_tags app/*
app/controllers/tags_controller.rb:      exec_sql([sql.gsub('$TABLENAME', 'categories_moderator_tags'), @primary.id, @subordinate.id])
app/controllers/tags_controller.rb:      tables = ['posts_tags', 'categories_moderator_tags', 'categories_required_tags', 'categories_topic_tags',
app/controllers/tags_controller.rb~:      exec_sql([sql.gsub('$TABLENAME', 'categories_moderator_tags'), @primary.id, @subordinate.id])
app/controllers/tags_controller.rb~:      tables = ['posts_tags', 'categories_moderator_tags', 'categories_required_tags', 'categories_topic_tags',
app/controllers/admin_controller.rb:    meta_category.moderator_tags << Tag.unscoped.where(community: @community, name: status_tags)
app/models/category.rb:  has_and_belongs_to_many :moderator_tags, class_name: 'Tag', join_table: 'categories_moderator_tags'
app/models/post.rb:  validate :moderator_tags, if: -> { post_type.has_tags && post_type.has_category && tags_cache_changed? }
app/models/post.rb:  def moderator_tags
app/models/post.rb:    mod_tags = category&.moderator_tags&.map(&:name)
app/views/categories/_form.html.erb:      <%= f.select :moderator_tag_ids, options_for_select(@category.moderator_tags.map { |t| [t.name, t.id] },

What should I do next? How do I find how that validation is done for regular edits, so I can (I hope) apply it to the suggested-edit case and prevent an unapprovable suggestion from getting created?

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

0 answers

Sign up to answer this question »