Ruby on Rails: gdzie definiować stałe globalne?

Dopiero zaczynam pracę z moją pierwszą aplikacją webową Ruby on Rails. Mam kilka różnych modeli, widoków, kontrolerów i tak dalej.

Chcę znaleźć dobre miejsce, aby trzymać definicje prawdziwie globalnych stałych, które mają zastosowanie w całej mojej aplikacji. W szczególności mają one zastosowanie zarówno w logice moich modeli, jak i w decyzjach podejmowanych w moich poglądach. Nie mogę znaleźć żadnego suchego miejsca, aby umieścić te definicje, gdzie są dostępne zarówno dla wszystkich moich modeli, jak i dla wszystkich moich widoki.

Aby wziąć konkretny przykład, chcę stałą COLOURS = ['white', 'blue', 'black', 'red', 'green']. Jest to używane wszędzie, zarówno w modelach, jak i widokach. Gdzie mogę go zdefiniować w jednym miejscu, aby był dostępny?

Czego próbowałem:

  • stałe zmienne klasy w modelu.plik rb, z którym są najbardziej związane, np. @@COLOURS = [...]. Ale nie mogłem znaleźć rozsądnego sposobu, aby to zdefiniować, aby móc pisać w moich poglądach Card.COLOURS, a nie coś kludgy jak Card.first.COLOURS.
  • metoda na modelu, coś w stylu def colours ['white',...] end - ten sam problem.
  • metoda w application_helper.rb-To jest to, co robię do tej pory, ale helpery są dostępne tylko w widokach, nie w modelach
  • myślę, że mogłem spróbować czegoś w aplikacji.rb lub środowiska.rb, ale te nie wydają się w porządku (i też nie wydają się działać)

Czy po prostu nie ma sposobu na zdefiniowanie czegokolwiek, aby było dostępne zarówno z modeli, jak i z widoków? Wiem, że modele i widoki powinny być oddzielne, ale z pewnością w niektórych domenach pojawią się czasy, w których będą musieli odwoływać się do tej samej wiedzy dotyczącej danej domeny?

Author: AlexC, 2010-11-06

12 answers

Jeśli twój model jest naprawdę "odpowiedzialny" za stałe, powinieneś je tam umieścić. Można tworzyć metody klas, aby uzyskać do nich dostęp bez tworzenia nowej instancji obiektu:

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

# accessible like this
Card.colours

Alternatywnie, można utworzyć zmienne klasy i accessor. Jest to jednak zniechęcające, ponieważ zmienne klasowe mogą dziwić w dziedziczeniu i w środowiskach wielowątkowych.

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

# accessible the same as above

Dwie powyższe opcje pozwalają na zmianę zwracanej tablicy przy każdym wywołaniu accesora metoda w razie potrzeby. Jeśli masz true a prawdziwie niezmienną stałą, możesz ją również zdefiniować na klasie modelu:

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

# accessible as
Card::COLOURS

Można również utworzyć stałe globalne, które są dostępne z każdego miejsca w inicjalizatorze, jak w poniższym przykładzie. Jest to prawdopodobnie najlepsze miejsce, jeśli twoje kolory są naprawdę globalne i używane w więcej niż jednym kontekście modelu.

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

Uwaga: kiedy definiujemy stałe powyżej, często chcemy freeze tablicy. Zapobiega to późniejszemu (nieumyślnie) modyfikowanie tablicy przez np. dodanie nowego elementu. Po zamrożeniu obiektu nie można go już zmienić.

 205
Author: Holger Just,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-29 11:29:05

Niektóre opcje:

Używając stałej:

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

Jeśli jest to prawdziwie globalna stała (unikaj globalnych stałych tego rodzaju, chociaż ), Możesz również rozważyć umieszczenie na przykład stała najwyższego poziomu w config/initializers/my_constants.rb.

 64
Author: Zabba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-30 07:14:02

Od Rails 5.0, możesz używać obiektu configuration bezpośrednio do niestandardowej konfiguracji :

W config/application.rb (lub config/custom.rb jeśli wolisz)

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

Będzie dostępny jako:

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

Uwaga: w wersji 4.2, musisz użyć config.x własność:

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

Który będzie dostępny jako:

Rails.configuration.x.colours # => ["white", "blue", "black", "red", "green"]
 44
Author: Halil Özgür,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-19 17:16:03

