У меня есть модель статей и событий и дополнительная модель полиморфизма 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