TGutmann87
TGutmann87

Reputation: 19

Setting variable flash[:message] in ruby

I have an .erb file that displays the following lines:

<% if flash[:message]%>
<p><span class"error"><%= flash[:message] %></p>
<%end%>

I would like to set the variable flash[:message] in a .rb file and am not sure how to do so. For whatever reason symbols in Ruby tend to confuse me a bit. They seem like pointers, but somewhat different.

File 1:

class HangpersonGame
 attr_accessor :word
 attr_accessor :guesses
 attr_accessor :wrong_guesses 

  # add the necessary class methods, attributes, etc. here
  # to make the tests in spec/hangperson_game_spec.rb pass.
  # Get a word from remote "random word" service
  # def initialize()
  # end

  def initialize(word)
    @word = word 
    @guesses = "" 
    @wrong_guesses = ""
  end

  def guess(letter)
    # make sure the letter is actually a letter
    if letter == nil || !(letter.class == String && letter =~ /^[A-z]$/i)
      raise ArgumentError
    end

    # handle different cases
    letter.downcase!

    # handle repeated guesses
    if @guesses.include?(letter) || @wrong_guesses.include?(letter)
      flash[message] = "You have already used that letter"
      return false
    end

    #handle case where guess is not a letter
    return false if letter.length != 1

    # finally handle check and return true
    if @word.include? letter
      @guesses << letter
    else
      @wrong_guesses << letter
    end
    return true
  end

  def word_with_guesses
    result = ''
    @word.split('').each do |char|
      if @guesses.include? char
        result << char
      else
        result << '-'
      end
    end

    return result
  end

  def check_win_or_lose
    if word_with_guesses.downcase == @word.downcase
      return :win
    elsif @wrong_guesses.length >= 7
      return :lose
    else
      return :play
    end
  end

  # You can test it by running $ bundle exec irb -I. -r app.rb
  # And then in the irb: irb(main):001:0> HangpersonGame.get_random_word
  #  => "cooking"   <-- some random word
  def self.get_random_word
    require 'uri'
    require 'net/http'
    uri = URI('http://watchout4snakes.com/wo4snakes/Random/RandomWord')
    Net::HTTP.new('watchout4snakes.com').start { |http|
      return http.post(uri, "").body
    }
  end

end

File 2:

<h2>Guess a letter</h2>

<% if flash[:message] %>
  <p>
    <span class="error"><%= flash[:message] %></span>
  </p>
<% end %>

<p>
  Wrong Guesses:
  <span class="guesses"><%= @game.wrong_guesses %></span>
</p>

<p>
  Word so far:
  <span class="word"><%= @game.word_with_guesses %></span>
</p>

<form action="/guess" method="post">
  <input type="text" size="1" name="guess" autocomplete="off"/>
  <input type="submit" value="Guess!"/>
</form>

<%= erb :new %>

File 3:

require 'sinatra/base'
require 'sinatra/flash'
require './lib/hangperson_game.rb'

class HangpersonApp < Sinatra::Base

  enable :sessions
  register Sinatra::Flash

  before do
    @game = session[:game] || HangpersonGame.new('')
  end

  after do
    session[:game] = @game 
  end

  # These two routes are good examples of Sinatra syntax
  # to help you with the rest of the assignment
  get '/' do
    redirect '/new'
  end

  get '/new' do
    erb :new
  end

  post '/create' do
    # NOTE: don't change next line - it's needed by autograder!
    word = params[:word] || HangpersonGame.get_random_word
    # NOTE: don't change previous line - it's needed by autograder!

    @game = HangpersonGame.new(word)
    redirect '/show'
  end

  # Use existing methods in HangpersonGame to process a guess.
  # If a guess is repeated, set flash[:message] to "You have already used that letter."
  # If a guess is invalid, set flash[:message] to "Invalid guess."
  post '/guess' do
    letter = params[:guess].to_s[0]
    ### YOUR CODE HERE ###

    @game.guess(letter);

    redirect '/show'
  end

  # Everytime a guess is made, we should eventually end up at this route.
  # Use existing methods in HangpersonGame to check if player has
  # won, lost, or neither, and take the appropriate action.
  # Notice that the show.erb template expects to use the instance variables
  # wrong_guesses and word_with_guesses from @game.
  get '/show' do
    ### YOUR CODE HERE ###
    erb :show # You may change/remove this line
  end

  get '/win' do
    ### YOUR CODE HERE ###
    erb :win # You may change/remove this line
  end

  get '/lose' do
    ### YOUR CODE HERE ###
    erb :lose # You may change/remove this line
  end

end

Upvotes: 0

Views: 775

Answers (1)

Pablo
Pablo

Reputation: 3005

You tagged the question as ruby-on-rails, but it is sinatra. In ruby-on-rails you set the flash message in the controller (it's part of the session). You cannot set it in the model.

I don't know how Sinatra works, but I read it's similar. I found this:

Flash message in Sinatra

You can set the flash message in the controller (post '/guess'):

result = @game.guess(letter);
if result == REPEATED then
  session[:message] = "You have already used that letter"
elsif result == WRONG
  session[:message] = "Invalid guess"
else
   session[:message] = nil
end

This requires you to change the guess method to return different values instead of just true or false.

Then you can set a variable in the controller (get '/show') to be used in the view. I don't know if this is mandatory (or you could use the session[:message] in the view):

@message = session[:message]
session[:message] = nil

Finally you show the message in the show view

<% if @message %>
  <p>
    <span class="error"><%= @message %></span>
  </p>
<% end %>

Upvotes: 1

Related Questions