Редактировать
Я начал риффить ответ ниже, но у меня возникло мнение, что "обычно есть встроенный способ сделать это в Ruby / Rails", я бы проверилSimpleDelgator, и если кто-то захочет использовать его для создания модели, подобной PersonAttributor < SimpleDelgator
, и выполнить в ней ваши преобразования, я бы ее поддержал.
Не уверен, что это направление, в котором выищите, но вы можете сделать что-нибудь с сериализацией JSON.Если вы используете Postgres, вы можете использовать тип столбца JASONB и сохранить данные в формате JSON, которые можно запрашивать напрямую.Но простая сериализация может произойти так:
person.attributes = {'one' => 'something', 'two' => 'some_other_thing'}.to_json
=> "{\"one\":\"something\",\"two\":\"some_other_thing\"}"
person.save
JSON(person.attributes)
=> {"one"=>"something", "two"=>"some_other_thing"}
JSON(person.attributes)["one"]
=> "something"
Это очень простой, не поддающийся проверке пример.Он помещает все ваши пары ключ / значение в столбец, не создавая кучу attr_accessors.Вы можете выполнить очистку, когда хэш впервые назначен человеку.
Это не распространяется на вашу идею переместить эти атрибуты в свои собственные классы.Если вы хотите создавать эти объекты на лету, я не уверен, что вы спасаете себя, делая это.Если вы хотите, чтобы они были доступны как методы, вы могли бы использовать OpenStruct каким-либо образом, вот один из них:
В вашей модели персонажа вы можете использовать метод:
class Person < ApplicationRecord
...
def attr_object
OpenStruct.new(self.attributes)
end
...
Затем вы получитеобъект со всеми вашими ключами в качестве методов и вашими значениями как возвращаемыми этими методами ...
os_obj = person.attr_object
=> #<OpenStruct one='something', two='something_else'....>
Теперь у вас есть объект, который дает вам методы one
и one=
.Вы можете применить все свои преобразования к этому объекту, используя методы ...
os_obj.one
=> 'something'
os_obj.one = 'something new'
=> 'something new'
Вы можете создать модель, которая наследуется от Person и создает объект OpenStruct.Он также может сохранить обновленные пары ключ / значение из объекта OpenStruct, сериализовав его в JSON:
person.attr_store = os_obj.to_h.to_json
"{\"one\":\"something new\"....}"
new_obj = Openstruct.new(JSON(person.attr_store))
=> #<OpenStruct one='something_new', two='something_else'....>
Надеюсь, что это приведет к чему-то полезному для вас.