Cześć!
Szukam informacji gdzie mógłbym przechowywać hardcode’wane stringi, niestety google nie pomogło. Nie chcę ich trzymać bezpośrednio w kodzie bo jak wiadomo utrudnia to potem modyfikację. Czy w Railsach albo samym Ruby’im jest coś takiego jak np. resources w ASP.Net lub string.xml dla androida?
Możesz utworzyć jakiś plik w folderze /lib np. my.rb, a w nim:
module My
MOJ_STRING_1 = "Alibaba"
MOJ_STRING_2 = "Sindbad"
...
end
a później w wielu miejscach aplikacji używać zgodnie z konstrukcją:
require 'my'
puts "#{My::MOJ_STRING_1} i 40 rozbójników"
Oczywiście MOJ_STRING_1 lepiej zastąpić czymś sensownym np.: ROZBOJNIK …ale to już wg własnego uznania.
jak już string zapisujesz w stałej, to warto go zamrozić, w ten sposób generuje się mniej obiektów i GC ma mniej pracy do ich sprzątania.
module My
MOJ_STRING_1 = "Alibaba".freeze
MOJ_STRING_2 = "Sindbad".freeze
...
end
Osobisćie polecam gem Configatron:
Warto wiedzieć że w Railsach jest moduł ActiveSupport::Configurable, który pozwala na zbudowanie samemu pliku konfiguracji, jeśli nie korzystacie z Railsów to jest dry-configurable, którego użycie wygląda bardzo podobnie. Configatron wygląda ciekawie ale wg mnie lepszym podejściem jest napisanie coś samemu, jeśli można to zrobić dość szybko niż pchać się w dodatkowe zależności.
słuszna uwaga z tym mrożeniem
Jeżeli to Ruby 2.3 to wystarczy na szczycie pliku dodać:
# frozen_string_literal: true
I nie trzeba wtedy mrozić każdego z plików z osobna.
Jak używasz tych samych stringów w kilku miejsca lepszym rozwiązaniem jest użyć słowika z zamrożonymi stringami, bo jeśli dobrze rozumiem, to frozen_string_literal
mrozi stringi dla każdego pliku z osobna.
Co myślicie o wykorzystaniu do tego celu I18n?
Zostaw w spokoju to I18n, niech służy do tego do czego zostało stworzone. Skąd takie pytanie i dlaczego powyższe rozwiązania Ci nie pasują?
Być może nie do końca Cię zrozumiałem, ale robiłem mały eksperyment:
one.rb
# frozen_string_literal: true
module One
STRING_ONE = 'String One'
puts "In one: #{STRING_ONE.object_id}"
end
two.rb
# frozen_string_literal: true
require_relative 'one'
x = One::STRING_ONE
puts "In two: #{x.object_id}"
puts "In two: #{One::STRING_ONE.object_id}"
puts "In two: #{'String One'.object_id}"
puts "In two: #{'String One'.object_id}"
puts "In two: #{"String One".object_id} double quoutes"
three.rb
# frozen_string_literal: true
require_relative 'two'
puts "In three: #{'String One'.object_id}"
x = "String One"
puts "In three: #{x.object_id} double quotes"
y = 'String One'
puts "In three: #{y.object_id} back to single quotes"
four.rb
# frozen_string_literal: true
require_relative 'three'
x = "String One"
puts "In four: #{x.object_id}"
wynik bez frozen literals
$ ruby four.rb
In one: 70273424681840
In two: 70273424681840
In two: 70273424681840
In two: 70273424679220
In two: 70273424678960
In two: 70273424670440 double quoutes
In three: 70273424668220
In three: 70273424668000 double quotes
In three: 70273424667640 back to single quotes
In four: 70273424664620
Wynik z frozen literals: true
$ ruby four.rb
In one: 70290113952320
In two: 70290113952320
In two: 70290113952320
In two: 70290113952320
In two: 70290113952320
In two: 70290113952320 double quoutes
In three: 70290113952320
In three: 70290113952320 double quotes
In three: 70290113952320 back to single quotes
In four: 70290113952320
Wydaje mi się to jest tak jak z atomamai w erlangu, dla konkretnego stringa jest allokowany obiekt w pamięci i wszystkie identyczne stringi są po prostu wskaźnikami na ten obiekt. Wyszukiwanie czy dany string już istnieje jako obiekt w pamięci powinno być dosyć szybką operacją.
W takim razie masz racje z tą flagą.