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:
1 2 3 4 5 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_by methods: if the record is not found,
.find always raises an exception while
.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.
1 2 3 def find_comment(id_code) Comment.find_by(id_code.to_i(26)) end
1 2 3 4 5 6 7 8 9 10 11 12 <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:
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:
1 2 3 def find_comment(id_code) Comment.find_by(id_code: id_code) end
Testing my local application, everything worked as expected :tada::
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!