What is the best way to handle constants in Ruby when using Rails?
You can use an array or hash for this purpose (in your environment.rb):
OPTIONS = ['one', 'two', 'three']
OPTIONS = {:one => 1, :two => 2, :three => 3}
or alternatively an enumeration class, which allows you to enumerate over your constants as well as the keys used to associate them:
class Enumeration
def Enumeration.add_item(key,value)
@hash ||= {}
@hash[key]=value
end
def Enumeration.const_missing(key)
@hash[key]
end
def Enumeration.each
@hash.each {|key,value| yield(key,value)}
end
def Enumeration.values
@hash.values || []
end
def Enumeration.keys
@hash.keys || []
end
def Enumeration.[](key)
@hash[key]
end
end
which you can then derive from:
class Values < Enumeration
self.add_item(:RED, '#f00')
self.add_item(:GREEN, '#0f0')
self.add_item(:BLUE, '#00f')
end
and use like this:
Values::RED => '#f00'
Values::GREEN => '#0f0'
Values::BLUE => '#00f'
Values.keys => [:RED, :GREEN, :BLUE]
Values.values => ['#f00', '#0f0', '#00f']
constant values in Rails
I believe what you are currently doing is fine; you said the data only pertains to one controller, and therefore that's where it belongs. If it was needed for multiple controllers, or if they were more complex than constant values, other approaches may make sense.
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.
Access model-specific constants in a Rails view
You should access them as following:
Challenge::CLOSED
Since your CLOSED
constant is defined within a class, you need to access the constant using the scope resolution operator. So if your view you would check it like:
# challenge/_details.html.erb
<% if @challenge.status == Challenge::CLOSED %>
Challenge is closed, broheim!
<% end %>
Accessing a class's constants
What you posted should work perfectly:
class Foo
CONSTANT_NAME = ["a", "b", "c"]
end
Foo::CONSTANT_NAME
# => ["a", "b", "c"]
Related Topics
Rails Email Error - 530-5.5.1 Authentication Required
Open_Id_Authentication - "Openidauthentication.Store Is Nil. Using In-Memory Store." Problem
Rspec Allow/Expect VS Just Expect/And_Return
How to Generate a Random Number Between a and B in Ruby
Find or Create Record Through Factory_Girl Association
Why 'Self' Method of Module Cannot Become a Singleton Method of Class
Generate and Publish Ruby Based Rest APIs Documentation
Converting Utc Timestamp to Iso 8601 in Ruby
Concatenating String with Number in Ruby
Ruby Way to Check for String Palindrome
Rails with Paypal Permissions and Paypal Express Checkout
Ruby Float#Round Method Behaves Incorrectly with Round(2)
How to Update Ruby with Homebrew
Ruby - Elegantly Convert Variable to an Array If Not an Array Already
Rails Bundler Doesn't Install Gems Inside a Group