Модель before_save не использует обновленный порядок множественного выбора, поступающий от params / controller - PullRequest
0 голосов
/ 10 апреля 2020

В форме у меня есть выпадающий список с множественным выбором, который я могу отсортировать вручную. Когда я отправляю форму на редактирование, я получаю в параметрах следующее:

"article" =>{"tag_ids"=>["", "4", "1", "2"]}

Что именно я хочу, а не 1, 2, 4. Модель я обновляю порядковый номер. Я не могу получить новый порядок tag_id из параметра. Когда я вызываю article_tags, я получаю порядок таблицы, а не тот, который указан в параметрах. Я предполагаю, что это потому, что не было никаких изменений в tag_ids (те же записи, другой порядок). Есть ли способ получить доступ к этому порядку в самой модели?

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

Контроллер:

def update
 if @article.update(article_params)
  redirect_to articles_path
 end
end

def article_params
 params.require(:article).permit(:title, tag_ids: [])
end

Модели:

class Article
 has_many: :article_tags
 has_many: :tags, through: :article_tags

 before_save: :order

 def order
  self.article_tags.each_with_index do |i, idx|
   i.update_attribute(:ordinal, idx) 
  end
 end
end

class ArticleTag
 belongs_to: :article
 belongs_to: :tag
end

Таблицы

articles
 id  |   title
------------------
  1  |  Testing

tags
 id  |   name
------------------
  1  |  Business
  2  |  Education
  3  |  Health
  4  |  Social

article_tags
 id  |   article_id  |  tag_id  | ordinal
------------------------------------------
  1  |       1       |     1    |   2
  2  |       1       |     2    |   3
  3  |       1       |     4    |   1

1 Ответ

1 голос
/ 10 апреля 2020

Вы можете сделать это, переопределив метод установки tag_ids=, созданный has_many: :tags, through: :article_tags.

class Article
  # ...
  def tags_ids=(ids)
    ids.reject(&:blank?).each_with_index do |id, index|
      article_tag = self.article_tags.find_or_intialize_by(tag_id: id)
      article_tag.update(
        ordinal: index
      )
      article_tag.where.not(tag_id: ids).destroy_all
    end
  end
end
...