Ruby Best Practice - Динамические атрибуты против хэша для приложения RoR
Я разрабатываю модель, которая содержит параметры конфигурации для параметров сервера. Количество и тип серверных опций меняются, и мне нужны сведения о плюсах и минусах двух способов сделать это. Я делаю это отдельно от базы данных рельсов ActiveRecord. Все мои взаимодействия с базой данных будут происходить вручную с файловой системой.
Во-первых, наличие модели для динамического создания атрибутов, необходимых для каждого указанного сервера. (пока это возможно... Я никогда не делал это раньше)
Во-вторых, создание единого хэша, который имеет ключи параметров сервера и значения параметров сервера.
Я думаю, что второе было бы легче реализовать, но я не уверен, что это правильный путь? Похоже, чище с динамическими атрибутами.
Есть ли эмпирическое правило для этого?
2 ответа
Сделал что-то для тебя.
Вот как это будет работать.
s = Settings.new(SettingsFileManager.new(some_file))
s.ip # returns whats in the file.
s.ip = 10.0.0.1 # overrides the new value.
Я еще не написал, как он взаимодействует с файлами, поэтому вам придется написать правильный SettingsFileManager.
Во всяком случае, это должно дать вам хорошую основу для начала. Но я написал это в первую очередь для проверки того, что я знаю о рубине. Так как он использует некоторые полусложные вещи.
Разместил его на github тоже с некоторыми тестами.
class Settings
attr_accessor :settings
def initialize(file_writer)
@file_writer = file_writer
read_settings_to_new_hash
end
def read_settings_to_new_hash
@settings = fabricate_hash
@settings.replace(@file_writer.read_keys)
end
def fabricate_hash
InterceptedHash.new( &hash_saved_proc )
end
def hash_saved_proc
Proc.new do |key, value|
@file_writer.write_key(key, value)
end
end
def method_missing(m, *args, &block)
if @settings.has_key?(m) || args[0]
if args[0]
@settings[m.to_s.sub("=","").to_sym] = args[0]
else
@settings[m]
end
else
raise "unknown setting"
end
end
end
# Not implemented. This should continue the logic to interact with whatever you want.
class SettingsFileManager
def initialize(file)
@file = file
end
# write the key and its value somewhere.
def write_key(key, value)
puts 'write_key', key, value
end
# should return hash of keys.
def read_keys
puts 'read_keys'
Hash.new
end
end
class InterceptedHash < Hash
def initialize(&block)
super
@block = block
end
def store(key, value)
super(key, value)
@block.call(key, value)
end
def []=(key, value)
store(key, value)
end
end
Знаете ли вы о функциональности магазина в Rails?
http://api.rubyonrails.org/classes/ActiveRecord/Store.html
В основном вы могли бы написать что-то вроде этого:
class Server < ActiveRecord::Base
store :options
end
Вам также необходимо создать новую миграцию со столбцом параметров и ввести текст.
Теперь вы можете добавлять и считывать значения в хранилище параметров следующим образом:
server_instance.options[:ip] = '10.0.1.7'
server_instance.options[:ip] # returns the IP.
Вы также можете убрать это, добавив опцию доступа к вызову магазина.
class Server < ActiveRecord::Base
store :options, accessors: [ :ip, :port ]
end
Теперь вы можете использовать ip & port как обычные атрибуты.
server_instance.ip = '10.0.1.7'
server_instance.ip # returns the IP.