Here’s how to get pictures from your webcam into Rails using the Paperclip plugin and jpegcam.
What we will do is create a Photo model and a Photos controller with actions new, upload and create to take care of the image creation.
Start by creating a new Rails application:
$ rails webcam_app $ cd webcam_app
Create the Photo model:
$ script/generate model Photo description:string $ rake db:migrate
Create the Photos controller:
$ script/generate controller Photos
Edit config/routes.rb to contain a photos resource:
map.resources :photos, :only => [:index, :show, :new, :create], :new => { :upload => :post }
Download jpegcam and put webcam.js in your public/javascripts folder and webcam.swf and shutter.mp3 in your public folder.
Create the layout file app/views/layouts/application.html.erb and insert the following HTML:
<html>
<head>
<%= javascript_include_tag :defaults %>
<%= javascript_include_tag 'webcam' %>
</head>
<body>
<%= yield %>
</body>
</html>
Next, create app/views/photos/new.html.erb and make a div for the webcam contents:
<div id="webcam"></div>
And the actual webcam javascript:
<script type="text/javascript">
webcam.set_swf_url('/webcam.swf');
webcam.set_api_url('<%= upload_new_photo_path %>');
webcam.set_quality(90);
webcam.set_shutter_sound(true, '/shutter.mp3');
$('webcam').innerHTML = webcam.get_html(640, 480);
</script>
That will run the actual webcam so you can see yourself :) But for taking a picture, we’ll need to add the following button:
<input type="button" value="Take picture" onclick="webcam.snap();" />
Now when you click the button, the webcam image will be posted to /photos/new/upload. Try it out:
$ script/server
and go to http://localhost:3000/photos/new.
Let’s add some code for handling the upload.
The webcam.swf just uploads a bunch of jpeg data so we’ll need to get a hold of the raw post data. That’s done with Rails’ request.raw_post. In your PhotosController:
def upload
File.open(upload_path, 'w') do |f|
f.write request.raw_post
end
render :text => "ok"
end
private
def upload_path # is used in upload and create
file_name = session[:session_id].to_s + '.jpg'
File.join(RAILS_ROOT, 'public', 'uploads', file_name)
end
Remember to create the public/uploads folder.
Now, back to app/views/photos/new.html.erb. Create the following at the bottom of the view:
<% form_for Photo.new, :html => { :style => "display: none;" } do |f| %>
<p>
<%= f.label :description %><br />
<%= f.text_field :description %>
</p>
<p>
<%= f.submit "Save the photo" %>
or <%= link_to "Take another", new_photo_path %>
</p>
<% end %>
In your javascript just below the webcam div, insert the following function:
function upload_complete(msg) {
if (msg == 'ok') {
$('new_photo').show();
$('photo_description').focus();
} else {
alert('An error occured');
webcam.reset();
}
}
And add the following webcam code:
webcam.set_hook('onComplete', 'upload_complete');
Now when you take a picture you will get a new photo form for entering a description. If something goes wrong, the webcam will be reset so you can try again. This might also be a good time to check your logs.
Now we have the upload (see for yourself in your public/uploads folder) but we still need to add Paperclip to the model.
Start by installing the plugin:
$ script/plugin install git://github.com/thoughtbot/paperclip.git
In the Photo model:
class Photo < ActiveRecord::Base
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }
end
For this to work, we need to add some necessary Paperclip columns to our Photo model:
$ script/generate paperclip photo image $ rake db:migrate
Now we can show photos like this:
<%= image_tag photo.image.url(:thumb) %>
We just need to save the photos first. Add the following to your PhotosController somewhere above the private keyword:
def create @photo = Photo.new(params[:photo]) @photo.image = File.new(upload_path) @photo.save redirect_to @photo end def show @photo = Photo.find(params[:id]) end def index @photos = Photo.all end
In app/views/photos/show.html.erb:
<h1>Photo</h1> <p><%= image_tag @photo.image.url(:medium) %></p> <p> <strong>Description:</strong><br /> <%=h @photo.description %> </p> <p> <%= link_to "Take a new picture", new_photo_path %> | <%= link_to "See all pictures", photos_path %> </p>
And last but not least in app/views/photos/index.html.erb:
<h1>All photos</h1>
<p>
<% @photos.each do |photo| %>
<%= link_to image_tag(photo.image.url(:thumb)), photo %>
<% end %>
</p>
<p>
<%= link_to "Take a new picture", new_photo_path %>
</p>
Now start your script/server if it isn’t already, go to http://localhost:3000/photos – aaannnd.. it works!
Andre indlæg:
Tags: jpegcam, Paperclip, Ruby on Rails, Webcam

Hi there,
Thanks for this blog post, it’s been helpful to me for a slightly different use case that involved uploading binary data from Flex to Rails.
One problem I still have is that Rails is complaining about a missing authenticity token. In other instances, I’ve worked around this by supplying the token using POST params .. assuming this is not possible sending the data as a raw POST – is that right?
Cheers
Josh
Hi Josh,
Strangely enough I didn’t have this problem.
You could try the following in the controller containing your upload action:
skip_before_filter :verify_authenticity_token, :only => :your_upload_actionBR, Lasse
i hv captured the image and it is saved in uploades folder but i m not able to view it…….wat may be the problem