Anyone want to critique my "guessing" addition to the intro rails app?

Edit: Sorry for the crappy formatting, I tried using ‘’‘ruby’‘’ and ‘’‘html’‘’ but it didn’t do anything?

So I added a guessing component to the app we build in the intro to rails workshop and I’m wondering if I went about it in the right way.
First I added a one line form next to each card so you can take a guess:

view/decks.show.html.erb

<% @cards.each do |card| %>
  <div>
    <strong><%= link_to card.front, [@deck, card] %></strong>
    -
    <%= link_to "Edit", edit_deck_card_path(@deck, card) %>
    <%= link_to "Delete", [@deck, card], method: :delete, confirm: "You sure?" %>
    <%= form_for(:guess, url: guess_path) do |form| %>
	<%= form.text_field :guess, placeholder: "Guess the #{@deck.name} word for #{card.front}", size: 50 %>
	<%= form.hidden_field :deck, value: @deck.id %>
	<%= form.hidden_field :card, value: card.id %>
	<%= form.submit "Guess" %>
    <% end %>
    <br>
  </div>
<% end %>

I had to create the hidden fields so that I could redirect to the proper
card#show page in the guess controller I created:

class GuessesController < ApplicationController
    def create
	@deck = Deck.find(params[:guess][:deck])
	@card = Card.find(params[:guess][:card])
	cookies[:guess] = params[:guess][:guess]
	redirect_to deck_card_path(@deck, @card)
    end
end

I stored the guess in a cookie since that was the only way I could think of to pass around and object that’s not in the database (just like we did with sessions).
Then I created a guess_correct? helper method that could be used in the card view:

application_controller.rb

def guess_correct? guess, answer
  guess.downcase == answer.downcase
end
helper_method :guess_correct?

And here’s the view where it is used:

views/cards/show.html.erb

<% if guess_correct? cookies[:guess], @card.back %>
  <h1><%= @card.back %> is correct!</h1>
<% else %>
  <h1><%= cookies[:guess] %> is incorrect.</h1>
  <h2><%= @card.back %> is <%= @deck.name %> for <%= @card.front %></h2>
<% end %>
<br>
<div><%= link_to "#{@deck.name} cards", @deck %></div>

Well it works but it seems weird to me like I ‘hacked’ it together. I guess I’m wondering:

  1. Is storing the value of the guess in a cookie the right way to do go about it? It doesn’t need to persist in the database but it does need to persist for the guess_correct? method for use in the view.
  2. Did I really need to create the hidden form fields in order to have the proper redirect after going to the guess#create action?
  3. Has anyone else done this? I’d love to see other implementations.

Thanks thoughtbotters!

Hi @savmac, thanks for posting this and nice work.

A few minor points and then answering your larger question.

  1. I would move the guess form (in decks/show) into a partial.
  2. It looks like the guess controller is nested under the decks controller, so that you don’t actually need to pass in the deck in
  3. Instead of params[:guess][:deck] I think this can be params[:deck_id] - this is related to point #2.
  4. I think it would be more common for params[:guess][:card] to be named params[:guess][:card_id]

I’m not sure about not storing the guess in the database. I understand that it doesn’t actually need to be be persisted long term, but it does need to be persisted - you’ve just done it in a cookie. I think my inclination would be to have a Guess model and persist it to the database instead.

@halogenandtoast do you have any additional thoughts on this?

Hey @savmac,

One of the ways to get around not having to persist the guess is to have the guess#create method actually show the response rather than redirecting. That means you’ll have the guess available to you for that request. Additionally there could be a reason to store guesses on cards (providing statistics or adding in spaced repetition).