#ruby-on-rails #ruby-on-rails-5 #rails-activerecord
#ruby-on-rails #ruby-on-rails-5 #rails-activerecord
Вопрос:
У меня есть приложение Rails 2.3, которое я хочу обновить до Rails 5.
В некоторых моих моделях есть непостоянные атрибуты, я мог бы таким образом читать и записывать в свой контроллер:
r_v = Model.new
r_v[:count_all_bqu] = 0
r_v[:count_all_bsk] = 0
r_v[:count_all_bmd] = 0
Я изменил структуру, потому что по какой-то причине Rails 5 больше не обрабатывает ее.
Итак, я создал attr_accessors в своей модели:
attr_accessor :count_all_bqu
attr_accessor :count_all_bsk
attr_accessor :count_all_bmd
и заменил приведенные выше строки на эти:
r_v = Model.new
r_v.count_all_bqu = 0
r_v.count_all_bsk = 0
r_v.count_all_bmd = 0
Пока никаких проблем.
Но есть и такие вещи, как:
for r in Model.where(condition)
r_v["count_#{r.b_id}_erg_bst"] = 0
...
Как мне преобразовать «count_#{r.b_id}_erg_bst» в непостоянный атрибут?
Ответ №1:
Хотя я уверен, что есть другой ActiveModel
(RoR Guides, API — но это может быть не ActiveModel
просто аналогичный модуль) способ сделать это, с простым Ruby вы бы сделали это так:
r_v.send("count_#{r.b_id}_erg_bst=", 0)
По сути, вы «вызываете» метод count_..._erg...=
(метод, присваивающий локальную переменную, определенную с помощью attr_accessor
) с аргументом 0
.
Ибо r.bid == 'my'
это было бы то же самое, что и вызов r_v.count_my_erg_bst= 0
.
Обратите внимание, что это будет работать только в том случае, если что-то подобное attr_accessor :count_my_erg_bst
является частью вашего определения класса.
В противном случае вы можете сделать это более метапрограммным с помощью чего-то вроде rv.instance_eval { @count_my_erg_bst = 0 }
или, потому что вам нужна интерполяция строк rv.instance_eval " @count_#{r.bid}_erg_bst = 0 "
Обратите внимание на последствия для безопасности!Если r.bid
предоставлено пользователем, это может быть что-то вроде "a = 1; system("rm -rf /");"
или другой вредоносный код!
Комментарии:
1. Спасибо, Феликс! Хорошая идея, к сожалению, у меня это не совсем сработало, потому что я также хотел бы сделать сравнения и дополнения. Тем не менее, это привело меня в правильном направлении. Теперь я решил это так: я создал
attr_accessor :z_hash
в своей модели, которую я заполняю в контроллере парами ключ-значение:r_v.z_hash["count_#{r.b_id}_erg_bst"] = 0