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ądachCard.COLOURS
, a nie coś kludgy jakCard.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?
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ć.
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
.
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"]
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
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.
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.
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
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
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');
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)
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.
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:
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
Nie zapomnij zrestartować serwera
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