Ruby on Rails: Where to define global constants?

I'm just getting started with my first Ruby on Rails webapp. I've got a bunch of different models, views, controllers, and so on.

I'm wanting to find a good place to stick definitions of truly global constants, that apply across my whole app. In particular, they apply both in the logic of my models, and in the decisions taken in my views. I cannot find any DRY place to put these definitions where they're available both to all my models and also in all my views.

To take a specific example, I want a constant COLOURS = ['white', 'blue', 'black', 'red', 'green'] . This is used all over the place, in both models and views. Where can I define it in just one place so that it's accessible?

What I've tried:

  • Constant class variables in the model.rb file that they're most associated with, such as @@COLOURS = [...] . But I couldn't find a sane way to define it so that I can write in my views Card.COLOURS rather than something kludgy like Card.first.COLOURS .
  • A method on the model, something like def colours ['white',...] end - same problem.
  • A method in application_helper.rb - this is what I'm doing so far, but the helpers are only accessible in views, not in models
  • I think I might have tried something in application.rb or environment.rb, but those don't really seem right (and they don't seem to work either)
  • Is there just no way to define anything to be accessible both from models and from views? I mean, I know models and views should be separate, but surely in some domains there'll be times they need to refer to the same domain-specific knowledge?


    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']
      cattr_reader :colours
    end
    
    # accessible the same as above
    

    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
    

    Note: when we define constants above, often we want to freeze the array. That prevents other code from later (inadvertently) modifying the array by eg adding a new element. Once an object is frozen, it can't be changed anymore.


    Some options:

    Using a constant:

    class Card
      COLOURS = ['white', 'blue', 'black', 'red', 'green', 'yellow'].freeze
    end
    

    Lazy loaded using class instance variable:

    class Card
      def self.colours
        @colours ||= ['white', 'blue', 'black', 'red', 'green', 'yellow'].freeze
      end
    end
    

    If it is a truly global constant ( avoid global constants of this nature, though ), you could also consider putting a top-level constant in config/initializers/my_constants.rb for example.


    As of Rails 5.0, You can use the configuration object directly for custom configuration:

    In config/application.rb (or config/custom.rb if you prefer)

    config.colours = %w(white blue black red green)
    

    It will be available as:

    Rails.configuration.colours # => ["white", "blue", "black", "red", "green"]
    

    Note: For version 4.2, you need to use the config.x property:

    config.x.colours = %w(white blue black red green)
    

    Which will be available as:

    Rails.configuration.x.colours # => ["white", "blue", "black", "red", "green"]
    
    链接地址: http://www.djcxy.com/p/35146.html

    上一篇: C列举,NS

    下一篇: Ruby on Rails:在哪里定义全局常量?