I learned a lot from working on a Forem issue, where comments containing Comment Liquid Tags were rendered invalid if the tagged comment was later deleted.
Yes. That was a mouthful.
I created a walkthrough video sharing my troubleshooting process. If you would rather read, I have reproduced my process below the video image. π
Say Arit creates a comment, and then Bene creates their comment and includes a Liquid Tag to Arit's comment:
Next, Arit deletes her comment. When Bene goes to edit her comment containing the tag to Arit's now-deleted comment, she sees an error message. Also, the permalink to Bene's comment 404's.
Looking in the code, the app > liquid_tags > comment_tag.rb
file initializes and renders the tagged comment. The app > views > comments > _liquid.html.erb
file is the actual tagged-comment view.
Looking at the find_comment
method in comment_tag.rb
, we see that the error message raised by the exception matches what we see in the application:
def find_comment(id_code)
Comment.find(id_code.to_i(26))
rescue ActiveRecord::RecordNotFound
raise StandardError, "Invalid comment ID or comment does not exist"
end
Intuitively, I felt like a good solution would be to return a message like "Comment Not Found" within the Liquid Tag, while leaving the enclosing comment intact. But I was not sure how to bypass the error exception in order to accomplish this.
After a short tete-a-tete with my teammate Rhymes (ππΎ), I learned a key difference between the .find
and .find_by
methods: if the record is not found, .find
always raises an exception while .find_by
returns nil
.
By calling .find_by
, I could then render different views in _liquid.html.erb
, depending on whether the local comment
variable (passed into the render
method) existed.
def find_comment(id_code)
Comment.find_by(id_code.to_i(26))
end
<div class="liquid-comment">
<% if comment %>
<div class="details">
<a href="/<%= comment.user.username %>">
...
...
<% else %>
<div class="body">
<p>Comment Not Found</p>
</div>
<% end %>
</div>
But when I tested my implementation, I got another error:
Unsupported argument type: 53 (Integer)
The only code I changed that accepts an argument was the find_comment
method. I realized that .find_by
requires me to specify which attribute to search by. Furthermore, the Comment.id_code
attribute is a string, not an integer. So I made the appropriate corrections:
def find_comment(id_code)
Comment.find_by(id_code: id_code)
end
Testing my local application, everything worked as expected π:
Figuring out how to solve a certain coding problem is sometimes akin to detective work. π You use the clues provided in the codebase (or by other devs) to figure out what needs to be changed, and where.
I hope this was helpful to someone. π Thanks for reading/watching!
Cover Photo by Meghan Schiereck on Unsplash
Top comments (1)
I did not know
find
raises exception andfind_by
does not. Thank you for that.