Применение ограничения уникальности во вложенной форме - PullRequest
3 голосов
/ 25 февраля 2010

Я стараюсь не бороться со значениями по умолчанию и использую встроенную поддержку Rails для вложенных атрибутов (от http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes).. Я маркирую вещи тегами, и все работает отлично, и для каждой вещи, которая у меня есть форма с вложенным полем, которое создает новый тег по имени. Проблема в том, что мне нужно убедиться, что каждый тег имеет уникальное имя. Вместо создания нового тега, если пользователь вводит имя уже существующего, Мне нужно создать ассоциацию с этим уже существующим тегом. Как мне это сделать?

Ответы [ 2 ]

1 голос
/ 04 апреля 2010

В вашем классе Thing определите метод tags_attributes = для переопределения по умолчанию и используйте Tag.find_or_create

def tags_attributes=(attributes)
  attributes.each do |attr|
    Tag.find_or_create_by_name(attr[:name])
  end
end

Не уверен, как будет выглядеть хеш атрибутов, но вы поняли.

1 голос
/ 25 февраля 2010

Возможно, есть лучший способ сделать это, но это лучшее из того, что я могу придумать на данный момент.

В ассоциации has_many (: through) accepts_nested_arguments_for использует присвоение виртуальному атрибуту #{association}_attributes, чтобы применить магию. Он ожидает массив хэшей, где каждый хеш содержит ключи атрибутов и их значения. Любые хэши с идентификатором будут обновлены (или удалены, если есть ключ :_delete со значением true). Любые хэши, в которых отсутствует идентификатор, будут использоваться для создания новых элементов этой ассоциации. Таким образом, ключ заключается в том, чтобы перехватить вызов tags_associations= и проверить все хэши, в которых отсутствуют идентификаторы для существующего тега с тем же значением имени, и заменить его записью, которую tags_attributes будет использовать для установления связи с существующим тегом , N.B. для отношений has_one и own_to tag_attributes ожидает один хеш. Код будет похож, но намного проще.

class Thing < ActiveRecord::Base
  has_many :tags, :through => :taggings
  has_many :taggings
  accepts_nested_attributes_for :tags

  def tags_attributes_with_recycling=(attributes)
    existing_attributes = attributes.reject{|attribute| attribute[:id].nil?}
    new_attributes = attributes - existing_attributes
    new_and_recycled_attributes = new_attributes.map { |attribute| 
      tag_id = Tag.find_by_name(attribute[:name]).id
      tag_id ? {:id => tag_id) : attribute
    }
    tags_attributes_without_recycling= (existing_attributes + new_and_recycled_attributes)
  end

  alias_method_chain :tags_attributes=, :recycling
end

Это не проверено, поэтому никаких гарантий. Но это должно, по крайней мере, помочь вам найти решение.

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