Topic: File Upload: No Method Error

I'm trying to write a simple file upload and can't seem to find why I'm getting this error:

NoMethodError in Project filesController#create
undefined method `[]' for #<File:/tmp/CGI4061.0>

Here's my controller:

def create
  @project_file = ProjectFile.new(params[:project_file])
  if @project_file.save
    flash[:notice] = 'ProjectFile was successfully created.'
    redirect_to :action => 'new'
  else
    flash[:notice] = "Ah Crap!"
    render :action => 'new'
  end
end

Here's my model:

class ProjectFile < ActiveRecord::Base
  belongs_to :user
  belongs_to :project

  validates_presence_of :file_name, :content_type, :user_id, :project_id

  def content_type=(project_file)
    write_attribute(:content_type, project_file[:file_name].content_type)
  end
 
  def file_name=(project_file)
    path = "/project_files/"
    filename = project_file[:project_id].to_s + "_" + project_file[:file_name].original_filename.to_s
    File.open(path + filename, "w") { |f| f.write(project_file[:file_name].read) }
    write_attributes(:file_name, filename)
  end

  def file_name
    "/project_files/" + read_attribute(:file_name)
  end
end


Here's My view (I've inserted the partial for the sake of space and readability):

<h1 class='heading'>Add File</h1>

<%= start_form_tag( {:controller => 'project_files', :action => 'create'}, :multipart => true )%>

<%= file_field 'project_file', 'file_name'  %>
<%= hidden_field 'project_file', 'project_id', :value => params[:project_id] %>
<%= submit_tag 'Upload' %>
<%= end_form_tag %>

If art interprets our dreams, the computer executes them in the guise of programs.

-SICP (Abelson, Sussman)

Re: File Upload: No Method Error

How/Why are you treating project_file as an array within your model? Rails is complaining that the object doesn't provide a '[]' method, presumably where you are trying to call

project_file[:file_name]

or

project_file[:project_id]

Unless this is a way of accessing the member variables of the object (I'm quite new to Ruby), it doesn't seem right.

Kee

Re: File Upload: No Method Error

From the examples of rewriting accessor and write functions i've seen, that's a totally valid thing to do.  I believe when Project_file.new is called and given params[:project_file] it passes the hash contained by params[:project_file] in via the argument set in the write file_name= function.  However, I could be way off base.  But sadly, and obviously, no one has let me know that I'm writing this all wrong yet.  Thanks for the post, maybe I'll get some more input now.

If art interprets our dreams, the computer executes them in the guise of programs.

-SICP (Abelson, Sussman)

Re: File Upload: No Method Error

From the looks of the error message, the argument passed to file_name=() or content_type=() is a File object. Sounds like a perfect job for a breakpoint. If you haven't used breakpoints before, I would highly recommend trying it out. They make debugging so much easier.

Just add a line "breakpoint" to the beginning of the file_name=() and content_type=() method definitions. Call "script/breakpointer" in the command line (ignore the error message about no breakpoint service found). Now load the page in the web browser that calls the code with the breakpoint in it. When the breakpoint line is called, the script/breakpointer prompt turns into an interactive ruby session right where the breakpoint line was. You have access to all of the local variables and such. You can call "project_file.class" to see what type of object the project_file is. See the docs for some more details. Also see the wiki page.

Railscasts - Free Ruby on Rails Screencasts