1

I have created a form in order to create articles, it has fields for title, date, content, main image, and a special field for the multiple upload. Images are uploaded with Carrierwave.

I have two differents models and controllers that work with this form. progress and progress_attachments.

As I want to attach multiple images in order to create a photos gallery I have created this other controller progress_attachment I followed SSR explanations

When I submit my form, I have this error

NoMethodError in ProgressesController#create
    undefined method `[]' for nil:NilClass

Even though the article is published... (I can find it in rails console, and If I go back to the show)

I beleive that this undefined method []comes from my create method in the the progress controller, but I am missing something and I don't understand what...??

progresses_controller.rb

class ProgressesController < ApplicationController

  def index
    @progresses = Progress.all
  end

  def show
    @progress = Progress.find(params[:id])
    @progress_attachments = @progress.progress_attachments.all
  end

  def new
     @progress = Progress.new
     @progress_attachment = @progress.progress_attachments.build
  end

  def create
     @progress = Progress.new(progress_params)

     respond_to do |format|
       if @progress.save
         params[:progress_attachments]['image'].each do |a|
            @progress_attachment = @progress.progress_attachments.create!(:image => a)
         end
         format.html { redirect_to progresses_path, notice: 'Progress was successfully created.' }
       else
         format.html { render action: 'new' }
       end
     end
   end

   def update
     respond_to do |format|
       if @progress.update(article_params)
         format.html { redirect_to @progress, notice: 'Article was successfully updated.' }
         format.json { render :show, status: :ok, location: @progress }
       else
         format.html { render :edit }
         format.json { render json: @progress.errors, status: :unprocessable_entity }
       end
     end
   end

   def destroy
     @progress.destroy
     respond_to do |format|
       format.html { redirect_to articles_url, notice: 'Article was successfully destroyed.' }
       format.json { head :no_content }
     end
   end
   private
     def progress_params
        params.require(:progress).permit(:title, :content, :date, :main_image, progress_attachments_attributes: [:id, :progress_id, :image])
     end

end

progress_attachments_controller.rb

class ProgressAttachmentsController < ApplicationController
  before_action :set_progress_attachment, only: [:show, :edit, :update, :destroy]

  def index
    @progress_attachments = ProgressAttachment.all
  end

  def new
    @progress_attachment = ProgressAttachment.new
  end

  def create
    @progress_attachment = ProgressAttachment.new(progress_attachment_params)
    @progress_attachment = @progress.progress_attachments.build
    respond_to do |format|
      if @progress_attachment.save
        format.html { redirect_to @progress_attachment, notice: 'Progress attachment was successfully created.' }
        format.json { render :show, status: :created, location: @progress_attachment }
      else
        format.html { render :new }
        format.json { render json: @progress_attachment.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @progress_attachment.update(progress_attachment_params)
        format.html { redirect_to @progress_attachment, notice: 'Progress attachment was successfully updated.' }
        format.json { render :show, status: :ok, location: @progress_attachment }
      else
        format.html { render :edit }
        format.json { render json: @progress_attachment.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @progress_attachment.destroy
    respond_to do |format|
      format.html { redirect_to progress_attachments_url, notice: 'Progress attachment was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

    def set_progress_attachment
      @progress_attachment = ProgressAttachment.find(params[:id])
    end

    def progress_attachment_params
      params.require(:progress_attachment).permit(:progress_id, :image)
    end
end

the form in views/progresses/new.html.slim

 = simple_form_for(@progress, html: { multipart: true} ) do |f|
   =f.input :title
   =f.input :date
   =f.input :content
   =f.input :main_image
   =f.simple_fields_for :progress_attachments do |f|
     =f.input_field :image, multiple: true, name: "progress_attachments_attributes[:image][]"
   =f.button :submit 

I have edited the form since I have solved the problem of multiple uploads

models/progress_attachment.rb

class ProgressAttachment < ActiveRecord::Base
  mount_uploader :image, ImageUploader
  belongs_to :progress
  validates :image, presence: true
end

models/progress.rb

class Progress < ActiveRecord::Base
  default_scope ->{order(created_at: :DESC)}
  mount_uploader :main_image, MainImageUploader
  has_many :progress_attachments
  accepts_nested_attributes_for :progress_attachments

  validates :main_image,   presence: true
  validates :title,   presence: true
  validates :content,  presence: true
  validates :date,    presence: true
end

EDIT

this is my pry on my actual controller.

Started POST "/progresses" for ::1 at 2016-09-02 01:37:49 +0200
  ActiveRecord::SchemaMigration Load (0.1ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by ProgressesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"KdZkIvo+lbmE8JPlMNOOFc2grNG6w9u4kuO3kII2erOG+iD3RXfqutdwzAxvMIQbVGAzHVGawcBMW+WJfgZ+uA==", "progress"=>{"title"=>"Hello", "date"=>"1st september 2016", "content"=>"bonjourbonjour", "main_image"=>#<ActionDispatch::Http::UploadedFile:0x007fede250ecb8 @tempfile=#<Tempfile:/var/folders/11/mdddnw8d0zd961bsfkq1cjy00000gn/T/RackMultipart20160902-22001-1l0mkug.jpg>, @original_filename="12915103_10208497250246588_1486835977_o.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"progress[main_image]\"; filename=\"12915103_10208497250246588_1486835977_o.jpg\"\r\nContent-Type: image/jpeg\r\n">, "progress_attachments_attributes"=>{"0"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x007fede250eb78 @tempfile=#<Tempfile:/var/folders/11/mdddnw8d0zd961bsfkq1cjy00000gn/T/RackMultipart20160902-22001-9k74to.jpg>, @original_filename="band.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"progress[progress_attachments_attributes][0][image]\"; filename=\"band.jpg\"\r\nContent-Type: image/jpeg\r\n">}}}, "commit"=>"Create Progress"}

From: /Users/nelly/Desktop/ROR/leschner_guitars/app/controllers/progresses_controller.rb @ line 20 ProgressesController#create:

19: def create
 => 20:   binding.pry
    21:    @progress = Progress.new(progress_params)
    22:
    23:    respond_to do |format|
    24:      if @progress.save
    25:        params[:progress_attachments]['image'].each do |a|
    26:           @progress_attachment = @progress.progress_attachments.create!(:image => a)
    27:        end
    28:
    29:        format.html { redirect_to progresses_path, notice: 'Progress was successfully created.' }
    30:      else
    31:        format.html { render action: 'new' }
    32:      end
    33:    end
    34:  end

[1] pry(#<ProgressesController>)> params
=> {"utf8"=>"✓",
 "authenticity_token"=>"KdZkIvo+lbmE8JPlMNOOFc2grNG6w9u4kuO3kII2erOG+iD3RXfqutdwzAxvMIQbVGAzHVGawcBMW+WJfgZ+uA==",
 "progress"=>
  {"title"=>"Hello",
   "date"=>"1st september 2016",
   "content"=>"bonjourbonjour",
   "main_image"=>
    #<ActionDispatch::Http::UploadedFile:0x007fede250ecb8
     @content_type="image/jpeg",
     @headers=
      "Content-Disposition: form-data; name=\"progress[main_image]\"; filename=\"12915103_10208497250246588_1486835977_o.jpg\"\r\nContent-Type: image/jpeg\r\n",
     @original_filename="12915103_10208497250246588_1486835977_o.jpg",
     @tempfile=#<File:/var/folders/11/mdddnw8d0zd961bsfkq1cjy00000gn/T/RackMultipart20160902-22001-1l0mkug.jpg>>,
   "progress_attachments_attributes"=>
    {"0"=>
      {"image"=>
        #<ActionDispatch::Http::UploadedFile:0x007fede250eb78
         @content_type="image/jpeg",
         @headers=
          "Content-Disposition: form-data; name=\"progress[progress_attachments_attributes][0][image]\"; filename=\"band.jpg\"\r\nContent-Type: image/jpeg\r\n",
         @original_filename="band.jpg",
         @tempfile=#<File:/var/folders/11/mdddnw8d0zd961bsfkq1cjy00000gn/T/RackMultipart20160902-22001-9k74to.jpg>>}}},
 "commit"=>"Create Progress",
 "controller"=>"progresses",
 "action"=>"create"}
[2] pry(#<ProgressesController>)>

and with changing like SteveTurczyn suggested:

Started POST "/progresses" for ::1 at 2016-09-02 01:49:14 +0200
Processing by ProgressesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"XevIqKvA6UhcmipGb/zu8wJ3ItCwA5EBjldLQhwyXj7yx4x9FImWSw8ada8wH+T9m7e9HFtai3lQ7xlb4AJaNQ==", "progress"=>{"title"=>"This is a title", "date"=>"Today !", "content"=>"That's a short content", "main_image"=>#<ActionDispatch::Http::UploadedFile:0x007fb00af89dc0 @tempfile=#<Tempfile:/var/folders/11/mdddnw8d0zd961bsfkq1cjy00000gn/T/RackMultipart20160902-22410-13jb3ww.jpg>, @original_filename="band.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"progress[main_image]\"; filename=\"band.jpg\"\r\nContent-Type: image/jpeg\r\n">, "progress_attachments_attributes"=>{"0"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x007fb00af89c80 @tempfile=#<Tempfile:/var/folders/11/mdddnw8d0zd961bsfkq1cjy00000gn/T/RackMultipart20160902-22410-6mze6c.jpg>, @original_filename="boss2.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"progress[progress_attachments_attributes][0][image]\"; filename=\"boss2.jpg\"\r\nContent-Type: image/jpeg\r\n">}}}, "commit"=>"Create Progress"}

From: /Users/nelly/Desktop/ROR/leschner_guitars/app/controllers/progresses_controller.rb @ line 20 ProgressesController#create:

    19: def create
 => 20: binding.pry
    21:    @progress = Progress.new(progress_params)
    22:
    23:    respond_to do |format|
    24:      if params[:progress_attachments]
    25:        params[:progress_attachments]['image'].each do |a|
    26:         @progress_attachment = @progress.progress_attachments.create!(:image => a)
    27:        end
    28:        format.html { redirect_to progresses_path, notice: 'Progress was successfully created.' }
    29:      else
    30:        format.html { render action: 'new' }
    31:      end
    32:    end
    33:  end

[1] pry(#<ProgressesController>)> params
=> {"utf8"=>"✓",
 "authenticity_token"=>"XevIqKvA6UhcmipGb/zu8wJ3ItCwA5EBjldLQhwyXj7yx4x9FImWSw8ada8wH+T9m7e9HFtai3lQ7xlb4AJaNQ==",
 "progress"=>
  {"title"=>"This is a title",
   "date"=>"Today !",
   "content"=>"That's a short content",
   "main_image"=>
    #<ActionDispatch::Http::UploadedFile:0x007fb00af89dc0
     @content_type="image/jpeg",
     @headers="Content-Disposition: form-data; name=\"progress[main_image]\"; filename=\"band.jpg\"\r\nContent-Type: image/jpeg\r\n",
     @original_filename="band.jpg",
     @tempfile=#<File:/var/folders/11/mdddnw8d0zd961bsfkq1cjy00000gn/T/RackMultipart20160902-22410-13jb3ww.jpg>>,
   "progress_attachments_attributes"=>
    {"0"=>
      {"image"=>
        #<ActionDispatch::Http::UploadedFile:0x007fb00af89c80
         @content_type="image/jpeg",
         @headers="Content-Disposition: form-data; name=\"progress[progress_attachments_attributes][0][image]\"; filename=\"boss2.jpg\"\r\nContent-Type: image/jpeg\r\n",
         @original_filename="boss2.jpg",
         @tempfile=#<File:/var/folders/11/mdddnw8d0zd961bsfkq1cjy00000gn/T/RackMultipart20160902-22410-6mze6c.jpg>>}}},
 "commit"=>"Create Progress",
 "controller"=>"progresses",
 "action"=>"create"}

Thanks for your help

Community
  • 1
  • 1

2 Answers2

4
unless params[:progress_attachments].nil?
  params[:progress_attachments]['image'].each do |a|
    @progress_attachment = @progress.progress_attachments.create!(:image => a)
  end
end
Ahsan
  • 640
  • 6
  • 17
3

This is a likely source of your error...

params[:progress_attachments]['image'].each do |a|

If your params don't have a :progress_attachments key it will return nil, and doing nil['image'] will give you exactly the error you're seeing.

You may want to inspect the params coming into the create method using byebug or pry. If it's legitimate that no progress attachment needs to be present then you can wrap the each loop in if params[:progess_attachments] ... end

if params[:progress_attachments]
  params[:progress_attachments]['image'].each do |a|
    @progress_attachment = @progress.progress_attachments.create!(:image => a)
  end
end

I'm not actually clear that this will be the finished solution as I'm not clear you'll have an array of images but inspection of the params should clarify that.

SteveTurczyn
  • 36,057
  • 6
  • 41
  • 53
  • Hello Steve thanks for your answer, I don't really know how to use pry or byebug could you explain me please ? I am newbie... –  Sep 01 '16 at 23:10
  • 1
    Install the gem pry in your Gemfile by inserting three lines... `group :development, test do; gem 'pry'; end` then do `bundle install` to install pry. Then immediately after your `def create` line put in a line `binding.pry` and the next time the create method is called in development, the console will halt and you can type commands, like `params` to see what the params contain. When you're ready to resume your application, type `exit` and the application will continue. – SteveTurczyn Sep 01 '16 at 23:29
  • could you help me little more please. I updated the question with the pry :) –  Sep 04 '16 at 15:13