Если «имя» действительно является единственным атрибутом лицензии, который будет использоваться для его создания, если он еще не существует, то вы можете сделать это с помощью обратного вызова класса 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
Тогда вы можете просто передать licence_name
в качестве атрибута для нового объекта Package, например, используя 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 %>
Вам нужно будет проделать немного больше работы в действии create контроллера, чтобы заставить его работать, но это не должно быть слишком сложно.