我刚刚开始使用我的第一个Ruby on Rails web应用程序。我有很多不同的模型,视图,控制器等等。

我想找到一个好地方粘真正的全局常数的定义,适用于我的整个应用程序。特别是,它们适用于我的模型的逻辑,并在我的视图中所做的决定。我找不到任何DRY的地方来放置这些定义,它们既适用于我的所有模型,也适用于我的所有视图。

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

我的尝试:

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)

是否没有办法定义从模型和视图都可以访问的东西?我的意思是,我知道模型和视图应该是分开的,但在某些领域,它们肯定会有需要引用相同的领域特定知识的时候?


当前回答

我通常在我的rails程序中有一个“查找”模型/表,并将其用于常量。如果常数在不同的环境下是不同的这是非常有用的。此外,如果你有一个扩展它们的计划,比如你想在以后的日期添加“黄色”,你可以简单地向查找表中添加一个新行,然后完成它。

如果您赋予管理员修改此表的权限,则他们将不会来维护。:)干燥。

下面是我的迁移代码:

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

我用种子。Rb来预填充它。

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

其他回答

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

  # app/config/application.yml
  defaults: &defaults
    cool:
      sweet: 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/)。它非常灵活。你不需要发明一辆自行车。

如果一个常量在多个类中需要,我会把它放在config/initializers/constant中。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

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

例如:你可以创建不同的文件。development_env, .production_env, .test_env,并根据你的应用程序环境加载它,检查这个gen dotenv-rails,它为你的应用程序自动化。

一些选项:

使用常量:

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

如果它是一个真正的全局常数(但是要避免这种性质的全局常数),您还可以考虑put config/initializers/my_constants中的顶级常量。比如Rb。

我认为您可以使用gem配置

https://github.com/rubyconfig/config

易于操作和编辑