validates_uniqueness_of polymorphi c ассоциация не работает для действия create, работает для редактирования при наличии ассоциации - PullRequest
0 голосов
/ 06 мая 2020

У меня есть модель статей и событий и дополнительная модель полиморфизма c item_references. Я использую это, чтобы взять конкретный c элемент (item_unique_id) и извлечь статьи или события, которые к нему относятся.

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

Я использую validates_uniqueness_of в модели item_reference, и это успешно блокирует обновления с повторяющимися item_unique_id, но только если отредактированная статья уже связан с item_reference. Он не работает для метода создания новой статьи, который позволяет мне сохранить статью с повторяющимися идентификаторами item_unique_ids.

Мне интересно, как это преодолеть. Нужно ли мне каким-то образом передавать пустую или фиктивную ссылку item_reference во время функции new / create, чтобы ассоциация существовала?

Вот соответствующие биты моего кода:

Модели:

class Article < ApplicationRecord
  has_many :item_references, as: :item_referenceable
  accepts_nested_attributes_for :item_references, allow_destroy: true,
   :reject_if => proc { |att| att[:item_unique_id].blank? }
end

class ItemReference < ApplicationRecord
  belongs_to :item_referenceable, polymorphic: true

  validates_uniqueness_of :item_unique_id,  scope: [:item_referenceable_type, 
      :item_referenceable_id],
      allow_nil: true,
      message: 'cannot be duplicated'
end

Контроллер статьи:

class Admin::ArticlesController < ApplicationController
  before_action :set_article, only: [:show, :edit, :update, :destroy]

  def new
    @article = Article.new
    5.times { @article.item_references.build }
  end

  def edit
    @item_referenceable = @article
    @item_references = @item_referenceable.item_references
    @item_reference = ItemReference.new
    5.times { @article.item_references.build }
  end

  def create
    @article = Article.new(article_params)
    if @article.save
      redirect_to admin_article_path(@article), notice: 'Article was successfully created.'
    else
      render :new
    end
  end

  def update
    if @article.update(article_params)
      redirect_to admin_article_path(@article), notice: 'Article was successfully updated.' 
    else
      render :edit
    end
  end

  private

    def set_article
      @article = Article.find(params[:id])
    end

    def article_params
      params.require(:article).permit(:title,
                                      :content,
                                      item_references_attributes: [:item_unique_id,
                                                                   :id, :item_reference_id,
                                                                   :item_reference_type])
    end

end

Контроллер ссылки на элемент:

class Admin::ItemReferencesController < ApplicationController

  before_action :load_item_referenceable

  def new
    @item_reference = @item_referenceable.item_references.new
  end

  def create
    @item_reference = @item_referenceable.item_references.new(item_referenceable_params)
    if @item_reference.save
      redirect_to [:admin, @item_referenceable], notice: "Item Reference created"
    else
      render :new
    end
  end

  private

  def load_item_referenceable
    resource, id_or_slug = request.path.split('/')[2,3]
    if id_or_slug.to_i > 0
      @item_referenceable = resource.singularize.classify.constantize.find(id_or_slug)
    else
      @item_referenceable = resource.singularize.classify.constantize.slug_find(id_or_slug)
    end
  end

end

Просмотр статьи - частичная форма:

<%= form_for [:admin, @article] do |f| %>

  <div class="field">
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.label :content %><br />
    <%= f.text_area :content %>
  </div>

  <h2>Item References</h2>

  <%= f.fields_for :item_references do |ref| %>
    <div>
      <%= ref.text_area :item_unique_id %>
    </div>
  <% end %>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Дальнейшие исследования показывают следующие два вопросы на странице rails github. Мне интересно, должен ли я сделать вывод, что то, что я пытаюсь сделать, невозможно с текущим подходом?

https://github.com/rails/rails/issues/1572 https://github.com/rails/rails/issues/20676

...