У художников много событий. События имеют много художников. Соединение между этими двумя моделями называется Performances.рельсы проверяют вложенные атрибуты
В настоящее время форма Event создает Performance, но создает нового исполнителя для каждого Artist, добавленного в форму Event.
Я хотел бы форму событий на:
- Validate, что артист может быть добавлен только к событию, когда
- Если артист с таким же именем уже существует в таблице художников, создать ассоциацию в соединительной таблице (выступления), но не создаю другой художник
- Если артист с таким именем еще не существует, создайте его и производительность
Я пытался добавить ing 'validates_uniqueness_of: name' to artist.rb, но это предотвращает сохранение события. Соединение (производительность) должно быть создано, если оно еще не существует, и художник должен быть создан, если он еще не существует, но существование художника не должно препятствовать созданию соединения/ассоциации.
event.rb
validates_presence_of :name, :location
has_many :performances, :dependent => :destroy
has_many :artists, :through => :performances
accepts_nested_attributes_for :artists, :reject_if => proc {|a| a['name'].blank?}, :allow_destroy => true
artist.rb
has_many :performances
has_many :events, :through => :performances
perfomance.rb
belongs_to :artist
belongs_to :event
events_controller.rb
def create
@event = Event.new(params[:event])
respond_to do |format|
if @event.save
flash[:notice] = 'Event was successfully created.'
format.html { redirect_to(admin_events_url) }
format.xml { render :xml => @event, :status => :created, :location => @event }
else
format.html { render :action => "new" }
format.xml { render :xml => @event.errors, :status => :unprocessable_entity }
end
end
end
_form.html.erb
<% form_for([:admin,@event]) do |f| %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :location %><br/>
<%= f.text_field :location %>
</p>
<p>
<%= f.label :date %><br />
<%= f.date_select :date %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description %>
</p>
<% f.fields_for :artists do |builder| %>
<%= render 'artist_fields', :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add Artist", f, :artists %></p>
<p>
<%= f.submit 'Submit' %> <%= link_to 'Cancel', admin_events_path %>
</p>
<% end %>
artist_fields.html.erb
<p class="fields">
<%= f.label :name, "Artist"%><br/>
<%= f.text_field :name %>
<%= link_to_remove_fields "remove", f %>
</p>
Я исследовал то, что вы предложили, но не можете понять, как Начало. – shalako
Поэтому мне нужно добавить настраиваемый метод в модель событий и каким-то образом включить find_or_create_by_name. Мне нужно удалить accepts_nested_attributes_for? Нужно ли использовать виртуальные атрибуты, как предлагает Райан Бэйтс в Railscasts # 102? Before_save, after_save? Я не нашел хорошего примера того, как эти вещи сочетаются друг с другом. – shalako
Я добавил пример метода artist_attributes = выше. Я думаю, вам все равно нужно accepts_nested, если вы хотите использовать «f.fields_for: artist» –