summerteeth
summerteeth

Reputation: 15

How can I keep a running score in a very basic Rails app?

New to Rails, so I appreciate your patience in advance! For a class assignment we had to build out a very basic web app (no databases) that included a "Guess the secret number" game and a "Rock, Paper, Scissors" game. At this point, I have both games all done, but I felt like going a bit further and adding a simple "Current Score" item that persists at the top of the screen no matter what part of that app you're in, and that keeps track of your score as you go from game to game -- the score refreshes when you restart the server, basically.

My initial instinct was to create an instance variable called @score in my application controller, but my game controllers can't see that variable, despite being children of the application controller. So I tried just simply adding it to my game controller -- that correctly brought in the starting value of '10' but then reset the value every time I hit refresh. Alright, so now I'm stuck.

My assumption is that the use of an instance variable in this case is incorrect. It would make sense to store it in some sort of globally-accessible variable that I can increment or decrement no matter where I am in the app. Thus, it seems to make sense that it should exists in the Application controller, but then I'm running into the issue of having it be accessible throughout each part of the app.

I hope this is clear enough. I guess the basic question is this: If I want to initialize a variable at 0 from the moment someone starts the app, and have the ability to increment and decrement that number, permanently, until I restart the server, how can I do that? Where is the variable created, and how do I access it from other points in the app?

Thanks!

Upvotes: 0

Views: 789

Answers (2)

Mark Meeus
Mark Meeus

Reputation: 707

You should never have any kind of state variables in your application. It is bad practice, and it will break all sorts of things in a production application. The value of the score is state.

Ideally, you store state in a database, or some sort of storage which is outside of your application. (This way, you can run multiple instances of your application, and they will all see the same data)

In your case (for the sake of the exercise) you can store it in a cookie as well. Cookies are sent back to the browser as part of the http response, and they will be sent back to the server with every subsequent response.

You could also use the Rails sessions (which is stored in a cookie by default) like this

session[:score] = score

However, neither the session and the cookie solution will destroy your value when the server restarts. It really doesn't make any sense to me why you would want the score to reset. If you really want something like that, you could generate a random value once and check the score against that.

Put this in your application_controller.rb:

def score_key
    @@score_key ||= SecureRandom.uuid
end

def get_score
   if session[:score_key] == score_key
      session[:score]
   else
      0
   end
end

def save_score score
   session[:score] = score
   session[:score_key] = score_key
end

This way you can always get or save your score by using those methods.

Upvotes: 1

Anthony To
Anthony To

Reputation: 2303

A very simple way to do it would be to use an environment variable.

config/initializers/score.rb

SCORE_CONFIG = YAML.load_file("#{::Rails.root}/config/score.yml")[::Rails.env]

config/score.yml

development: &default
 score: 0

test: 
 <<: *default

production:
 <<: *default

In any view:

<%= SCORE_CONFIG["score"] %>

In any controller action:

SCORE_CONFIG["score"] += 1

When the server is running the app will continue the current state of the score variable, but once you restart the server is defaults back to 0.

Upvotes: 0

Related Questions