Ruby on Rails: Where to define global constants?

前端 未结 12 1721
我在风中等你
我在风中等你 2020-11-28 00:44

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 plac

相关标签:
12条回答
  • 2020-11-28 01:21

    According your condition, you can also define some environmental variables, and fetch it via ENV['some-var'] in ruby code, this solution may not fit for you, but I hope it may help others.

    Example: you can create different files .development_env, .production_env, .test_env and load it according your application environments, check this gen dotenv-rails which automate this for your.

    0 讨论(0)
  • 2020-11-28 01:24

    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.

    0 讨论(0)
  • 2020-11-28 01:24

    Use a class method:

    def self.colours
      ['white', 'red', 'black']
    end
    

    Then Model.colours will return that array. Alternatively, create an initializer and wrap the constants in a module to avoid namespace conflicts.

    0 讨论(0)
  • 2020-11-28 01:28

    Another option, if you want to define your constants in one place:

    module DSL
      module Constants
        MY_CONSTANT = 1
      end
    end
    

    But still make them globally visible without having to access them in fully qualified way:

    DSL::Constants::MY_CONSTANT # => 1
    MY_CONSTANT # => NameError: uninitialized constant MY_CONSTANT
    Object.instance_eval { include DSL::Constants }
    MY_CONSTANT # => 1
    
    0 讨论(0)
  • 2020-11-28 01:30

    Try to keep all constant at one place, In my application I have created constants folder inside initializers as follows:

    and I usually keep all constant in these files.

    In your case you can create file under constants folder as colors_constant.rb

    colors_constant.rb

    Don't forgot to restart server

    0 讨论(0)
  • 2020-11-28 01:33

    As of Rails 4.2, you can use the config.x property:

    # config/application.rb (or config/custom.rb if you prefer)
    config.x.colours.options = %w[white blue black red green]
    config.x.colours.default = 'white'
    

    Which will be available as:

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

    Another method of loading custom config:

    # config/colours.yml
    default: &default
      options:
        - white
        - blue
        - black
        - red
        - green
      default: white
    development:
      *default
    production:
      *default
    
    # config/application.rb
    config.colours = config_for(:colours)
    
    Rails.configuration.colours
    # => {"options"=>["white", "blue", "black", "red", "green"], "default"=>"white"}
    Rails.configuration.colours['default']
    # => "white"
    

    In Rails 5 & 6, you can use the configuration object directly for custom configuration, in addition to config.x. However, it can only be used for non-nested configuration:

    # config/application.rb
    config.colours = %w[white blue black red green]
    

    It will be available as:

    Rails.configuration.colours
    # => ["white", "blue", "black", "red", "green"]
    
    0 讨论(0)
提交回复
热议问题