Как назначить хеш-значения объекту при создании каждой пары ключ-значение в качестве нового объекта в Ruby - PullRequest
0 голосов
/ 05 апреля 2019

У меня есть объект person, который получает большой хэш информации о человеке после вызова веб-службы (около 400 пар ключ-значение).Каждый из элементов в хэше несколько отличается, и должен обрабатываться по-разному перед отображением для пользователя (например, преобразование значения метки времени, обработка нулей или преобразование текста и т. Д.) И т. Д., И сами ключи также важны в другом месте и должны быть'переведено' из списка фиксированных сопоставлений.

В настоящее время к хэшу атрибутов обращаются непосредственно в представлении Rails, а затем возвращаемое значение очищается во вспомогательном средстве, как в

<%= clean_up(person.attributes["some_strangly_formatted_name"]) %>
* 1005.* или
<%= show_timestamp(person.attributes["some_nonhuman_time"]) %>

Я пытаюсь выяснить, как динамически присваивать каждое из этих значений объекту персонажа, а также создавать каждый из атрибутов как свой собственный объект другого класса (например, Атрибут) переместить связанное поведение туда, поскольку количество и сложность вспомогательных методов выходит из-под контроля.

В идеале в представлении я мог бы вызвать person.some_timestamp, и это вернуло бы читаемое человеком время или person.nameи вернуть строку имени человека

Я попытался назначить переменные, как показано здесь, ноt кажется, что атрибут должен быть предварительно определен для объекта, и я пытаюсь избежать 400 attr_accessors, а также пытаюсь учесть возможность добавления новых атрибутов Динамически устанавливать атрибут объекта Ruby Имея хеш, задайте свойства объекта в Ruby СУХОЙ способ присвоения хеш-значения объекту

нерабочий метод выглядит как

  def process_attributes(attributes)
    attributes.each {|k,v| public_send("#{k}=", v)}
  end

Как мне достичь этой цели?В более общем смысле, имеет ли эта стратегия смысл?

1 Ответ

0 голосов
/ 06 апреля 2019

Редактировать

Я начал риффить ответ ниже, но у меня возникло мнение, что "обычно есть встроенный способ сделать это в 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'....>

Надеюсь, что это приведет к чему-то полезному для вас.

...