自动完成与嵌套属性和多对多关系的关联

时间:2012-05-30 09:42:30

标签: ruby-on-rails ruby-on-rails-3

我遵循自动完成协会Railscast将'艺术家'添加到我的'版本'中。一切似乎都很好用,但我注意到它每次创建一个新的艺术家,而不是使用现有的艺术家,如果通过自动完成选择。

与railscast不同,我使用多对多的关系,艺术家也被接受为发布版本的嵌套属性,所以我知道这个问题可能与其中一个或两个有关。

以下是我的模型和相关观点。在我看来,self.artist = Artist.find_or_create_by_name(name) if name.present?行没有被使用。我认为这是因为我有f.autocomplete_field :name而不是f.autocomplete_field :artist_name但是当我改为那时我得到了一个no方法错误!

有人可以帮忙吗?

class Release < ActiveRecord::Base
  has_many :artist_releases
  has_many :artists, :through => :artist_releases

  accepts_nested_attributes_for :artists, :reject_if => lambda { |a| a[:name].blank? }
  accepts_nested_attributes_for :artist_releases

  def artist_name
   artist.try(:name)
  end

  def artist_name=(name)
   self.artist = Artist.find_or_create_by_name(name) if name.present?
  end      
end

class ArtistRelease < ActiveRecord::Base
  belongs_to :artist
  belongs_to :release
end

class Artist < ActiveRecord::Base
  has_many :artist_releases
  has_many :releases, :through => :artist_releases  
end


#Release Form
<%= form_for(@release) do |f| %>
<%= f.text_field :title, :class => "text" %>
    <%= f.fields_for :artists do |builder| %>
    <%= render 'artist_fields', :f => builder %>
    <% end %>
    <p><%= link_to_add_fields "Add Artist", f, :artists %> </p>
<% end %>

#Artist Fields
<p>
<%= f.label :artist_name, "Artist" %><br />
<%= f.autocomplete_field :name, autocomplete_artist_name_releases_path, :id_element => '#artist_id', :class => "text" %>
</p>

1 个答案:

答案 0 :(得分:0)

你应该把

<%= f.autocomplete_field :artist_name, autocomplete_artist_name_releases_path, :class => "text" %>

其中f是发布形式。但由于你的发布模型has_many :artists

,这将分配给Release#artist(只有一个),这应该是未定义的

你能做的是在逗号分隔列表中允许许多名字。请注意,我们直接将其放在发布表单中,不需要嵌套属性。

#Release Form
<%= form_for(@release) do |f| %>
<%= f.text_field :title, :class => "text" %>
...
<%= f.autocomplete_field :artist_names, autocomplete_artist_name_releases_path, :class => "text", 'data-delimiter' => ',' %>
<% end %>

在发布模型中,不需要嵌套属性。

class Release < ActiveRecord::Base
  has_many :artist_releases
  has_many :artists, :through => :artist_releases

  attr_accessor :artist_names 
  def artist_names=(names)
    self.artists = names.split(',').map { |name| Artist.find_or_create_by_name(name.strip) }
  end 
end

您可以使用嵌套属性进行解决,但只有在您有多个艺术家要填写的字段时才会推荐。