Rails HABTM fields_for - проверяет, существует ли уже запись с таким именем - PullRequest
1 голос
/ 13 ноября 2010

У меня есть HABTM-отношение между моделями "Snippets" и "Tags". В настоящее время, когда я сохраняю фрагмент с несколькими тегами, каждый тег сохраняется как новая запись.

Теперь я хочу проверить, существует ли уже тег с таким именем, и если это так, я не хочу новую запись, только запись в snippets_tags существующей записи.

Как я могу это сделать?

snippet.rb:

class Snippet < ActiveRecord::Base
  accepts_nested_attributes_for :tags, :allow_destroy => true, :reject_if => lambda { |a| a.values.all?(&:blank?) }
  ...
end

_snippet.html.erb:

<% f.fields_for :tags do |tag_form| %>
  <span class="fields">
    <%= tag_form.text_field :name, :class => 'tag' %>
    <%= tag_form.hidden_field :_destroy %>
  </span>
<% end %>

1 Ответ

0 голосов
/ 14 ноября 2010

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

Мне пришлось изменить решение Райана Бейтса: Railscast "Ассоциация автозаполнения" , которая обрабатывает ассоциацию own_to, чтобы заставить ее работать с HABTM.

В моем фрагменте формы есть новое текстовое поле с именем tag_names, которое ожидает список тегов через запятую.

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

Просмотр "_snippet.html.erb"

<div class="float tags">
  <%= f.label :tag_names, "Tags" %>
  <%= f.text_field :tag_names %>
</div>

Модель "snippet.rb":

def tag_names
  # Get all related Tags as comma-separated list
  tag_list = []
  tags.each do |tag|
    tag_list << tag.name
  end
  tag_list.join(', ')
end

def tag_names=(names)
  # Delete tag-relations
  self.tags.delete_all

  # Split comma-separated list
  names = names.split(', ')

  # Run through each tag
  names.each do |name|
    tag = Tag.find_by_name(name)

    if tag
      # If the tag already exists, create only join-model
      self.tags << tag
    else
      # New tag, save it and create join-model
      tag = self.tags.new(:name => name)
      if tag.save
        self.tags << tag
      end
    end
  end
end

Это просто базовый код, не очень хорошо протестированный и нуждающийся в улучшении, но, похоже, он работает, и я рад, что нашел решение!

...