Ruby on Rails: где определить глобальные константы?



Я только начинаю с моего первого Ruby on Rails webapp. У меня есть куча разных моделей, представлений, контроллеров и так далее.



Я хочу найти хорошее место, чтобы придерживаться определения действительно глобальных констант, которые применяются во всем моем приложении. В частности, они применимы как в логике моих моделей, так и в решениях, принимаемых на мой взгляд. Я не могу найти сухого места, чтобы поместить эти определения, где они доступны как для все мои модели, а также в все мои взгляды.



чтобы взять конкретный пример, я хочу константу COLOURS = ['white', 'blue', 'black', 'red', 'green']. Это используется повсюду, как в моделях, так и в представлениях. Где я могу определить его только в одном месте, чтобы он был доступен?



что я пробовал:




  • постоянные переменные класса в модели.rb-файл, с которым они больше всего связаны, например @@COLOURS = [...]. Но я не мог найти разумный способ определить его, чтобы я мог писать в своих представлениях Card.COLOURS а не что-то запутано как Card.first.COLOURS.

  • метод на модели, что-то вроде def colours ['white',...] end - та же проблема.

  • метод в application_helper.rb-это то, что я делаю до сих пор, но помощники доступны только в представлениях, а не в моделях

  • я думаю, что я мог бы попробовать что-то в приложении.РБ или окружающая среда.rb, но они действительно не кажутся правильными (и они, похоже, тоже не работают)


просто нет способа определить что-либо, чтобы быть доступным как из модели и представления? Я имею в виду, что я знаю, что модели и представления должны быть отдельными, но, конечно, в некоторых доменах будут времена, когда им нужно будет ссылаться на одно и то же доменное знание?

658   12  

12 ответов:

если ваша модель действительно "отвечает" за константы, вы должны вставить их туда. Вы можете создать методы класса могут обращаться к ним без создания нового экземпляра объекта:

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

два варианта выше позволяют изменить возвращаемый массив на каждом вызов метода доступа, если требуется. Если у вас есть true действительно неизменяемая константа, вы также можете определить ее в классе модели:

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 матрица. Это предотвращает последующее (непреднамеренное) изменение массива другим кодом, например, путем добавления нового элемента. После того, как объект заморожен, он больше не может быть изменен.

варианты:

используя константу:

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

Lazy загружается с помощью переменной экземпляра класса:

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

Если это действительно глобальная константа (избегайте глобальных констант такого рода, хотя), вы также можете рассмотреть вопрос о размещении константа верхнего уровня в config/initializers/my_constants.rb например.

начиная с Rails 5.0, вы можете использовать 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"]

Если константа нужна более чем в одном классе, я помещаю ее в 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

для общих настроек приложения и для глобальных констант я рекомендую использовать 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/). Он очень гибкий. И вам не нужно изобретать велосипед.

использовать метод класса:

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

затем Model.colours возвращает массив. Кроме того, создайте инициализатор и оберните константы в модуль, чтобы избежать конфликтов пространств имен.

общее место для размещения глобальные константы для всего приложения внутри config/application.

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

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

другой вариант, если вы хотите определить свои константы в одном месте:

module DSL
  module Constants
    MY_CONSTANT = 1
  end
end

но все же сделать их глобально видимыми без необходимости доступа к ним в полном объеме:

DSL::Constants::MY_CONSTANT # => 1
MY_CONSTANT # => NameError: uninitialized constant MY_CONSTANT
Object.instance_eval { include DSL::Constants }
MY_CONSTANT # => 1

обычно у меня есть модель/таблица "lookup" в моей программе 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

Я использую семена.РБ, чтобы предварительно заполнить его.

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

глобальная переменная должна быть объявлена в config/initializers каталог

COLOURS = %w(white blue black red green)

в соответствии с вашим условием, вы также можете определить некоторые переменные среды, и получить его через ENV['some-var'] в коде Ruby, это решение может не подойти для вас, но я надеюсь, что это может помочь другим.

пример: вы можете создавать различные файлы .development_env,.production_env,.test_env и загрузите его в соответствии с вашими средами приложений, проверьте это поколение dotenv-rails которые автоматизируют это для вашего.

попробуйте сохранить все константы в одном месте, в моем приложении я создал папку константы внутри инициализаторов следующим образом:

enter image description here

и я обычно держу все в этих файлах.

в вашем случае вы можете создать файл в папке константы как colors_constant.rb

colors_constant.РБ

enter image description here

не забудьте перезагрузить сервер

Comments

    Ничего не найдено.