0

I'm building a Rails 4 app with the paperclip gem in which users can upload a video file from a form with several other fields (uploader_first_name, uploader_last_name, uploader_email).

The paperclip installation went smoothly (although I needed to add gem 'protected_attributes' ) and I'm able to save file to the correct and create the corresponding records in the videos table, however all the non-paperclip fields are null and I'm not sure why.

class Video < ActiveRecord::Base
    belongs_to :project
    attr_accessible :file
    has_attached_file :file, :url=>"/tmp/video_uploads", :path=>":rails_root/tmp/video_uploads"

end

class VideosController < ApplicationController
  def save
    @video = Video.create(params[:video])
    if @video.save
        redirect_to root_path
    else
        redirect_to "somewhere_else"
    end
  end

#I tried with this too...
  #private
    #def video_params
      #params.require(:video).permit( :uploader_first_name, :uploader_last_name, :uploader_email)
    #end
end

In the view...

<h2>Upload your video</h2>
<% myclass = {:class=>'form-control'} %>
<%= form_for(:video, :url => {:action=>'save', :controller=>'videos'}, :html=>{:class=>'upload-form-js', :multipart=> true} ) do |f| %>

<div class="form-group">
<%= f.label(:uploader_first_name, "First Name") %>
<%= f.text_field(:uploader_first_name, myclass) %>
</div>

<div class="form-group">
<%= f.label(:uploader_last_name, "Last Name") %>
<%= f.text_field(:uploader_last_name, myclass) %>
</div>

<div class="form-group">
<%= f.label(:uploader_email, "Email") %>
<%= f.text_field(:uploader_email, myclass) %>
</div>

<div class="form-group">
    <label>Video File</label>
        <input type="file" name="video[file]" id="video_file"/></span>            
</div>

<%= f.submit('Upload', {class: 'btn btn-primary btn-block'}) %>
<% end %>

Update 1 I changed to this...

class VideosController < ApplicationController
  def save
    @video = Video.create( video_params )
    if @video.save
        redirect_to root_path
    else
        redirect_to "somewhere_else"
    end
  end
  private
    def video_params
      params.require(:video).permit(:file, :uploader_first_name, :uploader_last_name, :uploader_email)
    end
end

...and now I get this error:

Errno::EISDIR in VideosController#save
Is a directory - /Applications/MAMP/htdocs/clippo2/tmp/video_uploads

Don't I want the url/path to point to a directory?

Update 2 I changed the video model to...

has_attached_file :file, :url=>"/tmp/video_uploads/:basename.:extension", :path=>":rails_root/tmp/video_uploads/:basename.:extension"

...and now no errors, files get saved to the right directory and the corresponding fields added to the new row, but all other fields are still NULL (original problem).

Update 3 I turned on the debugger and here's what I see after I try to upload a file. It looks like a strong parameters error but I'm not sure how to fix it:

