我正在使用Rails的accepts_nested_attributes_for方法取得了巨大的成功,但是如果记录已经存在,我如何才能创建新记录?
我找到了这篇文章accepts_nested_attributes_for with find_or_create?,但在我的案例中似乎没有用。
我在软件包和许可证之间存在多对多的关系。表中应该只有一个许可证实例,例如:我不应该有两个名为“Awesome”的许可证
所需的功能是,当我创建包时,将许可证名称作为属性传递,如果名称尚不存在,则创建新许可证或在现有许可证(使用提供的名称)之间创建关联包裹。
以下是我的模型的样子:
class Package < ActiveRecord::Base
has_and_belongs_to_many :licenses, :autosave => true
accepts_nested_attributes_for :licenses
end
class License < ActiveRecord::Base
attr_accessible :name
has_and_belongs_to_many :packages
validates :name, :presence => true
end
答案 0 :(得分:0)
如果'name'确实是用于创建它的唯一属性,如果它尚不存在,那么你可以通过Package
类和虚拟属性的回调来实现:
class Package < ActiveRecord::Base
has_and_belongs_to_many :licenses, :autosave => true
before_create :set_license_from_name
attr_accessor :license_name
protected
def set_license_from_name
self.licenses << Licence.find_or_create_by_name(self.license_name)
end
end
然后你可以在新的Package对象中传递licence_name
作为属性,例如使用text_box:
<%= form_for @package do |f| %>
<%= f.text_field :license_name %>
<% end %>
可能不是世界上最好的用户界面。相反,您可能希望人们能够从下拉框中选择现有许可,或者键入新名称。有accepts_nested_attributes_for
有用的地方:
class Package < ActiveRecord:Base
has_and_many :licenses
accepts_nested_attributes_for :licenses, :reject_if => :all_blank
end
class PackagesController < ApplicationController
def new
@package = Package.new
@package.licenses.build
@licenses = License.all
end
end
在视图中:
<%= form_for @package do |f| %>
License:
<%= f.collection_select :license_id, @licenses, :id, :name, :include_blank => true %>
or create a new one:
<%= f.fields_for :licenses do |l| %>
<%= l.text_field :name %>
<% end %>
<% end %>
你必须在控制器的创建动作中做更多的工作才能使它工作,但它不应该太难。
答案 1 :(得分:0)
我遇到了类似的问题,并使用回调挂钩解决了这个问题。在我的情况下,我有一个状态模型和一个人模型。我想让用户在状态更新中标记多个人(人物),只需键入一个名称并创建一个新人(如果匹配的人不存在,这些人不会映射到用户,顺便说一下,它只是供私人使用)
class Person < ActiveRecord::Base
has_and_belongs_to_many :statuses
end
Class Status < ActiveRecord::Base
has_and_belongs_to_many :people
accepts_nested_attributes_for :people
before_save :get_people
def get_people
self.people.map! do |person|
Person.find_or_create_by_name(person.name)
end
end
end