Using Nested Form with Simple Form


I would like to introduce you guys a Rails gem for conveniently manage multiple nested models in a single form. It does so in an unobtrusive way through jQuery.

For now this gem only works with Rails 3.

Add it to your Gemfile then run bundle to install it.

    gem 'nested_form', :git => 'git://github.com/ryanb/nested_form.git'

For Rails 3.1, the only thing you have to do is just require the js file in your application.js

    # application.js
    //= require jquery
    //= require jquery_ujs
    //= require nested_form

So we can get started with nested form now, we can imagine that we have a Product model that has_many :photos. To be able to use this function, you need to add some configuration to your Product model, ad we have Photo model which is to store the photos.

    class Photo
      include Mongoid::Document

      mount_uploader :data, PhotoUploader

      field :data, type: String

      embedded_in :product

    end
    class Product
      include Mongoid::Document
      include Mongoid::Timestamps

      embedded_many :photos, cascade_callbacks: true

      accepts_nested_attributes_for :photos,
                                    reject_if: proc { |attributes| attributes['data'].blank? },
                                    allow_destroy: true
    end

If you don't have the accepts_nested_attributes_for settings for photos, you'll get a Missing Block Error.

We also use SimpleForm to make our form simpler, in this Git repo, It was implemented to use simple_nested_form_for for SimpleForm support. But this feature is not yet in a Gem release, so you can use this git repo.

Here is the form.

    = simple_nested_form_for resource, :url => products_path do |f|
      = f.input :name
      
      - resource.photos.each do |photo|
        = f.simple_fields_for :photos, photo do |p|
          .photo
            = label_tag ''
            = image_tag photo.data
            %br/
            = label_tag ''
            = p.link_to_remove 'delete this image'
            = p.input :data_cache, :as => :hidden
            
      = f.simple_fields_for :photos, resource.photos.build do |p|
        = p.input :data, :as => :file
        = p.input :data_cache, :as => :hidden
        = p.link_to_remove 'remove'
      = f.link_to_add 'Add', :photos

      .actions
        = f.submit 'Save changes'
        = button_tag 'Reset', :type => 'reset'

This gem is produced by Ryanb, many thanks.

Posted at 30 Nov 2011

blog comments powered by Disqus