Rails 4 add file_field for attachment upload to existing form and controller
Asked Answered
S

3

5

I'm super new to rails. Been learning a few weeks now. Please excuse my idiocy. I cannot get my file I've selected to upload.

I'm using Rails 4.0.0.

I am working on my first application, and I started by following the rails guide for the blog application. I took that and ran with it and am creating something different (bug tracking system) just trying to learn to ropes.

So, I've got my form:

<%= form_for @post do |f| %>

and I've added in my file_field. The display part in from the view looks and works good as far as selecting a file goes.

<%= f.label :attachment %>
<%= f.file_field :attachment %>

I've pulled this from the rails 4 guides FYI. So my controller looks like this:

class PostsController < ApplicationController

    def new
      @post = Post.new
    end

    def create
      @post = Post.new(params[:post].permit(:title, :text, :user, :screen))

      if @post.save
        redirect_to posts_path
      else
        render 'new'
      end
    end

    def show
      @post = Post.find(params[:id])
    end

    def index
      @posts = Post.all
    end

    def edit
      @post = Post.find(params[:id])
    end

    def update
      @post = Post.find(params[:id])

      if @post.update(params[:post].permit(:title, :text, :user, :screen))
        redirect_to posts_path
      else
        render 'edit'
      end
    end

    def destroy
      @post = Post.find(params[:id])
      @post.destroy
      redirect_to posts_path
    end

    def upload
      uploaded_io = params[:post][:attachment]
      File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'w') do |file|
        file.write(uploaded_io.read)
      end
    end

    private
    def post_params
      params.require(:post).permit(:title, :text, :user, :screen, :attachment)
    end

end

The new piece in here is upload. Everything else is working fine with writing/reading from the database and displaying. When the view is displayed I make text entries, attached a file and hit submit. Everything writes to the database and shows up on index, but the file I've attempted to attached does not get written to ~/bugs/public/uploads/

Thanks in advance for the help.

Smaragdite answered 23/8, 2013 at 15:53 Comment(0)
G
4

I think the problem might be that the :attachment attribute is not a permitted parameter in the "create" or "update" action.

Edit: The way I do simple file uploads is with the Paperclip gem - this railscast explains it well. It's really easy to use.

There's also this answer that might answer the question.

Also, the standard way to use strong parameters is defining permitted params in a private method and calling that method in the controller action (so you don't have to repeat yourself). That might be the cause of the error.

Example:

def create
  @post = Post.new(post_params)
  ...
end

Hope that helps.

Gorlicki answered 23/8, 2013 at 16:37 Comment(5)
Thanks for the response Chris. So, I looked into that too. I added :attachment to create action only and then created a new "bug". On submit, I get "unknown attribute: attachment". So do I need to generate my controller again and include :attachment? I hadn't done this because I was thinking the file name (at least not yet) wasn't getting inserted into the database. Then again, I don't really know what I'm talking about. I will try it and update my comment.Smaragdite
Quick update, as I'm still researching, so I generated a new model, and ran rake db:migrate and am I now getting a new error (progress!) which reads: TypeError: can't cast ActionDispatch::Http::UploadedFile to string: INSERT INTO "posts" ("attachment", "created_at", "screen", "text", "title", "updated_at", "user") VALUES (?, ?, ?, ?, ?, ?, ?)Smaragdite
Edited the answer with a couple possible solutions.Gorlicki
I got it work. I just moved the contents of my upload action into my create action. I will eventually make it to paperclip/carrierwave but I wanted to do it plain jane to start with. Chris C. thank you very much for your help as it helped me discover the answer. Also, many thanks for the (post_params) after defining the params privately.Smaragdite
No prob. Glad it helped. Good luck learning Rails... it's awesome.Gorlicki
E
2

I had the same problem,

solution :-

delete the "def upload" and give the code inside "def create" itself

>  def create
>              
>             uploaded_io = params[:post][:attachment]
>             File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'w') do |file|
>             file.write(uploaded_io.read)
>             end
> 
>             @post = Post.new(params[:post].permit(:title, :text, :user, :screen))
> 
>             if @post.save
>                     redirect_to posts_path
>             else
>                     render 'new'
>             end
>     end
Edyth answered 9/2, 2016 at 12:55 Comment(0)
A
1

Make sure that the 'uploads' directory exists in 'public'.

You can handle this automatically by adding this line before the file operation:

Dir.mkdir 'public/uploads' unless File.directory? 'public/uploads'

Afroasiatic answered 23/8, 2013 at 16:6 Comment(1)
Thanks, I definitely ran it a few times before creating an uploads directory in the public folder. But after doing so still no dice.Smaragdite

© 2022 - 2024 — McMap. All rights reserved.