Теория
При использовании nested attributes и fields_for очень часто нам нужно добавлять новый элемент в форму при помощи javascript.
Руководствуясь принципом DRY рекомендую использовать следующее решение. Я знаю, что это общеизвестная техника, но как обычно бывает большинство всё-равно изобретает свои решения, ну и во всяком случае на русском языке таких примеров я не видел.
В application_helper.rb я уже добавил следующий код:
def add_object_link(name, form, object, partial, where) html = render(:partial => partial, :locals => {:form => form}, :object => object) link_to_function name, %{ var new_object_id = new Date().getTime() ; var html = jQuery(#{html.to_json}.replace(/index_to_replace_with_js/g, new_object_id)).hide(); html.appendTo(jQuery("#{where}")).slideDown('slow'); } end
Это основной helper, который генерирует html нового элемента при помощи javascript, где:
name — заголовок ссылки
form — объект формы form_for
object — объект элемента, который нужно добавить
partial — название шаблона, который генерирует html для отображение добавляемого элемента
where — id html-контейнера на странице
Пример
Допустим у нас есть рубрика (Rubric), в которую нужно добавить какие-то характеристики (Anchor)
app/models/rubric.rb
class Rubric < ActiveRecord::Base has_many :anchors accepts_nested_attributes_for :anchors, :allow_destroy => true end
app/models/anchor.rb
class Anchor < ActiveRecord::Base belongs_to :rubric end
app/view/admin/rubrics/edit.html.haml
- form_for @rubric do |f| %h3 Анкоры != add_object_link('<img src="/images/icons/add.png" />', f, Anchor.new, "anchor", "#anchors") %ul#anchors - @rubric.anchors.each do |anchor| != render :partial => "anchor", :locals => {:form => f, :anchor => anchor} != f.submit("Сохранить анкоры")
app/view/admin/rubrics/_anchor.html.haml
- raise ArgumentError unless defined?(form) - raise ArgumentError unless defined?(anchor) %li.anchor - form.fields_for :anchors, anchor, :child_index => (anchor.new_record? ? "index_to_replace_with_js" : nil) do |anchor_form| != anchor_form.text_field :title - if anchor_form.object.new_record? %a{:href => "#", :onclick => "jQuery(this).parent('.anchor').remove(); return false;"} %img{:src => "/images/icons/delete.png"} - else != anchor_form.check_box '_destroy' != anchor_form.label '_destroy', 'удалить?'
p.s. Ни на что не претендую, просто хочу обратить всё большее количество людей в свою веру =)