This topic is for the [Active Record Queries] exercise in the [Rails Fundamentals] trail. Post any questions, corrections, or pointers you have to share with other Upcase subscribers.
[Active Record Queries]: https://exercises.upcase.com/exercises/active-record-queries
[Rails Fundamentals]: Rails Fundamentals | Online Tutorial by thoughtbot
Hi there,
It seems there is some undesirable functionality in this iteration of the app which is not being caught by the tests. The visitor_views_guestbook_entries_spec
tests for proper scoping of entries on the home page. But if an invalid entry is made (and the home page re-rendered), this behavior is not tested for scoping.
In the else
branch of the create
action in the controller, the following line causes all the entries to be displayed when the page is rendered:
@guestbook_entries = GuestbookEntry.all
It would appear that this is not the intended behavior of the app.
As a suggestion, adding the following example to the visitor_views_guestbook_entries_spec.rb
file catches this:
scenario "properly scopes entries in case of errors" do
create_old_guestbook_entry("Hi from a long time ago!")
(1..6).each { |n| create_recent_guestbook_entry("Entry #{n}") }
visit root_path
fill_in "Guestbook Entry:", with: ""
click_button "Submit"
expect(page).to have_content "can't be blank"
expect(page).not_to have_content("Hi from a long time ago!")
expect(page).not_to have_content("Entry 1")
end
Hey Josh,
Thanks for pointing this out and suggesting a fix.
I think youāre right that in a real app this might be unwanted behavior. However, Iām not 100% convinced yet that we should add your new test to the exercise. I worry that it makes the exercise a bit less clear.
Did you find the existing behavior confusing as you were trying to complete it, or is this just something you happened to notice as you were working on it?
Thanks!
Hey Ben,
Actually, I didnāt see it when working on the exercise myself. But I noticed the issue in someone elseās solution, and I realized that the display output for the āunhappy pathā effectively breaks the view in cases where the db contains more than a dozen or so entries.
Point 4 of the exercise instructions says this: āChain these scopes together in the controller so that the GuestbookEntry records are displayed correctly on the guestbook home page.ā If my controller action looks like this:
def create
@guestbook_entry = GuestbookEntry.new(guestbook_entry_params)
if @guestbook_entry.save
redirect_to root_path, notice: "Thank you for your entry."
else
@guestbook_entries = GuestbookEntry.all # No scoping here
render :index
end
end
ā¦(which is all the spec calls for) then when I am redirected to the index page, the error message and indeed the form itself are well off the screen. For demonstration, I added 60 guestbook entries to the db. See screenshots here:
- Normal index view: Dropbox - Screenshot 2015-05-28 14.23.51.png - Simplify your life
- Index view with errors: Dropbox - Screenshot 2015-05-28 14.24.17.png - Simplify your life
To my mind, this is a classic mistake that I can see myself making in development, and then discovering later. Which, as it turns out, is exactly what happened here.
That said, if you think the extra test muddies the exercise, I certainly understand. Simplicity vs real-world/completeness is, Iām sure, a fine line to walk when creating these things. But given the instructions, I felt that the requirements were not fully met without applying the scope chain to both possible paths in the controller. The suggested spec would simply serve as an indicator that both successful and unsuccessful outcomes are important.
So thereās my two cents. Hope itās helpful either way. And by the way, may I say that on the whole, these exercises are amazing! Iāve never seen anything like this in any other Rails training Iāve done. I procrastinated in starting them for a while, but now that Iāve begun, Iām enjoying them immensely. Great work!
i donāt think it would be confusing to replace GuestbookEntry.all with GuestbookEntry.limited in the create block.
GuestbookEntry.limited is not the answer. But whatever the answer is could be used in the create block.