开发者

Rails HABTM fields_for – check if record with same name already exists

开发者 https://www.devze.com 2023-01-24 17:42 出处:网络
I have a HABTM-relation between the models \"Snippets\" and \"Tags\". Currently, when i save a snippet with a few tags, every tag is saved as a new record.

I have a HABTM-relation between the models "Snippets" and "Tags". Currently, when i save a snippet with a few tags, every tag is saved as a new record.

Now i want to check if a tag with the same name already exists and if that´s the case, i don´t want a new record, only an entry in snippets_tags to the existing record.

How can i do this?

snippet.rb:

class Snippet < ActiveRecord::Base
  accepts_nested_attr开发者_StackOverflow中文版ibutes_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 %>


Ok, i´m impatient… after a while i found a solution that works for me. I don´t know if this is the best way, but i want to show it though.

I had to modify the solution of Ryan Bates Railscast "Auto-Complete Association", which handles a belongs_to-association to get it working with HABTM.

In my snippet-form is a new text field named tag_names, which expects a comma-separated list of tags.

Like Ryan, i use a virtual attribute to get and set the tags. I think the rest is self-explanatory, so here´s the code.

View "_snippet.html.erb"

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

Model "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

This is just the basic code, not very well tested and in need of improvement, but it seemingly works and i´m happy to have a solution!

0

精彩评论

暂无评论...
验证码 换一张
取 消