Яндекс.Метрика

    Ни о чём

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

    Теория


    При использовании 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. Ни на что не претендую, просто хочу обратить всё большее количество людей в свою веру =)