Paperclip scaffolding

I just updated the View Mapper gem to support Paperclip. You can use it to generate scaffolding code that supports uploading and downloading Paperclip file attachments.

Creating a view for an existing model

If you have a model like this:

class Song < ActiveRecord::Base
  has_attached_file :mp3
end

… you can generate a “Paperclip view” for this model like this:

script/generate view_for song --view paperclip

This will generate a controller, view and other code files that support uploading and downloading files. If you run your app you’ll see the typical scaffolding user interface but with a file field for the “mp3” Paperclip attachment:

View Mapper has:

  • inspected your model (“Song” in this example) and found its Paperclip attachments and other standard ActiveRecord attributes
  • called the Rails scaffold generator and passed in the ActiveRecord columns it found
  • added additional view code to support Paperclip (e.g. set the form to use multipart/form-data encoding)
  • created a file field in the form for each Paperclip attachment (“mp3” in this example), as well as a link to each attachment in the show view code file.

If you’re not very familiar with Paperclip and how to use it or if you just want to get a Rails upload form working very quickly, then View Mapper can help you.

Creating an entirely new Paperclip model and view

View Mapper also provides a generator called “scaffold_for_view” that is identical to the standard Rails scaffold generator, except it will create the specified view. As an example, let’s create a new Rails app from scratch that uses Paperclip; you should be able to type in these precise commands on your machine and get this example to work.

First, let’s install View Mapper and create a new Rails app to display my MP3 library online (ignoring copyright issues for now):

$ gem sources -a http://gemcutter.org
http://gemcutter.org added to sources
$ sudo gem install view_mapper
Successfully installed view_mapper-0.2.0
1 gem installed
Installing ri documentation for view_mapper-0.2.0...
Installing RDoc documentation for view_mapper-0.2.0...
$ rails music
      create  
      create  app/controllers
      create  app/helpers
      create  app/models
      create  app/views/layouts
etc…

And now we can generate a new “Song” model that has a Paperclip attachment called “MP3” using View Mapper like this:

$ cd music
$ ./script/generate scaffold_for_view song name:string artist:string
                    album:string play_count:integer --view paperclip:mp3
       error  The Paperclip plugin does not appear to be installed.

Wait… I forgot to install Paperclip; let’s do that and then try again:

$ ./script/plugin install git://github.com/thoughtbot/paperclip.git
Initialized empty Git repository in /Users/pat/rails-apps/music/vendor/plugins/paperclip/.git/
remote: Counting objects: 71, done.
remote: Compressing objects: 100% (59/59), done.
remote: Total 71 (delta 7), reused 29 (delta 3)
Unpacking objects: 100% (71/71), done.
From git://github.com/thoughtbot/paperclip
 * branch            HEAD       -> FETCH_HEAD
$ ./script/generate scaffold_for_view song name:string artist:string
                    album:string play_count:integer --view paperclip:mp3
      exists  app/models/
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/songs
      exists  app/views/layouts/
      exists  test/functional/
etc…

Finally, we just need to run db:migrate – one minor detail here is that the scaffold_for_view generator included the Paperclip columns (“mp3_file_name,” “mp3_content_type,” etc…) in the migration file to create the songs table:

$ rake db:migrate
(in /Users/pat/rails-apps/music)
==  CreateSongs: migrating ====================================================
-- create_table(:songs)
   -> 0.0022s
==  CreateSongs: migrated (0.0024s) ===========================================

Now you can run your app and see the scaffolding UI I showed above, and will be able to upload and download MP3 files using Paperclip.

Let’s take a quick look at exactly what is different about the scaffolding code View Mapper generated vs. the standard Rails scaffolding code:

<h1>New song</h1>

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

… etc …

  <p>
    <%= f.label :mp3 %><br />
    <%= f.file_field :mp3 %>
  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

<%= link_to 'Back', songs_path %>

The code in bold was generated by View Mapper specifically to support Paperclip since we used the “--view paperclip” command line option. You can see that “:html => { :multipart => :true }” was added to form_for to allow for file uploads, and also a file_field was added for the mp3 Paperclip attachment.

If you take a look at the show view, you’ll see:

<p>
  <b>Name:</b>
  <%=h @song.name %>
</p>

… etc …

<p>
  <b>Mp3:</b>
  <%= link_to @song.mp3_file_name, @song.mp3.url %><br>
</p>

<%= link_to 'Edit', edit_song_path(@song) %> |
<%= link_to 'Back', songs_path %>

Here a link to the file attachment was added, using Paperclip to provide the name and URL of the attachment.

Next I’ll be adding support for nested attributes and complex forms to View Mapper.