Jeśli stała jest potrzebna w więcej niż jednej klasie, umieszczam ją w config/initializers / contant.rb zawsze we wszystkich wielkościach (lista stanów poniżej jest okrojona).

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

Są one dostępne za pośrednictwem aplikacji, z wyjątkiem kodu modelu jako takiego:

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

Aby użyć stałej w modelu, użyj attr_accessor, aby stała była dostępna.

class Customer < ActiveRecord::Base
    attr_accessor :STATES

    validates :state, inclusion: {in: STATES, message: "-- choose a State from the drop down list."}
end
 16
Author: Hank Snow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-18 20:36:36

Dla ustawień dla całej aplikacji i dla stałych globalnych zalecam użycie Settingslogic . Ustawienia te są przechowywane w pliku YML i mogą być dostępne z modeli, widoków i kontrolerów. Nawet więcej.. możesz tworzyć różne ustawienia dla wszystkich środowisk:

  # 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

Gdzieś w widoku (preferuję metody pomocnicze dla tego typu rzeczy) lub w modelu, który można uzyskać, na przykład., tablica kolorów Settings.colors.split(/\s/). Jest bardzo elastyczny. I nie musisz wymyślać roweru.

 14
Author: Voldy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-05 23:50:58

Użyj metody klasowej:

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

Wtedy Model.colours zwróci tablicę. Alternatywnie, Utwórz inicjalizator i zawiń stałe w module, aby uniknąć konfliktów przestrzeni nazw.

 7
Author: Steve Ross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-06 03:15:10

Wspólne miejsce do umieszczania stałych globalnych dla całej aplikacji znajduje się wewnątrz config/application.

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

  class Application < Rails::Application
    config.foo_bar = :baz
  end
end
 3
Author: Dennis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-29 13:10:03

Inna opcja, jeśli chcesz zdefiniować swoje stałe w jednym miejscu:

module DSL
  module Constants
    MY_CONSTANT = 1
  end
end

Ale nadal sprawiają, że są widoczne globalnie bez konieczności dostępu do nich w pełni wykwalifikowany sposób:

DSL::Constants::MY_CONSTANT # => 1
MY_CONSTANT # => NameError: uninitialized constant MY_CONSTANT
Object.instance_eval { include DSL::Constants }
MY_CONSTANT # => 1
 2
Author: wincent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-08 01:43:16

Zazwyczaj mam model/tabelę' lookup ' w moim programie rails i używam jej dla stałych. Jest to bardzo przydatne, jeśli stałe będą różne dla różnych środowisk. Ponadto, jeśli masz plan ich rozszerzenia, powiedz, że chcesz dodać "żółty" w późniejszym terminie, możesz po prostu dodać nowy wiersz do tabeli wyszukiwania i zakończyć z nim.

Jeśli nadasz administratorowi uprawnienia do modyfikowania tej tabeli, nie przyjdą do Ciebie w celu konserwacji. :) Sucha.

Oto jak mój kod migracji wygląda następująco:

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
Używam nasion.rb, aby go wstępnie wypełnić.
Lookup.find_or_create_by_group_key_and_lookup_key_and_lookup_value!(group_key: 'development_COLORS', lookup_key: 'color1', lookup_value: 'red');
 1
Author: SriSri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-27 11:25:23

Zmienna globalna powinna być zadeklarowana w katalogu config/initializers

COLOURS = %w(white blue black red green)
 0
Author: Tam Dc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-11 04:03:55

Zgodnie z Twoim warunkiem, możesz również zdefiniować niektóre zmienne środowiskowe i pobrać je za pomocą ENV['some-var'] w kodzie ruby, To rozwiązanie może nie pasować do ciebie, ale mam nadzieję, że może pomóc innym.

Przykład: możesz tworzyć różne pliki .development_env, .production_env, .test_env i załaduj go zgodnie ze środowiskami aplikacji, sprawdź ten gen dotenv-rails który automatyzuje to dla Twojego.

 0
Author: fangxing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-03 04:32:43

Staraj się trzymać wszystkie stałe w jednym miejscu, w mojej aplikacji utworzyłem folder stałe wewnątrz inicjalizatorów w następujący sposób:

Tutaj wpisz opis obrazka

I zwykle trzymam wszystkie stałe w tych plikach.

W Twoim przypadku możesz utworzyć plik w folderze stałe jako colors_constant.rb

colors_constant.rb

Tutaj wpisz opis obrazka

Nie zapomnij zrestartować serwera

 0
Author: Ghanshyam Anand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-10 08:12:49