Как сделать обновление на вложенной форме в ruby? - PullRequest
0 голосов
/ 29 ноября 2018

В моем приложении есть объект «Пользователь», у которого есть один талант.Талант - это вид, которым может быть пользователь в моей системе (модель, фотограф, видеомейкер, клиент)

#user.rb

class User < ApplicationRecord
  has_one :talent, dependent: :destroy

Талант принадлежит пользователю и имеет много талантов.

#talent.rb
class Talent < ApplicationRecord
  belongs_to :user
  has_many :talent_talent_abilities, dependent: :destroy
  has_many :talent_abilities, through: :talent_talent_abilities

Итак, мы можем создать, например, TalentAbility, которая принадлежит Talent.Например:

TalentType.create!([
  {name: "Model", is_model: true, is_photo: false, is_makeup: false, is_hair: false},
  {name: "Photographer", is_model: false, is_photo: true, is_makeup: false, is_hair: false

])
TalentAbility.create!([
  {name: "Scuba diving", requires_description: false, talent_type_id: 1}
  {name: "River rafting", requires_description: false, talent_type_id: 1},

Я хочу добавить вид, в котором пользователь, основываясь на вашем TalentType, редактирует свой профиль, с множеством флажков, где он может щелкнуть, например, «Scuba Diving -> true».""Сплав по реке -> ложь".

Мой вопрос: как лучше всего обновить эти отношения на моем контроллере?Сначала удалите все способности TalentTalentAbility, которые принадлежат этому таланту, а затем добавьте все, основываясь на моей форме?

#profiles_controler.rb
def update
 ##delete all the entities
 TalentTalentAbility.where(talent: u.talent).each do |tt| 
   tt.destroy
 end

 ##some code to add the new relationships

end

Спасибо

Ответы [ 2 ]

0 голосов
/ 30 ноября 2018

Проблема с принятым ответом:

Скажем, у вас есть пользователь с 5 талантами, и он выбирает, что он выучил шестой.Если вы выберете способ .destroy_all, вот что произойдет:

  • 5 отдельных, последовательных DELETE операторов, отправленных в БД
  • 6 отдельных, последовательных INSERTоператоры, отправленные в БД

Правильное решение для такой проблемы - визуализировать флажки с соответствующими им идентификаторами и использовать атрибут _destroy (подробнее здесь ).

Короче говоря, если вы получите хеш (вам может понадобиться очистить его после того, как вы получите его из формы, извините, но у меня нет ничего под рукой, чтобы дать вам пример AZ), содержащийчто-то вроде этого:

..., talent_talent_abilities_attributes: [
       {id: 1, _destroy: true}, 
       {id: nil, talent_ability_id: 1}
       {id: 2, talent_ability_id: 2, some_attribute: "value"}
]

И вы сохраняете своего пользователя, ActiveRecord будет:

  • Выпустить один оператор DELETE для первого элемента.
  • Выпустить один *Оператор 1028 * для второго элемента.
  • В зависимости от того, загружены ли ваши записи и изменилось ли что-то для способности с id: 2, он может выдавать или не выдавать оператор UPDATE.

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

0 голосов
/ 29 ноября 2018

Я делал нечто подобное в прошлом, и это сработало очень хорошо.Я бы переместил это в модель, чтобы у вас было что-то вроде этого.

class User < ActiveRecord::Base
  ActiveModel::Dirty # if you need to track changes and only delete on attrs changed
  before_save :update_talents

  # ...

  private

  def update_talents
    talents.destroy_all if talents_changed?
  end
end

Тогда новые таланты будут сохранены с данными формы.Кроме того, таким образом, ваш контроллер не будет бесполезным.

Однако вы должны быть осторожны, чтобы убедиться, что именно такое поведение вы хотите.Вы можете добавить в чек только обновление, если таланты также меняются с ActiveModel::Dirty.Могу проверить синтаксис метода *_changed для ассоциаций.

Предостережение

Я склонен защищать этот подход, потому что моя вложенная форма использоваласьПозиционирование JS для повторного заказа товаров в нем.Там может быть более разумный подход.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...