В Ruby on Rails есть лучший способ, чем использовать eval (), чтобы динамически обвинять этот jsonb? - PullRequest
0 голосов
/ 10 мая 2019

У меня есть некоторый jsonb в базе данных, и я хочу записать в атрибут динамически, я знаю путь к атрибуту, но это может быть любая глубина и любое имя атрибута.

Я знаю путьк атрибуту, однако, я нашел единственный способ написания этого динамического клика с помощью eval().

eval("self.some_json_column['an_array'][10]['a_different_array'][5]['color'] = 'blue'")
self.save

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

Однако я знаю, что eval() является последним сценарием и был задан вопрос, возможно ли построить путь и записать (в данном случае это цветовой атрибут json)) динамически без использования eval()

Спасибо.

1 Ответ

4 голосов
/ 10 мая 2019

Вы можете сократить свой путь через Hash, который возвращается self.some_json_column

*path, target = ['an_array',10,'a_different_array',5,'color']
node = path.reduce(self.some_json_colum, &:[])
node[target] = 'blue' if node  

Нет обработки ошибок, если какая-либо часть пути неверна

Вы также можете посмотреть dig в зависимости от версии ruby, например,

node = self.some_json_column.dig(*path)
node[target] = 'blue' if node

Это вернет nil, если какая-либо часть пути не совпадает

Пример:

h = {
  'an_array' => [0,1,2,3,4,5,6,7,8,9,
    {'a_different_array' => [1,2,3,4,5, {'color' => 'orange'}]}
  ]
}

*path,target  = ['an_array',10,'a_different_array',5,'color']

h.dig(*path)[target] = 'blue'

h
#=> {"an_array"=>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
#     {"a_different_array"=>[0, 1, 2, 3, 4, 
#       {"color"=>"blue"}
#     ]}
#   ]}
...