Ruby on Rails: Where to define global constants?
If your model is really "responsible" for the constants you should stick them there. You can create class methods to access them without creating a new object instance:
class Card < ActiveRecord::Base
def self.colours
['white', 'blue']
end
end
# accessible like this
Card.colours
Alternatively, you can create class variables and an accessor. This is however discouraged as class variables might act kind of surprising with inheritance and in multi-thread environments.
class Card < ActiveRecord::Base
@@colours = ['white', 'blue'].freeze
cattr_reader :colours
end
# accessible the same as above
Card.colours
The two options above allow you to change the returned array on each invocation of the accessor method if required. If you have true a truly unchangeable constant, you can also define it on the model class:
class Card < ActiveRecord::Base
COLOURS = ['white', 'blue'].freeze
end
# accessible as
Card::COLOURS
You could also create global constants which are accessible from everywhere in an initializer like in the following example. This is probably the best place, if your colours are really global and used in more than one model context.
# put this into config/initializers/my_constants.rb
COLOURS = ['white', 'blue'].freeze
# accessible as a top-level constant this time
COLOURS
Note: when we define constants above, often we want to freeze
the array. That prevents other code from later (inadvertently) modifying the array by e.g. adding a new element. Once an object is frozen, it can't be changed anymore.
Rails: Where to define constants with Classes?
I tried putting them in config/initializers, but they would get cached and not update even when I saved a new version of the class/file.
You could define them in a module. Create a file called global_constants.rb
in your models directory and add constants there:
app/models/global_constants.rb
module GlobalConstants
ALL_DEMOGRAPHICS = [Demographic::Gender, Demographic::Age]
end
Then you can use the constants like so:
GlobalConstants::ALL_DEMOGRAPHICS
If you keep the module in lib folder, then make sure you have added lib to autoload:
config/application.rb
config.autoload_paths << Rails.root.join('lib')
Store constants in Rails
Option 1 (class variables):
class Provider
@@FACEBOOK = "facebook"
@@TWITTER = "twitter"
end
@user.authentications.create(:uid => "12345", :provider => Provider.FACEBOOK)
Using class variables is strongly discouraged though in some cases. A better way to go would be to use meta voodoo:
class Provider
@FACEBOOK = "facebook"
@TWITTER = "twitter"
class << self
attr_reader :FACEBOOK, :TWITTER
end
end
@user.authentications.create(:uid => "12345", :provider => Provider.FACEBOOK)
where to put configuration constant in rails
Let's make it clear what is the path you walk through to your app loads the initilization files. You must have in mind this :
When you run rails s
(from your app/script/rails
file) that runs rails
server,
your app
boot.rb
file (which mainly deals with gems loading) is required and then your consoleargs
(here theserver
aliass
) requirement is passed to therails
railties/lib/rails/command.rb
file (which is in therails
source code).There, your app
config/application.rb
is required. Then, theServer
class is instantiated and you are thrown inrailties/lib/rails/command/server.rb
file. In fact, theServer
class inhererits fromRack::Server
, so arails
app israck
app ! So, you'll find aconfig.ru
file in yourrails
app and this loads theconfig/environment.rb
file.
The config/environment.rb
file does two things
requiring your app
config/applcation.rb
, that loads the properrails framework
.( For info, you'll find in your appapplication.rb
theApplication
class that inherits fromRails::Application
, which inherits itself from theRails::Engine
, which inherits from aRails::Railtie
class)calling the
initialize!
bang method, that loads theconfig/environment/*.rb
files, and then processes all the initializers process (more precisely, the initializers methods are defined in therailties/lib/rails/engine.rb
) file. So, now, taking that into account, you should be able to define properly your constants.
To better understand the intialization process, I recommand you this great railscast, which mainly inspired this answer.
Where would I store static/constant values in a rails application?
It depends on where you need to access them.
If you need to use them throughout your application, you can put them in environment.rb
# environment.rb
#
# other global config info
HELLO_EVERYONE = "hiz"
If you need to access them only inside a specific class, you can define them in that model.
class Test < ActiveRecord::Base
HELLO_EVERYONE = "hiz"
end
EDIT
The second case (where the constant is defined in the Test
class), can also be accessed outside of the Test
class, only it needs to be referenced as Test::HELLO_EVERYONE
.
This may be helpful in cases where you have a list of items relevant to the domain of that object (like a list of US states) that you might use in a view (e.g. select_tag :address, :state, options_for_select(Address::STATES)
). Although I might consider wrapping this inside of a class method instead of exposing the internal structure of the class.
class Address< ActiveRecord::Base
STATES = ["AL", "AK", "AZ", "AR", ...]
def self.states
STATES
end
end
Related Topics
How to Iterate Activerecord Attributes, Including Attr_Accessor Methods
How to Capture Values in Command Line and Add to Recipe
What's the Difference Between Colon ":" and Fat Arrow "=>"
Return Index of All Occurrences of a Character in a String in Ruby
Ruby Craziness: Class VS Object
How to Install Ruby 2 on Ubuntu Without Rvm
Does Ruby Provide a Way to Do File.Read() with Specified Encoding
Keep Form Fields Filled After an Error (Ror)
Has_Many :Through with Counter_Cache
How to Reverse a 'Rails Generate'
How to Run a Single Rspec Test
Update Just One Gem with Bundler
How to Remove Gem from Ruby on Rails Application
Rails 4 Migration: How to Reorder Columns
Rails: Postgres Permission Denied to Create Database on Rake Db:Create:All
How to Set Up Simple Http Authentication for a Ruby on Rails App on Heroku