Using Private key for File Transfer (SFTP)
April 14, 2015Validate a url in Rails 4
June 14, 2015This post shows how to use field_for and accepts_nested_attributes_for to created nested form for has_many model
Let suppose the following scenario. We have multiple projects and each project can have multiple screenshots. Following will be the definition of model classes.
class Project < ActiveRecord::Base has_many :screenshots end
class Screenshot < ActiveRecord::Base belongs_to :project end
Now while adding a new project, we want to upload images for that project as well. This requires changes in all three type of files, i.e. Model, View, Controller. First the Project model, we need to specify that this model will accept attributes for its associated model. The following line of code does that
accepts_nested_attributes_for :screenshots, :reject_if => lambda { |a| a[:image].blank? }, :allow_destroy => true
The reject_if block specifies that image attribute is required for form to be submitted successfully.
Now in the controller we need to initialize the associated model so the new method will be as follows
class ProjectsController < ApplicationController def new @project = Project.new @project.screenshots.new end def project_params params.require(:project).permit(:title, :description, :screenshots => [:image]) end end
The form view will have fields for the associated model.
<%= form_for @project, :html => {:multipart => true, :class => "form-horizontal project" } do |f| %> <div class="form-group"> <%= f.label :title, :class => 'col-sm-2 control-label' %> <div class="col-sm-10"> <%= f.text_field :title, :class => 'form-control' %> </div> <%= error_span(@project[:title]) %> </div> <div class="form-group"> <%= f.label :description, :class => 'col-sm-2 control-label' %> <div class="col-sm-10"> <%= f.text_area :description, :class => 'form-control' %> </div> <%= error_span(@project[:description]) %> </div> <div class="form-group"> <%= f.fields_for :screenshots, @project.screenshots do |f_screenshot| %> <%= f_screenshot.label :image, :class => 'col-sm-2 control-label' do %> Screenshots <% end %> <div class="col-sm-10"> <%= f_screenshot.file_field :image, :class => 'form-control' %> </div> <% end %> </div> <div class="form-actions"> <%= f.submit nil, :class => 'btn btn-primary' %> <%= link_to t('.cancel', :default => t("helpers.links.cancel")), projects_path, :class => 'btn btn-default' %> </div> <% end %>