Как стать автором
Обновить

Rails. Добавление элемента при использовании nested attributes

Время на прочтение2 мин
Количество просмотров1.2K

Теория


При использовании 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. Ни на что не претендую, просто хочу обратить всё большее количество людей в свою веру =)
Теги:
Хабы:
+6
Комментарии2

Публикации

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн