3

I've heard that it's considered bad practice in Ruby to use global variables beginning with a dollar sign. Is this also true for Rails controllers?

For example, I have a web app that uses a series of partial views that render in successive stages. The user input from the first stage gets taken from the param and put into a global variable so that it is accessible to each subsequent method. Those later stages need to easily access the selections the user made in the earlier stages.

routes.rb

post 'stage_one_form' => 'myexample#stage_two_form'
post 'stage_two_form' => 'myexample#stage_three_form'
post 'stage_three_form' => 'myexample#stage_four_form'

myexample_controller.rb

def stage_two_form
   $stage_one_form_input = params[:stage_one_form_input]
end

...

def stage_four_form
   @stage_four_displayed_info = $stage_one_form_input + "some other stuff"
end

This is just a dummy example but it seems a lot more graceful to use global variables here than my original approach, which was to pass the information back and forth from the client to the server in each stage, by using hidden fields.

Are global variables appropriate, or is there a better way?

emery
  • 8,603
  • 10
  • 44
  • 51

2 Answers2

3

If you want store the input from the first stage and use on stage two, you are doing a kind o wizard. You consider using the session or something more robust to store the information, not configuration or models as stated by @NickM.

For more info:

Rails Multi-Step Form without Wizard Gem

http://railscasts.com/episodes/217-multistep-forms

Additional info...

What you have done here with these global variables will not work in a production deployment where you're using an application server. In those environments you need multiple processes (or threads) so that more than one visitor to your site can be served at the same time.

With both of these you will have two problems:

  1. Setting of the variable for one visitor will affect the experience of the next visitor (even if it's a different person) to be served by that process/thread.
  2. A related problem is that a single visitor is not at all guaranteed to be served by the same process on their next request, so the process/thread that serves their second request is probably not going to have the global variable set from their first request.

In summary, chaos, use session - that's precisely what it's for.

Community
  • 1
  • 1
RPinel
  • 866
  • 6
  • 15
0

You can throw them in config/application.rb, or your config.yml file.

config.your_variable = 'something'

Then call it from inside your app

<%= Rails.configuration.your_variable %>

Or you could throw it in a controller:

class Foo
  MY_VARIABLE = 'something'
end

And then call it in your view:

<%= Foo::MY_VARIABLE %>

Or you could throw it in a method in your controller and define a helper:

class FooController
  def my_variable
    'something'
  end
  helper_method :my_variable
end

More info about config.yml here: Best way to create custom config options for my Rails app?

..but if you need to access one variable in various stages, you might want to dump it in a session variable in your controller:

session[:stage] = 'something'

and access it later using session[:stage] Then you can clear it when the process starts again:

session[:stage] = nil
Community
  • 1
  • 1
NM Pennypacker
  • 6,704
  • 11
  • 36
  • 38
  • Are these approaches better than using global variables? – emery Mar 20 '15 at 18:23
  • The `config` approach has precisely the same problems as the global variables, see Roque's answer for details on those problems. – smathy Mar 20 '15 at 18:56