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

时间:2010-11-05 23:06:37

标签: ruby-on-rails constants global

我刚刚开始使用我的第一个Ruby on Rails webapp。我有一堆不同的模型,视图,控制器等等。

我想找到一个好地方来坚持真正全局常量的定义,这适用于我的整个应用程序。特别是,它们既适用于模型的逻辑,也适用于我的观点中的决策。我找不到任何干净的地方将这些定义放在所有我的模型以及我的所有视图中。

举一个具体的例子,我想要一个常数COLOURS = ['white', 'blue', 'black', 'red', 'green']。在模型和视图中都可以使用它。我在哪里可以在一个地方定义它以便它可以访问?

我尝试了什么:

  • model.rb文件中与它们关联最多的常量类变量,例如@@COLOURS = [...]。但我无法找到一种明智的方式来定义它,以便我可以在我的观点Card.COLOURS中写下,而不是像Card.first.COLOURS这样的kludgy。
  • 模型上的方法,如def colours ['white',...] end - 同样的问题。
  • application_helper.rb中的一个方法 - 这是我到目前为止所做的,但帮助程序只能在视图中访问,而不能在模型中访问
  • 我想我可能在application.rb或environment.rb中尝试了一些东西,但那些看起来并不正确(而且它们似乎也没有用)

是否无法定义任何可从模型和视图访问的内容?我的意思是,我知道模型和视图应该是分开的,但在某些领域肯定会有时候他们需要引用相同的领域特定知识?

12 个答案:

答案 0 :(得分:215)

如果你的模型对常量真的“负责”,你应该把它们粘在那里。您可以创建类方法来访问它们,而无需创建新的对象实例:

class Card < ActiveRecord::Base
  def self.colours
    ['white', 'blue']
  end
end

# accessible like this
Card.colours

或者,您可以创建类变量和访问器。但是不鼓励这样做,因为类变量在继承和多线程环境中可能会令人惊讶。

class Card < ActiveRecord::Base
  @@colours = ['white', 'blue']
  cattr_reader :colours
end

# accessible the same as above

如果需要,上面的两个选项允许您在每次调用访问器方法时更改返回的数组。如果你有一个真正不可改变的常量,你也可以在模型类上定义它:

class Card < ActiveRecord::Base
  COLOURS = ['white', 'blue'].freeze
end

# accessible as
Card::COLOURS

您还可以创建全局常量,这些常量可以在初始化程序中的任何位置访问,如下例所示。如果您的颜色真的是全局的并且在多个模型上下文中使用,那么这可能是最佳位置。

# put this into config/initializers/my_constants.rb
COLOURS = ['white', 'blue'].freeze

注意:当我们定义上面的常量时,通常我们想要freeze数组。这可以防止其他代码稍后(无意中)通过例如修改数组来修改数组。添加一个新元素。一旦对象被冻结,它就不能再被更改了。

答案 1 :(得分:66)

一些选项:

使用常数:

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

使用类实例变量加载延迟:

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

如果它是真正的全局常量(避免这种性质的全局常量,但),你也可以考虑放 例如config/initializers/my_constants.rb中的顶级常量。

答案 2 :(得分:51)

从Rails 5.0开始,您可以直接将configuration对象用于custom configuration

config/application.rb(或config/custom.rb,如果您愿意)

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

它将以:

的形式提供
Rails.configuration.colours # => ["white", "blue", "black", "red", "green"]

注意:对于4.2版,您需要使用config.x属性:

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

将提供:

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

答案 3 :(得分:17)

如果在一个以上的类中需要一个常量,我将它放在config / initializers / contant.rb中,总是全部大写(下面的状态列表被截断)。

STATES = ['AK', 'AL', ... 'WI', 'WV', 'WY']

除了模型代码之外,它们可以在整个应用程序中使用:

    <%= form.label :states, %>
    <%= form.select :states, STATES, {} %>

要在模型中使用常量,请使用attr_accessor使常量可用。

class Customer < ActiveRecord::Base
    attr_accessor :STATES

    validates :state, inclusion: {in: STATES, message: "-- choose a State from the drop down list."}
end

答案 4 :(得分:14)

对于应用程序范围的设置和全局常量,我建议使用Settingslogic。此设置存储在YML文件中,可以从模型,视图和控制器访问。更多..您可以为所有环境创建不同的设置:

  # app/config/application.yml
  defaults: &defaults
    cool:
      saweet: nested settings
    neat_setting: 24
    awesome_setting: <%= "Did you know 5 + 5 = #{5 + 5}?" %>

    colors: "white blue black red green"

  development:
    <<: *defaults
    neat_setting: 800

  test:
    <<: *defaults

  production:
    <<: *defaults

在视图中的某个地方(我更喜欢这种东西的辅助方法)或者在模型中你可以获得,例如,颜色数组Settings.colors.split(/\s/)。它非常灵活。而且你不需要发明一辆自行车。

答案 5 :(得分:7)

使用类方法:

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

然后Model.colours将返回该数组。或者,创建一个初始化程序并将常量包装在模块中以避免名称空间冲突。

答案 6 :(得分:3)

另一种选择,如果你想在一个地方定义你的常数:

error: package org.apache.commons does not exist 
import org.apache.commons.math3;

但仍然可以让它们全局可见,而无需以完全合格的方式访问它们:

module DSL
  module Constants
    MY_CONSTANT = 1
  end
end

答案 7 :(得分:3)

应用程序范围的全局常量放在config/application内的常见位置。

module MyApp
  FOO ||= ENV.fetch('FOO', nil)
  BAR ||= %w(one two three)

  class Application < Rails::Application
    config.foo_bar = :baz
  end
end

答案 8 :(得分:2)

尝试将所有常量保持在一个位置,在我的应用程序中,我在初始化器中创建了constants文件夹,如下所示:

enter image description here

通常我会在这些文件中保持不变。

根据您的情况,您可以在常量文件夹下将文件创建为Foo

colors_constant.rb

enter image description here

不要忘记重启服务器

答案 9 :(得分:1)

我通常在rails程序中有一个'lookup'模型/表,并将它用于常量。如果常量对于不同的环境会有所不同,那么它非常有用。此外,如果您有计划扩展它们,假设您想在以后添加“黄色”,您只需在查找表中添加一个新行即可完成。

如果您授予管理员权限以修改此表,则他们不会来找您进行维护。 :)干。

以下是我的迁移代码的样子:

class CreateLookups < ActiveRecord::Migration
  def change
    create_table :lookups do |t|
      t.string :group_key
      t.string :lookup_key
      t.string :lookup_value
      t.timestamps
    end
  end
end

我使用seeds.rb预先填充它。

Lookup.find_or_create_by_group_key_and_lookup_key_and_lookup_value!(group_key: 'development_COLORS', lookup_key: 'color1', lookup_value: 'red');

答案 10 :(得分:0)

全局变量应在config/initializers目录

中声明
COLOURS = %w(white blue black red green)

答案 11 :(得分:0)

根据你的情况,你也可以定义一些环境变量,并在ruby代码中通过ENV['some-var']获取它,这个解决方案可能不适合你,但我希望它可以帮助别人。

示例:您可以根据应用程序环境创建不同的文件.development_env.production_env.test_env并加载它,检查此版本dotenv-rails,以便为您自动执行此操作。< / p>