In this example, I will show you how to allow a single form submission from a parent object with multiple children associate to it using the “nested form”.
1) Let say we have a schema for albums that has many photos associate to it.
create_table "albums", force: true do |t| t.string "title", null: false t.text "description" t.integer "user_id" t.datetime "created_at" t.datetime "updated_at" end
create_table "photos", force: true do |t| t.integer "album_id" t.string "image" t.datetime "created_at" t.datetime "updated_at" end
2) Create new carrierwave uploader. see this post in order to setup one https://u.osu.edu/hasnan.1/2014/03/13/rails-4-upload-image-to-s3-using-fog-and-carrierwave/
3) Our Albums and Photos models.
class Album < ActiveRecord::Base # belongs to user model belongs_to :user # Album has many photos has_many :photos, :inverse_of => :album, :dependent => :destroy # enable nested attributes for photos through album class accepts_nested_attributes_for :photos, allow_destroy: true end
class Photo < ActiveRecord::Base #photo belongs to album belongs_to :album #validations validates :album, presence: true # Photo uploader using carrierwave mount_uploader :image, PhotoUploader end
4) Our Controller where all the magic happens
In our case, we want to allow our user to upload multiple photos, and it will only get saved when user hits the submit button. User will be able to add more images in the future when they click edit album and add images from there.
So here is the album controller.
class AlbumsController < ApplicationController # truncated for brevity. def create @album = current_user.albums.build(album_params) authorize @album if @album.save # to handle multiple images upload on create if params[:images] params[:images].each { |image| @album.photos.create(image: image) } end flash[:notice] = "Your album has been created." redirect_to @album else flash[:alert] = "Something went wrong." render :new end end def update authorize @album if @album.update(params[:album].permit(:title,:description)) # to handle multiple images upload on update when user add more picture if params[:images] params[:images].each { |image| @album.photos.create(image: image) } end flash[:notice] = "Album has been updated." redirect_to @album else render :edit end end end
Photos controller:
class PhotosController < ApplicationController # truncated for brevity. def create @photo = Photo.new(photo_params) @photo.save end end
5) Our Views
In this example, we are not using nested resources. That means we have our routes to setup like this
config/routes.rb
resources :albums resources :photos
app/views/albums/_form.html.erb
<%= form_for @album, :html => {:multipart => true} do |f| %><%= f.label :title, :class => 'control-label' %><%= f.text_field :title, :class => 'text_field' %><%= f.label :description, :class => 'control-label' %><%= f.text_field :description, :class => 'text_field' %>#images[] returned to the album as an array. We use file_field_tag since images is not @album's attribute <%= file_field_tag "images[]", type: :file, multiple: true %><%= f.submit "submit", :class => "btn btn-default" %><% end %>
pay attention to the comment that I made on _form.html.erb template.
6) Handle image preview with jquery file upload
I'm not going to cover this topic at this time.
So, that's it. now when your user hit the submit button, rails will save all the images to album.cerita.tv iqbalhasnan.wordpress.com