views:

76

answers:

1

Hi Everyone,

I am working on getting multiple file uploads working for an model in my application, I have included the code below:

delivers_controller.rb

# POST /delivers

def create
  @deliver = Deliver.new(params[:deliver])

  process_file_uploads(@deliver)

  if @deliver.save
    flash[:notice] = 'Task was successfully created.'
    redirect_to(@deliver)
  else
    render :action => "new" 
  end
end

protected

def process_file_uploads(deliver)
    i = 0
    while params[:attachment]['file_'+i.to_s] != "" && !params[:attachment]['file_'+i.to_s].nil?
        deliver.assets.build(:data => params[:attachment]['file_'+i.to_s])
        i += 1
    end
end

deliver.rb

  has_many :assets, :as => :attachable, :dependent => :destroy

  validate :validate_attachments

    Max_Attachments = 5
    Max_Attachment_Size = 5.megabyte

    def validate_attachments
      errors.add_to_base("Too many attachments - maximum is #{Max_Attachments}") if assets.length > Max_Attachments
      assets.each {|a| errors.add_to_base("#{a.name} is over #{Max_Attachment_Size/1.megabyte}MB") if a.file_size > Max_Attachment_Size}
    end

assets_controller.rb

class AssetsController < ApplicationController

  def show
    asset = Asset.find(params[:id])
    # do security check here
    send_file asset.data.path, :type => asset.data_content_type
  end

  def destroy
      asset = Asset.find(params[:id])
      @asset_id = asset.id.to_s
      @allowed = Deliver::Max_Attachments - asset.attachable.assets.count 
      asset.destroy
    end

end

asset.rb

class Asset < ActiveRecord::Base
  has_attached_file :data,

  belongs_to :attachable, :polymorphic => true

  def url(*args)
    data.url(*args)
  end

  def name
    data_file_name
  end

  def content_type
    data_content_type
  end

  def file_size
    data_file_size
  end
end

Whenever I create a new deliver item and try to attach any files I get the following error:

NoMethodError in DeliversController#create

You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]
/Users/danny/Dropbox/SVN/railsapps/macandco/surveymanager/trunk/app/controllers/delivers_controller.rb:60:in `process_file_uploads'
/Users/danny/Dropbox/SVN/railsapps/macandco/surveymanager/trunk/app/controllers/delivers_controller.rb:46:in `create'

new.html.erb (Deliver view)

<% content_for :header do -%>
    Deliver Repositories
<% end -%>

<% form_for(@deliver, :html => { :multipart => true }) do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :caseref %><br />
    <%= f.text_field :caseref %>
  </p>
  <p>
    <%= f.label :casesubject %><br />
    <%= f.text_area :casesubject %>
  </p>


  <p>
    <%= f.label :description %><br />
    <%= f.text_area :description %>
  </p>

  <p>Pending Attachments: (Max of <%= Deliver::Max_Attachments %> each under <%= Deliver::Max_Attachment_Size/1.megabyte%>MB)
      <% if @deliver.assets.count >= Deliver::Max_Attachments %>
        <input id="newfile_data" type="file" disabled />
      <% else %>
        <input id="newfile_data" type="file" />
      <% end %>
      <div id="attachment_list"><ul id="pending_files"></ul></div>

  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

<%= link_to 'Back', delivers_path %>

Show.html.erb (Delivers view)

<% content_for :header do -%>
    Deliver Repositories
<% end -%>

<p>
  <b>Title:</b>
  <%=h @deliver.caseref %>
</p>
<p>
  <b>Body:</b>
  <%=h @deliver.casesubject %>
</p>

<p><b>Attached Files:</b><div id="attachment_list"><%= render :partial => "attachment", :collection => @deliver.assets %></div></p>

<%= link_to 'Edit', edit_deliver_path(@deliver) %> | <%= link_to 'Back', deliver_path %>

<%- if logged_in? %>
<%= link_to 'Edit', edit_deliver_path(@deliver) %> |
<%= link_to 'Back', delivers_path %>
<% end %>

_attachment.html.erb (Delivers view)

<% if !attachment.id.nil? %><li id='attachment_<%=attachment.id %>'><a href='<%=attachment.url %>'><%=attachment.name %></a> (<%=attachment.file_size/1.kilobyte %>KB)
<%= link_to_remote "Remove", :url => asset_path(:id => attachment), :method => :delete, :html => { :title  => "Remove this attachment", :id => "remove" } %></li>
<% end %>

I have been banging my head against the wall with the error all day, if anyone can shed some light on it, I would be eternally grateful!

Thanks,

Danny

+1  A: 

The error message indicates that params[:attachment] is nil inside process_file_uploads(), which causes params[:attachment]['file_'+i.to_s] to raise an exception.

This happens because there's no field named attachment in the form in new.html.erb.

Pär Wieslander
Not sure how I missed that, thanks!
dannymcc