Started POST "/videos/save" for 127.0.0.1 at 2013-08-27 09:21:34 -0400
Processing by VideosController#save as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"es4wPqFr9xPBUFsbHQR/gAzofDC+ZwYsiiJ7RAQZUHk=", "video"=>{"uploader_first_name"=>"adsfasdf", "uploader_last_name"=>"asdfasdf", "uploader_email"=>"asdfasdf", "file"=>#<ActionDispatch::Http::UploadedFile:0x007fc4782e31e8 @tempfile=#<Tempfile:/var/folders/f2/jhv7xx0j3hlckhcg_jbv6hr00000gn/T/RackMultipart20130827-89636-188f0hs>, @original_filename="sample_iPod.m4v", @content_type="video/mp4", @headers="Content-Disposition: form-data; name=\"video[file]\"; filename=\"sample_iPod.m4v\"\r\nContent-Type: video/mp4\r\n">, "project_hashed_id"=>"1377539908"}, "commit"=>"Upload"}
{"utf8"=>"✓", "authenticity_token"=>"es4wPqFr9xPBUFsbHQR/gAzofDC+ZwYsiiJ7RAQZUHk=", "video"=>{"uploader_first_name"=>"adsfasdf", "uploader_last_name"=>"asdfasdf", "uploader_email"=>"asdfasdf", "file"=>#<ActionDispatch::Http::UploadedFile:0x007fc4782e31e8 @tempfile=#<Tempfile:/var/folders/f2/jhv7xx0j3hlckhcg_jbv6hr00000gn/T/RackMultipart20130827-89636-188f0hs>, @original_filename="sample_iPod.m4v", @content_type="video/mp4", @headers="Content-Disposition: form-data; name=\"video[file]\"; filename=\"sample_iPod.m4v\"\r\nContent-Type: video/mp4\r\n">, "project_hashed_id"=>"1377539908"}, "commit"=>"Upload", "controller"=>"videos", "action"=>"save"}
Unpermitted parameters: project_hashed_id
WARNING: Can't mass-assign protected attributes for Video: uploader_first_name, uploader_last_name, uploader_email
    app/controllers/videos_controller.rb:6:in `save'
  [1m[35m (0.2ms)[0m  BEGIN
  [1m[36mSQL (0.3ms)[0m  [1mINSERT INTO `videos` (`created_at`, `file_content_type`, `file_file_name`, `file_file_size`, `file_updated_at`, `updated_at`) VALUES ('2013-08-27 13:21:34', 'video/mp4', 'sample_iPod.m4v', 2236480, '2013-08-27 13:21:34', '2013-08-27 13:21:34')[0m
  [1m[35m (9.0ms)[0m  COMMIT
Redirected to http://localhost:3000/
Completed 302 Found in 21ms (ActiveRecord: 9.5ms)
emersonthis
  • 32,822
  • 59
  • 210
  • 375
  • When you say you "tried" the commented out code, how exactly did you incorporate it? – Peter Alfvin Aug 26 '13 at 21:37
  • I uncommented it and replaced `Video.create(params[:video])` with `Video.create(video_params)`. That didn't throw errors but it caused the file not to get saved and also didn't cause the other fields to get saved. – emersonthis Aug 26 '13 at 23:05
  • Ok, well without the `require`, you're not going to get those fields and if the `save` fails, you're not going to get _any_ fields. So you need to keep the `require`, I think, and figure out what the `save` is failing in that case. – Peter Alfvin Aug 26 '13 at 23:08
  • @PeterAlfvin I think I'm almost to the bottom of what's going on. I found the relevant error in the log, but I'm not entirely sure how to interpret it: "WARNING: Can't mass-assign protected attributes for Video: uploader_first_name, uploader_last_name, uploader_email" – emersonthis Aug 27 '13 at 13:26
  • 1
    Do you know what `Unpermitted parameters: project_hashed_id` is? – Peter Alfvin Aug 27 '13 at 14:00
  • @PeterAlfvin Yup. It was another one of the fields I was trying to pass through the form (but had not included in the `attr_accessible`). – emersonthis Aug 27 '13 at 14:10

2 Answers2

0

Welcome to the rails 4. 'attr_accessible' was replaced by the strong parameters.
http://api.rubyonrails.org/classes/ActionController/StrongParameters.html

Upd. Can you try this?

def create
  @video = Video.create(video_params)
end

private

def video_params
  params.require(:video).permit(:file, :uploader_first_name, :uploader_last_name, :uploader_email)
end
x3qt
  • 310
  • 2
  • 7
0

I figured out what's going on. The strong parameters were getting in the way because I'm using attr_accessible in the model. Instead of fiddling with the require() and permit() I removed them entirely and added the missing fields to the attr_accessible and now it works:

class Video < ActiveRecord::Base
    belongs_to :project
    attr_accessible :file, :uploader_first_name, :uploader_last_name, :project_hashed_id, :uploader_email, :rating
    has_attached_file :file, :url=>"/tmp/video_uploads/:basename.:extension", :path=>":rails_root/tmp/video_uploads/:basename.:extension"
end

class VideosController < ApplicationController
  def save
    logger.debug( params )
    #@video = Video.new( video_params )
    @video = Video.new( params[:video])
    if @video.save
        redirect_to root_path
    else
        redirect_to "somewhere_else"
    end
  end
end

I realize that attr_accessible was replaced by strong parameters in Rails 4 but I couldn't get paperclip to work without it. If anyone can tell me how, I'd love to know.

Update I removed attr_accessible entirely and just used the strong parameters...

class VideosController < ApplicationController

  def save
    logger.debug( params )
    @video = Video.new( video_params )
    if @video.save
        redirect_to root_path
    else
        redirect_to "somewhere_else"
    end
  end

  private
    def video_params
      #params.require(:video).permit(:file, :uploader_first_name, :uploader_last_name, :uploader_email, :project_hashed_id)
      params.require(:video).permit!
    end

end

...and it works BUT you have to remember to remove the protected_attributes gem and restart rails s for it to take effect (this n00b mistake cost me 45 minutes!)

Moral of this story: Don't mix and match attr_accessible with strong params. Do one or the other and paperclip will work with strong parameters.

emersonthis
  • 32,822
  • 59
  • 210
  • 375