[RoR] Gdzie trzymać hardcode'wane stringi?

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. :slight_smile:

1 Like

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
1 Like

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 :slight_smile:

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.

1 Like

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ą.