<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
  <title>Pat Shaughnessy - Home</title>
  <id>tag:patshaughnessy.net,2009:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.8.0">Mephisto Drax</generator>
  
  <link href="http://patshaughnessy.net/" rel="alternate" type="text/html" />
  <updated>2009-11-09T22:30:10Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/patshaughnessy" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-11-09:1553</id>
    <published>2009-11-09T22:06:00Z</published>
    <updated>2009-11-09T22:30:10Z</updated>
    <category term="Rails" />
    <category term="rails" />
    <category term="view_mapper" />
    <link href="http://patshaughnessy.net/2009/11/9/scaffolding-for-complex-forms-using-nested-attributes" rel="alternate" type="text/html" />
    <title>Scaffolding for complex forms using nested attributes</title>
<content type="html">
            &lt;p&gt;While the new nested attributes feature in Rails 2.3 greatly simplifies writing forms that operate on two or more models at the same time, writing a complex form is still a confusing and daunting task even for experienced Rails developers. To make this easier, I just added nested attribute support to my &lt;a href="http://patshaughnessy.net/view_mapper"&gt;View Mapper gem&lt;/a&gt;. This means you can generate complex form scaffolding for two or more models in a has_many/belongs_to, has_and_belongs_to_many or has_many, through relationship.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Example:&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;If I have a group model that has many people and accepts nested attributes for them like this:&lt;/p&gt;
&lt;pre&gt;class Group &amp;lt; ActiveRecord::Base
  has_many :people
  accepts_nested_attributes_for :people, :allow_destroy =&amp;gt; true
end&lt;/pre&gt;
&lt;p&gt;&amp;hellip; and a person model that belongs to a group:&lt;/p&gt;
&lt;pre&gt;class Person &amp;lt; ActiveRecord::Base
  belongs_to :group
end&lt;/pre&gt;
&lt;p&gt;&amp;hellip; then View Mapper will allow you to generate scaffolding that displays groups of people all at once, like this:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate view_for group --view has_many:people
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/groups
&amp;hellip;etc&amp;hellip;
      create  app/views/groups/_form.html.erb
      create  app/views/groups/_person.html.erb
      create  public/javascripts/nested_attributes.js&lt;/pre&gt;
&lt;p&gt;Now if I open my Rails app and create a new group, I will see:&lt;br /&gt;
 &lt;img src="http://patshaughnessy.net/assets/2009/11/9/new_group.png" /&gt;&lt;/p&gt;
&lt;p&gt;This looks just like the standard Rails scaffolding, but with one additional &amp;ldquo;Add a Person&amp;rdquo; link. If you click on it, you&amp;rsquo;ll see the attributes of the person model appear along with a &amp;ldquo;remove&amp;rdquo; link, indented to the right:&lt;br /&gt;
 &lt;img src="http://patshaughnessy.net/assets/2009/11/9/new_group_detail.png" /&gt;&lt;/p&gt;
&lt;p&gt;If I enter some values and submit, ActiveRecord will insert a new record into both the groups table and the people table, and set the group_id value in the new person record correctly:&lt;br /&gt;
 &lt;img src="http://patshaughnessy.net/assets/2009/11/9/show_group.png" /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;View Mapper has:
&lt;ul&gt;
  &lt;li&gt;inspected your group and person models to find their attributes (columns).&lt;/li&gt;
  &lt;li&gt;validated that they are in a has_many / belongs_to relationship, or in a has_and_belongs_to_many or a has_many, through relationship.&lt;/li&gt;
  &lt;li&gt;checked that you have a foreign key column (&amp;ldquo;group_id&amp;rdquo; by default for this example) in the people table if necessary. (The foreign key isn&amp;rsquo;t in the people table for has_and_belongs_to_many or has_many, through.)&lt;/li&gt;
  &lt;li&gt;generated scaffolding using your attribute and model names, and that uses Javascript to support the &amp;ldquo;Add a person&amp;rdquo; and &amp;ldquo;remove&amp;rdquo; links.&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;To get the add/remove links to work, I used a simplified version of the &amp;ldquo;complex-form-examples&amp;rdquo; sample application from &lt;a href="http://github.com/ryanb/complex-form-examples"&gt;Ryan Bates&lt;/a&gt; and &lt;a href="http://github.com/alloy/complex-form-examples"&gt;Eloy Duran&lt;/a&gt;. Ryan has &lt;a href="http://railscasts.com/episodes/73-complex-forms-part-1"&gt;a few screen casts&lt;/a&gt; on this topic as well. In my next post I&amp;rsquo;ll explain how that works in detail, since understanding the details about how scaffolding works is the first step towards using it successfully in your app.&lt;/p&gt;
&lt;p&gt;But for now, you can try this on your machine using the precise commands below&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Creating a new complex form from scratch&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s get started by creating a new Rails application; you will need to have Rails 2.3 or later in order to make this work:&lt;/p&gt;
&lt;pre&gt;$ rails complex-form
      create  
      create  app/controllers
      create  app/helpers
      create  app/models
      create  app/views/layouts
&amp;hellip; etc &amp;hellip;
      create  log/production.log
      create  log/development.log
      create  log/test.log&lt;/pre&gt;
&lt;p&gt;Using the same group has many people example from above, let&amp;rsquo;s generate a new person model:&lt;/p&gt;
&lt;pre&gt;$ cd complex-form
$ ./script/generate model person first_name:string last_name:string
      exists  app/models/
      exists  test/unit/
      exists  test/fixtures/
      create  app/models/person.rb
      create  test/unit/person_test.rb
      create  test/fixtures/people.yml
      create  db/migrate
      create  db/migrate/20091109204744_create_people.rb&lt;/pre&gt;
&lt;p&gt;And let&amp;rsquo;s run that migration to create the people table:&lt;/p&gt;
&lt;pre&gt;$ rake db:migrate
(in /Users/pat/rails-apps/complex-form)
==  CreatePeople: migrating ===================================================
-- create_table(:people)
   -&amp;gt; 0.0013s
==  CreatePeople: migrated (0.0014s) ==========================================&lt;/pre&gt;
&lt;p&gt;Now we&amp;rsquo;re ready to run View Mapper. View Mapper contains two generators; one is for creating scaffolding for an existing model, called &amp;ldquo;view_for,&amp;rdquo; which is what I used above. There&amp;rsquo;s also another generator called &amp;ldquo;scaffold_for_view&amp;rdquo; which will create a new model along with the scaffolding, using the same syntax as the standard Rails scaffold generator. Let&amp;rsquo;s use that here, since we have a new app and haven&amp;rsquo;t created the group model yet:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate scaffold_for_view group name:string --view has_many:people
     warning  Model Person does not contain a belongs_to association for Group.&lt;/pre&gt;
&lt;p&gt;Here View Mapper is reminding me that I didn&amp;rsquo;t specify &amp;ldquo;belongs_to&amp;rdquo; in the person model. This saves me the trouble later of figuring out what&amp;rsquo;s wrong when my complex form doesn&amp;rsquo;t work. Let&amp;rsquo;s add that line to app/models/person.rb and try again:&lt;/p&gt;
&lt;pre&gt;class Person &amp;lt; ActiveRecord::Base
  &lt;b&gt;belongs_to :group&lt;/b&gt;
end

$ ./script/generate scaffold_for_view group name:string --view has_many:people
     warning  Model Person does not contain a foreign key for Group.&lt;/pre&gt;
&lt;p&gt;Duh&amp;hellip; I also forgot to include the &amp;ldquo;group_id&amp;rdquo; column when I generated the person model. I could have done that by including &amp;ldquo;group_id:integer&amp;rdquo; on the script/generate model command line above. Since I already have the person model now, let&amp;rsquo;s just continue by creating a new migration for the missing column:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate migration add_group_id_column_to_people
      exists  db/migrate
      create  db/migrate/20091109205711_add_group_id_column_to_people.rb&lt;/pre&gt;
&lt;p&gt;Editing the migration file:&lt;/p&gt;
&lt;pre&gt;class AddGroupIdColumnToPeople &amp;lt; ActiveRecord::Migration
  def self.up
    &lt;b&gt;add_column :people, :group_id, :integer&lt;/b&gt;
  end
etc&amp;hellip;&lt;/pre&gt;
&lt;p&gt;And running the migration:&lt;/p&gt;
&lt;pre&gt;$ rake db:migrate
(in /Users/pat/rails-apps/complex-form)
==  AddGroupIdColumnToPeople: migrating =======================================
-- add_column(:people, :group_id, :integer)
   -&amp;gt; 0.0010s
==  AddGroupIdColumnToPeople: migrated (0.0012s) ==============================&lt;/pre&gt;
&lt;p&gt;Now let&amp;rsquo;s run View Mapper once more to see whether we have any other problems, or whether we&amp;rsquo;re ready to generate the complex form scaffolding:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate scaffold_for_view group name:string --view has_many:people
      exists  app/models/
      exists  app/controllers/
&amp;hellip;etc&amp;hellip;
      create  app/models/group.rb
      create  test/unit/group_test.rb
      create  test/fixtures/groups.yml
      exists  db/migrate
      create  db/migrate/20091109210312_create_groups.rb
      create  app/views/groups/show.html.erb
      create  app/views/groups/_form.html.erb
      create  app/views/groups/_person.html.erb
      create  public/javascripts/nested_attributes.js&lt;/pre&gt;
&lt;p&gt;It worked! Just looking at the list of files that View Mapper created, you can get a sense of how it has customized the standard Rails scaffolding to implement the complex form: _form.html.erb, _person.html.erb, nested_attributes.js. More on these details in my next article.&lt;/p&gt;
&lt;p&gt;One detail I will point out now is that in order to get you started in the right direction and to allow the complex form to work immediately, the scaffold_for_view generator included the has_many and accepts_nested_attributes_for calls in the new model:&lt;/p&gt;
&lt;pre&gt;class Group &amp;lt; ActiveRecord::Base
  has_many :people
  accepts_nested_attributes_for :people,
                                :allow_destroy =&amp;gt; true,
                                :reject_if =&amp;gt; proc { |attrs|
                                  attrs[&amp;#x27;first_name&amp;#x27;].blank? &amp;amp;&amp;amp;
                                  attrs[&amp;#x27;last_name&amp;#x27;].blank?
                                }
end&lt;/pre&gt;
&lt;p&gt;You don&amp;rsquo;t need to type in all of this code yourself and know the precise syntax of the accepts_nested_attributes_for method&amp;hellip; it&amp;rsquo;s all generated for you. Later when you start to customize the scaffolding to work for your specific requirements, you&amp;rsquo;ll have a working example to look at right inside your app.&lt;/p&gt;
&lt;p&gt;Finally, we&amp;rsquo;re need to run the migrations once more since the scaffold_for_view generator created a new group model and corresponding migration for the groups table:&lt;/p&gt;
&lt;pre&gt;$ rake db:migrate
(in /Users/pat/rails-apps/complex-form)
==  CreateGroups: migrating ===================================================
-- create_table(:groups)
   -&amp;gt; 0.0013s
==  CreateGroups: migrated (0.0014s) ==========================================&lt;/pre&gt;
&lt;p&gt;Now if you start up Rails and hit http://localhost:3000/groups/new, you&amp;rsquo;ll see the complex form!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-10-16:1336</id>
    <published>2009-10-16T16:29:00Z</published>
    <updated>2009-10-24T14:55:56Z</updated>
    <category term="paperclip" />
    <category term="Rails" />
    <category term="paperclip" />
    <category term="rails" />
    <category term="view_mapper" />
    <link href="http://patshaughnessy.net/2009/10/16/paperclip-scaffolding" rel="alternate" type="text/html" />
    <title>Paperclip scaffolding</title>
<content type="html">
            &lt;p&gt;I just updated the &lt;a href="http://patshaughnessy.net/view_mapper"&gt;View Mapper gem&lt;/a&gt; to support Paperclip. You can use it to generate scaffolding code that supports uploading and downloading Paperclip file attachments.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Creating a view for an existing model&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;If you have a model like this:&lt;/p&gt;
&lt;pre&gt;class Song &amp;lt; ActiveRecord::Base
  has_attached_file :mp3
end&lt;/pre&gt;
&lt;p&gt;&amp;hellip; you can generate a &amp;ldquo;Paperclip view&amp;rdquo; for this model like this:&lt;/p&gt;
&lt;pre&gt;script/generate view_for song --view paperclip&lt;/pre&gt;
&lt;p&gt;This will generate a controller, view and other code files that support uploading and downloading files. If you run your app you&amp;rsquo;ll see the typical scaffolding user interface but with a file field for the &amp;ldquo;mp3&amp;rdquo; Paperclip attachment:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://patshaughnessy.net/assets/2009/10/16/new_song.png" /&gt;&lt;/p&gt;
&lt;p&gt;View Mapper has:
&lt;ul&gt;
  &lt;li&gt;inspected your model (&amp;ldquo;Song&amp;rdquo; in this example) and found its Paperclip attachments and other standard ActiveRecord attributes&lt;/li&gt;
  &lt;li&gt;called the Rails scaffold generator and passed in the ActiveRecord columns it found&lt;/li&gt;
  &lt;li&gt;added additional view code to support Paperclip  (e.g. set the form to use multipart/form-data encoding)&lt;/li&gt;
  &lt;li&gt;created a file field in the form for each Paperclip attachment (&amp;ldquo;mp3&amp;rdquo; in this example), as well as a link to each attachment in the show view code file.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;If you&amp;rsquo;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.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Creating an entirely new Paperclip model and view&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;View Mapper also provides a generator called &amp;ldquo;scaffold_for_view&amp;rdquo; that is identical to the standard Rails scaffold generator, except it will create the specified view. As an example, let&amp;rsquo;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.&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s install View Mapper and create a new Rails app to display my MP3 library online (ignoring copyright issues for now):&lt;/p&gt;
&lt;pre&gt;$ 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&amp;hellip;&lt;/pre&gt;
&lt;p&gt;And now we can generate a new &amp;ldquo;Song&amp;rdquo; model that has a Paperclip attachment called &amp;ldquo;MP3&amp;rdquo; using View Mapper like this:&lt;/p&gt;
&lt;pre&gt;$ 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.&lt;/pre&gt;
&lt;p&gt;Wait&amp;hellip; I forgot to install Paperclip; let&amp;rsquo;s do that and then try again:&lt;/p&gt;
&lt;pre&gt;$ ./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       -&amp;gt; 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&amp;hellip;&lt;/pre&gt;
&lt;p&gt;Finally, we just need to run db:migrate &amp;ndash; one minor detail here is that the scaffold_for_view generator included the Paperclip columns (&amp;ldquo;mp3_file_name,&amp;rdquo; &amp;ldquo;mp3_content_type,&amp;rdquo; etc&amp;hellip;) in the migration file to create the songs table:&lt;/p&gt;
&lt;pre&gt;$ rake db:migrate
(in /Users/pat/rails-apps/music)
==  CreateSongs: migrating ====================================================
-- create_table(:songs)
   -&amp;gt; 0.0022s
==  CreateSongs: migrated (0.0024s) ===========================================&lt;/pre&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a quick look at exactly what is different about the scaffolding code View Mapper generated vs. the standard Rails scaffolding code:&lt;/p&gt;
&lt;pre&gt;&amp;lt;h1&amp;gt;New song&amp;lt;/h1&amp;gt;

&amp;lt;% form_for(@song&lt;b&gt;, :html =&amp;gt; { :multipart =&amp;gt; true }&lt;/b&gt;) do |f| %&amp;gt;
  &amp;lt;%= f.error_messages %&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :name %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= f.text_field :name %&amp;gt;
  &amp;lt;/p&amp;gt;

&amp;hellip; etc &amp;hellip;

&lt;b&gt;  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :mp3 %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= f.file_field :mp3 %&amp;gt;
  &amp;lt;/p&amp;gt;&lt;/b&gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.submit &amp;#x27;Create&amp;#x27; %&amp;gt;
  &amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;

&amp;lt;%= link_to &amp;#x27;Back&amp;#x27;, songs_path %&amp;gt;&lt;/pre&gt;
&lt;p&gt;The code in bold was generated by View Mapper specifically to support Paperclip since we used the &amp;ldquo;--view paperclip&amp;rdquo; command line option. You can see that &amp;ldquo;:html =&amp;gt; { :multipart =&amp;gt; :true }&amp;rdquo; was added to form_for to allow for file uploads, and also a file_field was added for the mp3 Paperclip attachment.&lt;/p&gt;
&lt;p&gt;If you take a look at the show view, you&amp;rsquo;ll see:&lt;/p&gt;
&lt;pre&gt;&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Name:&amp;lt;/b&amp;gt;
  &amp;lt;%=h @song.name %&amp;gt;
&amp;lt;/p&amp;gt;

&amp;hellip; etc &amp;hellip;

&lt;b&gt;&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Mp3:&amp;lt;/b&amp;gt;
  &amp;lt;%= link_to @song.mp3_file_name, @song.mp3.url %&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;&lt;/b&gt;

&amp;lt;%= link_to &amp;#x27;Edit&amp;#x27;, edit_song_path(@song) %&amp;gt; |
&amp;lt;%= link_to &amp;#x27;Back&amp;#x27;, songs_path %&amp;gt;&lt;/pre&gt;
&lt;p&gt;Here a link to the file attachment was added, using Paperclip to provide the name and URL of the attachment.&lt;/p&gt;
&lt;p&gt;Next I&amp;rsquo;ll be adding support for nested attributes and complex forms to View Mapper.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-10-01:1187</id>
    <published>2009-10-01T22:28:00Z</published>
    <updated>2009-11-09T22:30:39Z</updated>
    <category term="Rails" />
    <category term="view_mapper" />
    <category term="rails" />
    <category term="view_mapper" />
    <link href="http://patshaughnessy.net/2009/10/1/view-mapper-generate-complex-view-code-for-your-models" rel="alternate" type="text/html" />
    <title>View Mapper: Scaffolding for your models and plugins</title>
<content type="html">
            &lt;p&gt;View Mapper will generate scaffolding illustrating how to write view code using a specified plugin or feature with your existing models. It can also generate new models.&lt;/p&gt;
&lt;p&gt;A couple simple examples:&lt;/p&gt;
&lt;pre&gt;script/generate view_for office --view auto_complete:address&lt;/pre&gt;
&lt;p&gt;&amp;hellip; will generate Rails scaffolding code that displays a form for an existing &amp;ldquo;office&amp;rdquo; model, with auto complete on the &amp;ldquo;address&amp;rdquo; field.&lt;/p&gt;
&lt;pre&gt;script/generate scaffold_for_view office address:string code:string
                                  --view auto_complete:address&lt;/pre&gt;
&lt;p&gt;&amp;hellip; will generate the same form, but also create the &amp;ldquo;office&amp;rdquo; model class file, a migration file containing the &amp;ldquo;address&amp;rdquo; and &amp;ldquo;code&amp;rdquo; columns, and other standard scaffolding files as well.&lt;/p&gt;
&lt;p&gt;The idea behind View Mapper is that it&amp;rsquo;s easy to write simple, concise model classes representing your domain objects using ActiveRecord, but very hard to implement the corresponding views using a combination of HTML, Javascript Rails helper functions, routes, controllers, etc. If you&amp;rsquo;re not very familiar with a certain plugin you want to use in your app, View Mapper can help you get started in the right direction by generating a working example with scaffolding code.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re developing a Rails plugin or gem it&amp;rsquo;s easy to write your own View Mapper module for your plugin&amp;rsquo;s users to call with View Mapper.&lt;/p&gt;
&lt;p /&gt;
&lt;p /&gt;
&lt;p&gt;&lt;b&gt;Code:&lt;/b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href="http://github.com/patshaughnessy/view_mapper"&gt;http://github.com/patshaughnessy/view_mapper&lt;/a&gt;&lt;/p&gt;
&lt;p /&gt;
&lt;p /&gt;
&lt;p&gt;&lt;b&gt;Install:&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Right now I&amp;rsquo;ve only deployed &lt;a href="http://gemcutter.org/gems/view_mapper"&gt;View Mapper on gemcutter.org&lt;/a&gt;; if you haven&amp;rsquo;t already you first need to install gemcutter as a gem source:&lt;/p&gt;
&lt;pre&gt;gem sources -a http://gemcutter.org&lt;/pre&gt;
&lt;p&gt;Then just install it like any other gem:&lt;/p&gt;
&lt;pre&gt;sudo gem install view_mapper&lt;/pre&gt;
&lt;p /&gt;
&lt;p /&gt;
&lt;p&gt;&lt;b&gt;Usage:&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Two generators are provided, called view_for and scaffold_for_view:&lt;/p&gt;
&lt;p /&gt;
&lt;pre&gt;script/generate view_for model [ --view view_name:param ]&lt;/pre&gt;
    &lt;p&gt;This will generate the specified view code for an existing model. The view_for generator will look for your model, inspect all of its columns and then generate standard Rails scaffolding containing a form field for each existing column.&lt;/p&gt;
    &lt;p&gt;If you also specify a view, then a custom view will be created using the specified Rails feature or plugin, using the specified parameter.&lt;/p&gt;
&lt;p /&gt;
&lt;pre&gt;script/generate scaffold_for_view model attributes [ --view view_name:param ]&lt;/pre&gt;
    &lt;p&gt;If you don&amp;rsquo;t specify a view, then this command is identical to the standard Rails scaffold generator.&lt;/p&gt;
    &lt;p&gt;If you do specify a view, then the entire working set of a model, views and controller will be generated to implement the specified Rails feature or plugin, using the specified parameter.&lt;/p&gt;
&lt;p /&gt;
&lt;p /&gt;
&lt;p&gt;&lt;b&gt;Views:&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Right now, I&amp;rsquo;ve implemented four views:
&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://patshaughnessy.net/2009/10/1/auto_complete-scaffolding"&gt;auto_complete&lt;/a&gt;: Uses the standard Rails auto_complete plugin to implement type ahead behavior for the specified field.&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://patshaughnessy.net/2009/10/16/paperclip-scaffolding"&gt;paperclip&lt;/a&gt;: Uses the Paperclip plugin to upload and download file attachments.&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://patshaughnessy.net/2009/11/9/scaffolding-for-complex-forms-using-nested-attributes"&gt;has_many&lt;/a&gt;: Displays a complex form to edit two or more associated models.&lt;/li&gt;
  &lt;li&gt;(Default) If no view is specified, then standard Rails scaffold code will be generated.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ll be implementing more views in the coming weeks and months. There is also an API for implementing your own View Mapper module, for example to generate code illustrating how to use a plugin or gem you are working on. In the future I&amp;rsquo;ll document this as well.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-10-01:1186</id>
    <published>2009-10-01T22:20:00Z</published>
    <updated>2009-10-01T22:27:35Z</updated>
    <category term="auto_complete" />
    <category term="Rails" />
    <category term="auto_complete" />
    <category term="rails" />
    <category term="view_mapper" />
    <link href="http://patshaughnessy.net/2009/10/1/auto_complete-scaffolding" rel="alternate" type="text/html" />
    <title>Auto_complete scaffolding</title>
<content type="html">
            &lt;p&gt;I&amp;rsquo;ve written a lot here about the Rails auto_complete plugin; I&amp;rsquo;ve also &lt;a href="http://patshaughnessy.net/repeated_auto_complete"&gt;refactored the auto_complete plugin to support repeated fields and named scopes&lt;/a&gt;. Today I&amp;rsquo;d like to show how you can automatically generate Rails view and controller code with auto_complete behavior for one of your models using a new gem I&amp;rsquo;ve written called &lt;a href="http://patshaughnessy.net/view_mapper"&gt;View Mapper&lt;/a&gt;. If you&amp;rsquo;ve never used the auto_complete plugin before this is a great way to learn quickly how to use it in your app; even if you are familiar with the plugin using scaffolding like this can help to get a working auto_complete form up and running quickly and let you concentrate on more important parts of your app.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say you have an existing model in your app called &amp;ldquo;Person:&amp;rdquo;&lt;/p&gt;
&lt;pre&gt;Class Person &amp;lt; ActiveRecord::Base
end&lt;/pre&gt;
&lt;p&gt;And suppose the Person model has two string attributes for the person&amp;rsquo;s name and the name of the office they work in:&lt;/p&gt;
&lt;pre&gt;class CreatePeople &amp;lt; ActiveRecord::Migration
  def self.up
    create_table :people do |t|
      t.string :name
      t.string :office
      etc&amp;hellip;&lt;/pre&gt;
&lt;p&gt;Now let&amp;rsquo;s install View Mapper so we can generate an auto_complete view for our person model. Since I&amp;rsquo;ve only deployed &lt;a href="http://gemcutter.org/gems/view_mapper"&gt;view_mapper on gemcutter.org&lt;/a&gt; for now, you&amp;rsquo;ll also need to add gemcutter as a gem source if you haven&amp;rsquo;t already.&lt;/p&gt;
&lt;pre&gt;$ gem sources -a http://gemcutter.org
http://gemcutter.org added to sources
$ sudo gem install view_mapper
Successfully installed view_mapper-0.1.0
1 gem installed
Installing ri documentation for view_mapper-0.1.0...
Installing RDoc documentation for view_mapper-0.1.0...&lt;/pre&gt;
&lt;p&gt;Now with view_mapper you can run a single command to generate scaffolding that displays the your existing person model&amp;rsquo;s fields in a form with auto_complete type ahead behavior for the office field:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate view_for person --view auto_complete:office
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/people
      exists  app/views/layouts/
      exists  test/functional/
      exists  test/unit/
      create  test/unit/helpers/
      exists  public/stylesheets/
      create  app/views/people/index.html.erb
      create  app/views/people/show.html.erb
      create  app/views/people/new.html.erb
      create  app/views/people/edit.html.erb
      create  app/views/layouts/people.html.erb
      create  public/stylesheets/scaffold.css
      create  app/controllers/people_controller.rb
      create  test/functional/people_controller_test.rb
      create  app/helpers/people_helper.rb
      create  test/unit/helpers/people_helper_test.rb
       route  map.resources :people
       route  map.connect &amp;#x27;auto_complete_for_person_office&amp;#x27;,
                          :controller =&amp;gt; &amp;#x27;people&amp;#x27;,
                          :action =&amp;gt; &amp;#x27;auto_complete_for_person_office&amp;#x27;&lt;/pre&gt;
&lt;p&gt;This works just like the Rails scaffold generator, except that the view_for generator has also:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;inspected your person model and found the name and office columns.&lt;/li&gt;
  &lt;li&gt;added a route for &amp;ldquo;auto_complete_for_person_office&amp;rdquo; to routes.rb.&lt;/li&gt;
  &lt;li&gt;added a call to &amp;ldquo;auto_complete_for :person, :office&amp;rdquo; to PersonController.&lt;/li&gt;
  &lt;li&gt;used text_field_for_auto_complete on the office field in your new and edit forms.&lt;/li&gt;
  &lt;li&gt;inserted &amp;ldquo;javascript_include_tag :defaults&amp;rdquo; into views/layouts/people.html.erb to load the prototype javascript library.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you start up your application and create a few person records with names and addresses, then you will see the auto_complete plugin working!&lt;/p&gt;
&lt;p&gt;&lt;img src="http://patshaughnessy.net/assets/2009/10/1/person-autocomplete.png" /&gt;&lt;/p&gt;
&lt;p&gt;With this working example right inside your application, you can easily review exactly how the view, route and controller files use auto_complete. After that you can adapt the view to fit into your application&amp;rsquo;s design and delete the scaffolding you don&amp;rsquo;t really need or want.&lt;/p&gt;
&lt;p&gt;As another example, let&amp;rsquo;s create an entirely new Rails application completely from scratch, and use View Mapper to setup auto_complete inside it:&lt;/p&gt;
&lt;pre&gt;$ rails auto_complete_example
      create  
      create  app/controllers
      create  app/helpers
      create  app/models
      create  app/views/layouts
      etc&amp;hellip;
$ cd auto_complete_example&lt;/pre&gt;
&lt;p&gt;First, let&amp;rsquo;s install the auto_complete plugin. (In a future post I&amp;rsquo;ll show how to use View Mapper with my fork of auto_complete in a complex form.)&lt;/p&gt;
&lt;pre&gt;$ ./script/plugin install git://github.com/rails/auto_complete.git
Initialized empty Git repository in /Users/pat/rails-apps/auto_complete_example/vendor/plugins/auto_complete/.git/
remote: Counting objects: 13, done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 13 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (13/13), done.
From git://github.com/rails/auto_complete
 * branch            HEAD       -&amp;gt; FETCH_HEAD&lt;/pre&gt;
&lt;p&gt;Now that we have the plugin installed, let&amp;rsquo;s create our scaffolding. Along with the 
 &amp;ldquo;view_for&amp;rdquo; generator I used above, View Mapper also provides a generator called &amp;ldquo;scaffold_for_view.&amp;rdquo; This works the same way, except it just creates a new model the same way the Rails scaffold generator does, instead of inspecting an existing model.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create the same person model we used above, and an auto_complete view:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate scaffold_for_view person name:string office:string
                                      --view auto_complete:office
      exists  app/models/
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/people
      exists  app/views/layouts/
      exists  test/functional/
      exists  test/unit/
      create  test/unit/helpers/
      exists  public/stylesheets/
      create  app/views/people/index.html.erb
      create  app/views/people/show.html.erb
      create  app/views/people/new.html.erb
      create  app/views/people/edit.html.erb
      create  app/views/layouts/people.html.erb
      create  public/stylesheets/scaffold.css
      create  app/controllers/people_controller.rb
      create  test/functional/people_controller_test.rb
      create  app/helpers/people_helper.rb
      create  test/unit/helpers/people_helper_test.rb
       route  map.resources :people
  dependency  model
      exists    app/models/
      exists    test/unit/
      exists    test/fixtures/
      create    app/models/person.rb
      create    test/unit/person_test.rb
      create    test/fixtures/people.yml
      create    db/migrate
      create    db/migrate/20091001161349_create_people.rb
       route  map.connect &amp;#x27;auto_complete_for_person_office&amp;#x27;,
                          :controller =&amp;gt; &amp;#x27;people&amp;#x27;,
                          :action =&amp;gt;&amp;#x27;auto_complete_for_person_office&amp;#x27;&lt;/pre&gt;
&lt;p&gt;Note the syntax is the same as the standard Rails scaffold generator, except I&amp;rsquo;ve added the &amp;ldquo;view&amp;rdquo; parameter to specify we want the auto_complete plugin to be used in the view.&lt;/p&gt;
&lt;p&gt;Now we just need to migrate the database schema and run our app:&lt;/p&gt;
&lt;pre&gt;$ rake db:migrate
(in /Users/pat/rails-apps/auto_complete_example)
==  CreatePeople: migrating ===================================================
-- create_table(:people)
   -&amp;gt; 0.0012s
==  CreatePeople: migrated (0.0015s) ==========================================&lt;/pre&gt;
&lt;p&gt;And if you add a few records, you&amp;rsquo;ll see auto_complete working!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll be adding more views to View Mapper soon, and in future posts here I&amp;rsquo;ll write about how to generate scaffolding for Paperclip file attachments, my version of auto_complete used on a complex form, and also how to write your own views for View Mapper.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-09-02:835</id>
    <published>2009-09-02T19:03:00Z</published>
    <updated>2009-09-02T19:04:06Z</updated>
    <category term="Rails" />
    <category term="generators" />
    <category term="rails" />
    <link href="http://patshaughnessy.net/2009/9/2/rails-generator-tutorial-part-2-writing-a-custom-manifest-action" rel="alternate" type="text/html" />
    <title>Rails generator tutorial part 2: writing a custom manifest action</title>
<content type="html">
            &lt;p&gt;In &lt;a href="http://patshaughnessy.net/2009/8/23/tutorial-how-to-write-a-rails-generator"&gt;part one of this tutorial&lt;/a&gt; I wrote a simple rails generator that creates a controller code file in app/controllers. This time I want to finish up my simple &amp;ldquo;VersionGenerator&amp;rdquo; example by enabling it to add a line to the routes.rb file. In other words, I want to be able to use a manifest action called &amp;ldquo;route&amp;rdquo; like this:&lt;/p&gt;
&lt;pre&gt;def manifest
    record do |m|
      m.template(&amp;#x27;controller.rb&amp;#x27;, &amp;#x27;app/controllers/version_controller.rb&amp;#x27;)
      &lt;b&gt;m.route :name =&amp;gt; &amp;#x27;version&amp;#x27;,
              :controller =&amp;gt; &amp;#x27;version&amp;#x27;,
              :action =&amp;gt; &amp;#x27;display_version&amp;#x27;&lt;/b&gt;
    end
  end&lt;/pre&gt;
&lt;p&gt;The problem for today is how to implement the &amp;ldquo;route&amp;rdquo; action, which is not supported by Rails by default. The Rails generator base class code does provide a few other actions you can use in your manifest, like &amp;ldquo;file&amp;rdquo; or &amp;ldquo;directory,&amp;rdquo; which create a file or directory. Rails even provides a method called &amp;ldquo;route_resources&amp;rdquo; to add a &amp;ldquo;map.resources&amp;rdquo; line to routes.rb, but not a simple named route line like what we need for this example.&lt;/p&gt;
&lt;p&gt;This specific action might be useful for you, but my real goal is to explore how Rails generators work in general and discuss some of the issues you might run into if you need a custom manifest action like this for any purpose. Let&amp;rsquo;s get started by just adding the new action method we need right inside our generator class&amp;hellip;&lt;/p&gt;
&lt;pre&gt;def route(route_options)
  puts &amp;quot;This will create a new route!&amp;quot;
end&lt;/pre&gt;
&lt;p&gt;&amp;hellip;and see what happens when we run script/generate with manifest method above:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate version ../build-info/version.txt 
   identical  app/controllers/version_controller.rb
This will create a new route!&lt;/pre&gt;
&lt;p&gt;Very promising! All we need to do is add the necessary code here and we&amp;rsquo;ll be all set. But first let&amp;rsquo;s take a closer look at what&amp;rsquo;s happening by adding a call to &amp;ldquo;caller&amp;rdquo; inside this new method and see how it&amp;rsquo;s being called by the Rails generator system:&lt;/p&gt;
&lt;pre&gt;def route(route_options)
  puts &amp;quot;This will create a new route!&amp;quot;
  puts caller
end&lt;/pre&gt;
&lt;p&gt;Here&amp;rsquo;s what is displayed when we run this (paths shortened for readability):&lt;/p&gt;
&lt;pre&gt;$ ./script/generate version ../build-info/version.txt
   identical  app/controllers/version_controller.rb
This will create a new route!
/usr/local/lib/ruby/1.8/delegate.rb:270:in `__send__&amp;#x27;
/usr/local/lib/ruby/1.8/delegate.rb:270:in `method_missing&amp;#x27;
/path/to/rails-2.3.2/lib/rails_generator/manifest.rb:47:in `send&amp;#x27;
/path/to/rails-2.3.2/lib/rails_generator/manifest.rb:47:in `send_actions&amp;#x27;
/path/to/rails-2.3.2/lib/rails_generator/manifest.rb:46:in `each&amp;#x27;
/path/to/rails-2.3.2/lib/rails_generator/manifest.rb:46:in `send_actions&amp;#x27;
/path/to/rails-2.3.2/lib/rails_generator/manifest.rb:31:in `replay&amp;#x27;
/path/to/rails-2.3.2/lib/rails_generator/commands.rb:42:in `invoke!&amp;#x27;
&lt;b&gt;/path/to/rails-2.3.2/lib/rails_generator/scripts/../scripts.rb:31:in `run&amp;#x27;&lt;/b&gt;
/path/to/rails-2.3.2/lib/commands/generate.rb:6
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require&amp;#x27;
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require&amp;#x27;
./script/generate:3&lt;/pre&gt;
&lt;p&gt;There&amp;rsquo;s a lot going on here; in fact, when I started to learn more about Rails generators and how they work I was shocked at how complicated their object model and design are. I won&amp;rsquo;t try to explain all of it here, but let&amp;rsquo;s take a closer look at the one line I bolded above: line 31 of &lt;a href="http://github.com/rails/rails/blob/a147becfb86b689ab25e92edcfbb4bcc04108099/railties/lib/rails_generator/scripts.rb#L31"&gt;lib/rails_generator/scripts.rb&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;Rails::Generator::Base.instance(options[:generator], args, options)
                      .command(options[:command]).invoke!&lt;/pre&gt;
&lt;p&gt;This is called when you run script/generate, by the &amp;ldquo;Rails::Generator::Scripts::Generate&amp;rdquo; class. Translating this line of Ruby into English, we get: &amp;ldquo;Create an instance of the specified generator, passing in the arguments and options provided on the command line; then create an instance of the specified command that uses that generator; then invoke the command.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;What this means is that actually Rails generator classes do not do the real work of generating code &amp;ndash; Rails generator &amp;ldquo;commands&amp;rdquo; do! The &lt;a href="http://github.com/rails/rails/blob/a147becfb86b689ab25e92edcfbb4bcc04108099/railties/lib/rails_generator/commands.rb"&gt;lib/rails_generator/commands.rb&lt;/a&gt; file defines a series of command objects inside the Rails::Generator::Commands module. The two most important command classes are Create and Destroy.  The &amp;ldquo;Create&amp;rdquo; command is called when you execute script/generate, like what happened in the stack trace above. This class contains the implementation of the &amp;ldquo;template&amp;rdquo; method we used before, plus various other methods like &amp;ldquo;file&amp;rdquo; and &amp;ldquo;directory&amp;rdquo; that create files and directories, etc.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;Destroy&amp;rdquo; command is called when you execute script/destroy from the command line (I removed &amp;ldquo;puts caller&amp;rdquo; first before running this):&lt;/p&gt;
&lt;pre&gt;$ ./script/destroy version ../build-info/version.txt 
This will create a new route!
          rm  app/controllers/version_controller.rb&lt;/pre&gt;
&lt;p&gt;This class has all of the same methods that the Create class does, except that they perform the opposite action: instead of creating a file or directory, they delete them. The Destroy class also executes the actions in the opposite order, by looping backwards through the manifest that we recorded in our generator. Here the destroy command has deleted our version_controller.rb file we generated earlier. Note that it still displays &amp;ldquo;This will create a new route!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interesting in diving into the real details about how Rails generators work, then read the code in &lt;a href="http://github.com/rails/rails/blob/a147becfb86b689ab25e92edcfbb4bcc04108099/railties/lib/rails_generator/commands.rb"&gt;commands.rb&lt;/a&gt; very carefully. In particular, look at how the &amp;ldquo;self.included&amp;rdquo; and &amp;ldquo;self.instance&amp;rdquo; methods at the top work; these methods are used in the line I showed above to create the specified command, supplying the specified generator as an argument to the command constructor. The &amp;ldquo;invoke!&amp;rdquo; method on commands actually plays back the recorded manifest. Also all of the actions that are available to your generator's manifest method are defined in this file. One other interesting detail I don&amp;rsquo;t have space to explain carefully here is that the command objects contain the corresponding generator class as a delegate object; in other words they contain an instance of the generator as a member variable:&lt;/p&gt;
&lt;pre&gt;# module Rails::Generator::Commands...
class Base &amp;lt; DelegateClass(Rails::Generator::Base)&lt;/pre&gt;
&lt;p&gt;This explains the top two lines in the stack trace above:&lt;/p&gt;
&lt;pre&gt;/usr/local/lib/ruby/1.8/delegate.rb:270:in `__send__&amp;#x27;
/usr/local/lib/ruby/1.8/delegate.rb:270:in `method_missing&amp;#x27;&lt;/pre&gt;
&lt;p&gt;&amp;ldquo;DelegateClass&amp;rdquo; is defined by delegate.rb, which is a &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/delegate/rdoc/index.html"&gt;Ruby library that implements the delegate pattern&lt;/a&gt;. This is why we were able to add the new &amp;ldquo;route&amp;rdquo; method right in our generator; when Ruby found the &amp;ldquo;route&amp;rdquo; method missing in the Create command, it delegated the call to our generator object.&lt;/p&gt;
&lt;p&gt;Obviously we have a problem here: our new &amp;ldquo;route&amp;rdquo; method needs to be able to remove a route from routes.rb if the Destroy command is called, as well as create a new one for the Create command. One way to implement our new &amp;ldquo;route&amp;rdquo; method would be check the &amp;ldquo;options[:command]&amp;rdquo; value that we saw above on &lt;a href="http://github.com/rails/rails/blob/a147becfb86b689ab25e92edcfbb4bcc04108099/railties/lib/rails_generator/scripts.rb#L31"&gt;line 31 of scripts.rb&lt;/a&gt;, like this:&lt;/p&gt;
&lt;pre&gt;def route(route_options)
  if options[:command] == :create
    puts &amp;quot;This will add a new route to routes.rb.&amp;quot;
  elsif options[:command] == :destroy
    puts &amp;quot;This will remove the new route from routes.rb.&amp;quot;
  end
end&lt;/pre&gt;
&lt;p&gt;Now if we run script/generate again, our new method will create a route:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate version ../build-info/version.txt
      create  app/controllers/version_controller.rb
This will add a new route to routes.rb.&lt;/pre&gt;
&lt;p&gt;And if we run the destroy command, we&amp;rsquo;ll remove the route:&lt;/p&gt;
&lt;pre&gt;$ ./script/destroy version ../build-info/version.txt 
This will remove the new route from routes.rb.
          rm  app/controllers/version_controller.rb&lt;/pre&gt;
&lt;p&gt;It turns out a cleaner way to implement the &amp;ldquo;route&amp;rdquo; method is to directly add the method to both the Create and Destroy command classes. This allows me to call a utility method called &amp;ldquo;gsub_file&amp;rdquo; in the Rails::Generator::Commands::Base class which I wouldn&amp;rsquo;t have direct access to from my generator class. It also avoids the somewhat ugly if statement on the options[:command] value, and finally it might make it easier for me someday to refactor the new route methods into a separate module that I could use with various different generators that might need to add and remove routes.&lt;/p&gt;
&lt;p&gt;Anyway, here&amp;rsquo;s the finished code for the entire generator:&lt;/p&gt;
&lt;pre&gt;class VersionGenerator &amp;lt; Rails::Generator::NamedBase
  attr_reader :version_path
  def initialize(runtime_args, runtime_options = {})
    super
    @version_path = File.join(RAILS_ROOT, name)
  end
  def manifest
    record do |m|
      m.template(&amp;#x27;controller.rb&amp;#x27;, &amp;#x27;app/controllers/version_controller.rb&amp;#x27;)
      m.route :name =&amp;gt; &amp;#x27;version&amp;#x27;,
              :controller =&amp;gt; &amp;#x27;version&amp;#x27;,
              :action =&amp;gt; &amp;#x27;display_version&amp;#x27;
    end
  end
end

module Rails
  module Generator
    module Commands

      class Base
        def route_code(route_options)
          &amp;quot;map.#{route_options[:name]} &amp;#x27;#{route_options[:name]}&amp;#x27;, :controller =&amp;gt; &amp;#x27;#{route_options[:controller]}&amp;#x27;, :action =&amp;gt; &amp;#x27;#{route_options[:action]}&amp;#x27;&amp;quot;
        end
      end

# Here's a readable version of the long string used above in route_code;
# but it should be kept on one line to avoid inserting extra whitespace
# into routes.rb when the generator is run:
# &amp;quot;map.#{route_options[:name]} &amp;#x27;#{route_options[:name]}&amp;#x27;,
#     :controller =&amp;gt; &amp;#x27;#{route_options[:controller]}&amp;#x27;,
#     :action =&amp;gt; &amp;#x27;#{route_options[:action]}&amp;#x27;&amp;quot;

      class Create
        def route(route_options)
          sentinel = &amp;#x27;ActionController::Routing::Routes.draw do |map|&amp;#x27;
          logger.route route_code(route_options)
          gsub_file &amp;#x27;config/routes.rb&amp;#x27;, /(#{Regexp.escape(sentinel)})/mi do |m|
              &amp;quot;#{m}\n  #{route_code(route_options)}\n&amp;quot;
          end
        end
      end

      class Destroy
        def route(route_options)
          logger.remove_route route_code(route_options)
          to_remove = &amp;quot;\n  #{route_code(route_options)}&amp;quot;
          gsub_file &amp;#x27;config/routes.rb&amp;#x27;, /(#{to_remove})/mi, &amp;#x27;&amp;#x27;
        end
      end

    end
  end
end&lt;/pre&gt;
&lt;p&gt;More or less copied from the existing route_resources action found in &lt;a href="http://github.com/rails/rails/blob/a147becfb86b689ab25e92edcfbb4bcc04108099/railties/lib/rails_generator/commands.rb"&gt;commands.rb&lt;/a&gt;, this works as follows: If we call script/generate then the route action method in the Create command class is called. This uses gsub_file to look for the &amp;ldquo;sentinel&amp;rdquo; or target area of the file and replaces it with the sentinel + the new route code. I also use the &amp;ldquo;logger&amp;rdquo; method to display log messages using the Rails::Generator::SimpleLogger class. Here&amp;rsquo;s what it looks like on the command line:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate version ../build-info/version.txt
      create  app/controllers/version_controller.rb
       route  map.version &amp;#x27;version&amp;#x27;,
                 :controller =&amp;gt; &amp;#x27;version&amp;#x27;,
                 :action =&amp;gt; &amp;#x27;display_version&amp;#x27;&lt;/pre&gt;
&lt;p&gt;If script/destroy is called, then the second route implementation in the Destroy class is called. This uses gsub_file to remove the route code. Finally, the &amp;ldquo;route_code&amp;rdquo; method returns the route code that we want to generate or remove from routes.rb. This time on the command line we get:&lt;/p&gt;
&lt;pre&gt;$ ./script/destroy version ../build-info/version.txt 
remove_route  map.version 'version',
                 :controller =&gt; 'version',
                 :action =&gt; 'display_version'
          rm  app/controllers/version_controller.rb&lt;/pre&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-08-23:723</id>
    <published>2009-08-23T12:03:00Z</published>
    <updated>2009-08-23T12:19:15Z</updated>
    <category term="Rails" />
    <category term="generators" />
    <category term="rails" />
    <link href="http://patshaughnessy.net/2009/8/23/tutorial-how-to-write-a-rails-generator" rel="alternate" type="text/html" />
    <title>Tutorial: How to write a Rails generator</title>
<content type="html">
            &lt;p&gt;I&amp;rsquo;ve been working on a generator called &lt;a href="http://patshaughnessy.net/2009/7/24/generating-view-scaffolding-code-for-existing-models"&gt;ViewMapper&lt;/a&gt; recently that allows you to create view scaffolding from an existing model. I found writing a Rails generator to be somewhat confusing and hard to do: Where do I need to put my generator class? What does it need to be called? How does it work? This article will show step by step how to write your own Rails generator from scratch &amp;ndash; hopefully it will save you some time if you ever need to write your own.&lt;/p&gt;
&lt;p&gt;First let&amp;#x27;s think of some sample Rails code that I might want to generate as an example. This is admittedly contrived, but it&amp;rsquo;s short and simple enough to show here while still interesting enough to illustrate how a generator would work. Let&amp;rsquo;s suppose my Capistrano deployment scripts wrote the last commit information from Git into a file called &amp;ldquo;version.txt&amp;rdquo; in a folder RAILS_ROOT/../build-info:&lt;/p&gt;
&lt;pre&gt;commit 217d9bd1d1d508a0f7f1e7afa2b489b130196e33
Author: Pat Shaughnessy &amp;lt;pat@patshaughnessy.net&amp;gt;
Date:   Wed Aug 5 07:45:01 2009 -0400&lt;/pre&gt;
&lt;p&gt;Now with a controller like this I could display the info, helping me keep track of what version is running on a given development development, QA or production server:&lt;/p&gt;
&lt;pre&gt;class VersionController &amp;lt; ApplicationController
  VERSION_FILE = &amp;#x27;../build-info/version.txt&amp;#x27;
  def display_version
    path = File.join(RAILS_ROOT, VERSION_FILE)
    render path
  end
end&lt;/pre&gt;
&lt;p&gt;If I add a route to this action like this in config/routes.rb:&lt;/p&gt;
&lt;pre&gt;map.version 'version', :controller =&gt; 'version', :action =&gt; 'display_version'&lt;/pre&gt;
&lt;p&gt;&amp;hellip;then I&amp;rsquo;ll get the Git last commit info by just opening http://servername/version in my browser. Obviously it would be simpler to just put the version.txt file under the public folder&amp;hellip; but let&amp;rsquo;s continue with this contrived example for now. Now let&amp;rsquo;s say I have 5 or 10 different Rails apps, and that I&amp;rsquo;d like to add the same controller and route to each one. Let&amp;rsquo;s write a simple Rails generator that would make this easy to do, called the &amp;ldquo;version&amp;rdquo; generator. Here&amp;rsquo;s how to do it&amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;lt;u&gt;Step 1: A skeleton Rails generator&amp;lt;/u&gt;&lt;/p&gt;
&lt;p&gt;All Rails generators are derived from a class called &amp;ldquo;Rails::Generator::Base.&amp;rdquo; You can find the source code for this file in &lt;a href="http://github.com/rails/rails/blob/a147becfb86b689ab25e92edcfbb4bcc04108099/railties/lib/rails_generator/base.rb"&gt;vendor/rails/railties/lib/rails_generator/base.rb&lt;/a&gt; (link is to the Rails 2.3.3 version). Definately read the source code; there is helpful documentation in the comments and understanding the base class code is indispensible if you plan to use it for your generator.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an empty, skeleton Rails generator that we can use as a starting point:&lt;/p&gt;
&lt;pre&gt;class VersionGenerator &amp;lt; Rails::Generator::Base
  def manifest
    record do |m|
      # Do something
    end
  end
end&lt;/pre&gt;
&lt;p&gt;The name of the class is important: since we want a &amp;ldquo;version&amp;rdquo; generator we need to create a class called &amp;ldquo;VersionGenerator.&amp;rdquo; The other important detail here is where this class is located: we need to put it in lib/generators/version/version_generator.rb. The reason for all of this is that the code called by script/generate takes the generator name and looks for the corresponding generator class in this location. We can check that our class is being found by just running script/generate with no parameters, like this:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate 
Usage: ./script/generate generator [options] [args]
&amp;hellip;etc&amp;hellip;
Installed Generators
  &lt;b&gt;Lib: version&lt;/b&gt;
  Rubygems: cucumber, feature, install_rubigen_scripts, integration_spec, rspec, rspec_controller, rspec_model, rspec_scaffold, session
  Builtin: controller, helper, integration_test, mailer, metal, migration, model, observer, performance_test, plugin, resource, scaffold, session_migration&lt;/pre&gt;
&lt;p&gt;Note that our new &amp;ldquo;version&amp;rdquo; generator is listed as &amp;ldquo;Lib: version,&amp;rdquo; in bold above. The other generators found on my system were either part of Rails or else part of a gem or plugin. If you don&amp;rsquo;t see your generator in this list, or if it has the wrong name then double check your folder name: it should be lib/generators/XYZ or lib/generators/version in this example. After you finish developing your generator you'll want to move it into a plugin or gem so it can be reused in different apps on your machine; then "version" would appear in the "Rubygems" list for example.&lt;/p&gt;
&lt;p&gt;If we try running our empty generator, we&amp;rsquo;ll get no output or changes; not a surprise:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate version&lt;/pre&gt;
&lt;p&gt;If you see an error like this:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate version
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:
in `gem_original_require&amp;#x27;: no such file to load --
/path/to/myapp/lib/generators/version/version_generator.rb (MissingSourceFile)&lt;/pre&gt;
&lt;p&gt;Then you have the wrong file name&amp;hellip; it needs to be XYZ_generator.rb, or version_generator.rb in this example. Or if you see:&lt;/p&gt;
&lt;pre&gt;Missing VersionGenerator class in
  /path/to/myapp/lib/generators/version/version_generator.rb&lt;/pre&gt;
&lt;p&gt;&amp;hellip; then you have the wrong class name inside this file. It needs to be XYZGenerator, or VersionGenerator in this example.&lt;/p&gt;
&lt;p&gt;&amp;lt;u&gt;Step 2: Creating code using an ERB template&amp;lt;/u&gt;&lt;/p&gt;
&lt;p&gt;The way Rails generators work is by creating code using ERB, in just the same way that view code generates HTML for a Rails web site. To see how this works and to take the next step towards writing our version generator, let&amp;rsquo;s create a new template file for our version controller. Create a new text file called &amp;ldquo;controller.rb&amp;rdquo; and put it into this folder: lib/generators/version/templates/controller.rb; in other words, into a new subfolder under version called &amp;ldquo;templates.&amp;rdquo; Next, paste in the controller code from above:&lt;p&gt;
&lt;pre&gt;class VersionController &amp;lt; ApplicationController
  VERSION_FILE = &amp;#x27;../build-info/version.txt&amp;#x27;
  def display_version
    path = File.join(RAILS_ROOT, VERSION_FILE)
    render path
  end
end&lt;/pre&gt;
&lt;p&gt;Now if we add this line to our manifest method back in the VersionGenerator class:&lt;/p&gt;
&lt;pre&gt;def manifest
  record do |m|
    &lt;b&gt;m.template(&amp;#x27;controller.rb&amp;#x27;, &amp;#x27;app/controllers/version_controller.rb&amp;#x27;)&lt;/b&gt;
  end
end&lt;/pre&gt;
&lt;p&gt;&amp;hellip; a new code file called version_controller.rb will be generated inside of the app/controllers folder in our app when we run the generator:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate version
    create  app/controllers/version_controller.rb&lt;/pre&gt;
&lt;p&gt;If you take a look at this new version_controller.rb file, you&amp;rsquo;ll just see the code we pasted into the controller.rb template file. Here&amp;rsquo;s what happened when we ran script/generate version:&lt;/p&gt;
&lt;p&gt;
  &lt;ul&gt;
    &lt;li&gt;The Rails code called by script/generate looked for the &amp;ldquo;version&amp;rdquo; generator, by looking for a class called &amp;ldquo;VersionGenerator&amp;rdquo; in the lib/generators/version folder, among other places.&lt;/li&gt;
    &lt;li&gt;It called the &amp;ldquo;manifest&amp;rdquo; method in VersionGenerator. Using the &amp;ldquo;record&amp;rdquo; utility method, a series of actions are recorded that the Rails generator base classes will execute later. In our case, there&amp;rsquo;s only one action: &amp;ldquo;template.&amp;rdquo;&lt;/li&gt;
    &lt;li&gt;The template action indicates that the Rails generator code should run an ERB transformation to generate new code, using the &amp;ldquo;controller.rb&amp;rdquo; file. The generated code will then be copied to the app/controllers/version_controller.rb file.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;To make our generator interesting, let&amp;rsquo;s provide a parameter to it that indicates the path of the file containing the version information, instead of hard coding &amp;ldquo;version.txt.&amp;rdquo; To do that we can take advantage of another Rails built in class called &amp;ldquo;Rails::Generator::NamedBase&amp;rdquo;. If we derive our VersionGenerator class from NamedBase instead of Base, then we&amp;rsquo;ll get the ability to take a name parameter from the script/generate command line for free. Let start by changing our base class in version_generator.rb:&lt;/p&gt;
&lt;pre&gt;class VersionGenerator &amp;lt; Rails::Generator::&lt;b&gt;NamedBase&lt;/b&gt;&lt;/pre&gt;
&lt;p&gt;Now if you run the generator, you&amp;rsquo;ll get some helpful usage information:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate version
Usage: ./script/generate version VersionName [options]
Etc&amp;hellip;&lt;/pre&gt;
&lt;p&gt;Here the NamedBase class has written the usage info, explaining that an additional parameter is now expected. If we re-run the generator and add the version file name as a parameter, here&amp;rsquo;s what we&amp;rsquo;ll get:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate version ../build-info/version.txt
   identical  app/controllers/version_controller.rb&lt;/pre&gt;
&lt;p&gt;This shows a helpful feature of Rails generators: they check if you&amp;rsquo;re about to overwrite some existing code with the new, generated code. In this case, since we already had a controller called &amp;ldquo;version_controller.rb&amp;rdquo; the Rails generator code displayed the &amp;ldquo;identical&amp;rdquo; message. Our new generated controller is identical to the previous one since we haven&amp;rsquo;t used the version name parameter yet. To take advantage of the version file name parameter and our new NamedBase base class, we need to add some new code to VersionGenerator, in bold:&lt;/p&gt;
&lt;pre&gt;class VersionGenerator &amp;lt; Rails::Generator::NamedBase
  &lt;b&gt;attr_reader :version_path
  def initialize(runtime_args, runtime_options = {})
    super
    @version_path = File.join(RAILS_ROOT, name)
  end&lt;/b&gt;
  def manifest
    record do |m|
      m.template(&amp;#x27;controller.rb&amp;#x27;, &amp;#x27;app/controllers/version_controller.rb&amp;#x27;)
    end
  end
end&lt;/pre&gt;
&lt;p&gt;The way this works is:
  &lt;ul&gt;
    &lt;li&gt;The NamedBase base class parses the script/generate command line, expecting an additional parameter which indicates the name of some object.&lt;/li&gt;
    &lt;li&gt;This name is provided in "name," an instance variable/attribute of the NamedBase class.&lt;/li&gt;
    &lt;li&gt;The VersionGenerator class assumes "name" indicates the relative path of a version file, determines the full path of the file and then saves the full path in the @version_path attribute.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;I mentioned above that Rails generators work by running an ERB transformation; to try using ERB in this example, we just need to refer to the new &amp;ldquo;version_path&amp;rdquo; attribute inside the controller.rb template file, like this:&lt;/p&gt;
&lt;pre&gt;class VersionController &amp;lt; ApplicationController
  VERSION_PATH = &amp;#x27;&amp;lt;%= version_path %&amp;gt;&amp;#x27;
  def display_version
    render VERSION_PATH
   end
end&lt;/pre&gt;
&lt;p&gt;The &amp;ldquo;version_path&amp;rdquo; variable in this template refers to the version_path attribute of the VersionGenerator class above. I&amp;rsquo;ve also removed the File.join line from here since we now handle that in the generator itself. If we run the generate command and provide the name of the version file, we&amp;rsquo;ll get this result:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate version ../build-info/version.txt
overwrite app/controllers/version_controller.rb? (enter &amp;quot;h&amp;quot; for help) [Ynaqdh] Y
       force  app/controllers/version_controller.rb&lt;/pre&gt;
&lt;p&gt;As I mentioned above, Rails checks whether you&amp;rsquo;re about to overwrite some existing code file. Since in this case our controller code file is now different that what we had before (VERSION_PATH and not VERSION_FILE; no File.join, etc.) we get an overwrite warning. I just entered &amp;ldquo;Y&amp;rdquo; to overwrite the old file.&lt;/p&gt;
&lt;p&gt;If we look at our new controller, app/controllers/version_controller.rb, we now have:&lt;/p&gt;
&lt;pre&gt;class VersionController &amp;lt; ApplicationController
  VERSION_PATH = &amp;#x27;/path/to/myapp/../build-info/version.txt&amp;#x27;
  def display_version
    render VERSION_PATH
   end
end&lt;/pre&gt;
&lt;p&gt;We&amp;rsquo;ve successfully generated a new VersionController class, based on a parameter passed to our &amp;ldquo;version&amp;rdquo; generator. While this is a good start, to be able to use this action in our app we still need to add a route to config/routes.rb. It turns out this is a lot harder to do with a generator, since we will need to insert a new line of code in an existing file, and not just generate a new routes.rb file. We will also need to worry about how to remove the route line when script/destroy is run. It&amp;rsquo;s possible to do all of this with a Rails generator, but will require a more thorough understanding of how Rails generators actually work. I&amp;rsquo;ll explain all of that in my next post&amp;hellip;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-07-24:580</id>
    <published>2009-07-24T15:00:00Z</published>
    <updated>2009-10-01T22:43:21Z</updated>
    <category term="Rails" />
    <category term="rails" />
    <category term="view_mapper" />
    <link href="http://patshaughnessy.net/2009/7/24/generating-view-scaffolding-code-for-existing-models" rel="alternate" type="text/html" />
    <title>Generating view scaffolding code for existing models</title>
<content type="html">
            &lt;p&gt;(Updated October 2009)&lt;/p&gt;
&lt;p&gt;I just rewrote and cleaned up the code I describe below here and published it as a new gem called &lt;a href="http://gemcutter.org/gems/view_mapper"&gt;View Mapper on gemcutter.org&lt;/a&gt;. See &lt;a href="http://patshaughnessy.net/view_mapper"&gt;my usage article&lt;/a&gt; for more details. I also rethought and redesigned the commands I describe below&amp;hellip; the part about nested attributes will not work for now. I&amp;rsquo;m planning to reimplement that soon.&lt;/p&gt;
&lt;p /&gt;
&lt;p&gt;I&amp;rsquo;ve been thinking for a while that a generator that creates view scaffolding for an existing model or models would be really useful. For example, I want to be able to write this by hand:&lt;/p&gt;
&lt;pre&gt;class Group &amp;lt; ActiveRecord::Base
  has_many :people
end
class Person &amp;lt; ActiveRecord::Base
  belongs_to :group
end&lt;/pre&gt;
&lt;p&gt;&amp;hellip; and then run a generator and get a working view to edit and display groups of people. Recently I started developing a generator called &amp;ldquo;ViewMapper&amp;rdquo; that does this; see: &lt;a href="http://github.com/patshaughnessy/view_mapper"&gt;http://github.com/patshaughnessy/view_mapper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The idea is that it creates a view that maps to your existing models. Writing model classes is often very easy; using ActiveRecord allows you to write concise, short code files. However, writing a view that displays a form for these models is often very hard, requiring knowledge of a long list of Rails functions, macros, classes, as well as the usual HTML and Javascript. Right now ViewMapper it just a plugin; so you can install it into your app like this:&lt;/p&gt;
&lt;pre&gt;$ ./script/plugin install git://github.com/patshaughnessy/view_mapper.git&lt;/pre&gt;
&lt;p&gt;Probably it should be packaged as a gem instead… this is still work-in-progress. At the moment it supports:
  &lt;ul&gt;
    &lt;li&gt;Creating simple form based on the columns of an existing model&lt;/li&gt;
    &lt;li&gt;Creating a complex form based on the columns of two associated models in a many-one relationship, using nested attributes&lt;/li&gt;
  &lt;/ul&gt;
  If you&amp;rsquo;re interested and have time, try the examples below or better yet try the generator on some of your own models and let me know what you think.&lt;/p&gt;
&lt;p /&gt;
&lt;p /&gt;
&lt;p&gt;&amp;lt;u&gt;Example 1:&amp;lt;/u&gt; Create a view based on the columns of an existing model&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say I have an existing model class that manages a series of person records:&lt;/p&gt;
&lt;pre&gt;class Person &amp;lt; ActiveRecord::Base
end&lt;/pre&gt;
&lt;p&gt;Now to create the corresponding view with ViewMapper, just run this command:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate view_for person
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/people
      exists  app/views/layouts/
      exists  test/functional/
      create  test/unit/helpers/
      exists  public/stylesheets/
      create  app/views/people/index.html.erb
      create  app/views/people/show.html.erb
      create  app/views/people/new.html.erb
      create  app/views/people/edit.html.erb
      create  app/views/layouts/people.html.erb
      create  public/stylesheets/scaffold.css
      create  app/controllers/people_controller.rb
      create  test/functional/people_controller_test.rb
      create  app/helpers/people_helper.rb
      create  test/unit/helpers/people_helper_test.rb
       route  map.resources :people&lt;/pre&gt;
&lt;p&gt;If you run your Rails app you will see the usual scaffolding UI:&lt;/p&gt;
&lt;img src="http://patshaughnessy.net/assets/2009/7/24/person_new.png"&gt;
&lt;p&gt;This looks just like the scaffolding page you would have gotten from the Rails scaffolding generator. In fact, I&amp;rsquo;ve based the &amp;ldquo;view_for&amp;rdquo; generator class (ViewForGenerator) on the existing Rails ScaffoldGenerator class, so it generates the same code.&lt;/p&gt;
&lt;p&gt;The difference here is that the scaffolding code was based on the properties of the existing Person model. Here&amp;rsquo;s what the view_for generator did:
  &lt;ul&gt;
    &lt;li&gt;Find the specified model class&lt;/li&gt;
    &lt;li&gt;Inspect it and get a list of column names and data types&lt;/li&gt;
    &lt;li&gt;Create the scaffolding code as usual&lt;/li&gt;
  &lt;/ul&gt;
  If you also want to create your model class at the same time, then you don&amp;rsquo;t need ViewMapper; you would just run the standard Rails scaffold generator like this:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate scaffold person name:string age:integer&lt;/pre&gt;
&lt;p&gt;ViewMapper provides you with the flexibility to create the view scaffolding after the fact for a model you or someone else has already created in your app.&lt;/p&gt;
&lt;p /&gt;
&lt;p /&gt;
&lt;p&gt;&amp;lt;u&gt;Example 2:&amp;lt;/u&gt; Create a view using a complex form based on two associated models in a many-one relationship, using Rails 2.3 nested attributes&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s suppose you have two related models that describe groups of people:&lt;/p&gt;
&lt;pre&gt;class Group &amp;lt; ActiveRecord::Base
  has_many :people
end
class Person &amp;lt; ActiveRecord::Base
  belongs_to :group
end&lt;/pre&gt;
&lt;p&gt;Again, writing model classes is really easy. With just a few lines of code I have told ActiveRecord to manage two separate tables and their relationship.&lt;/p&gt;
&lt;p&gt;Now you can use ViewMapper to create a complex form for creating and editing groups and people at the same time like this:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate nested_attributes_view_for group containing:people
       error  Model &amp;#x27;Group&amp;#x27; does not accept nested attributes
              for child models &amp;#x27;people&amp;#x27;&lt;/pre&gt;
&lt;p&gt;This error indicates that my Group model is missing the &amp;ldquo;accepts_nested_attributes_for&amp;rdquo; directive. Since the generator creates view code that relies on the nested attributes feature, it won&amp;rsquo;t let you create the view for a model that is missing this line. This sort of helpful error message is possible since ViewMapper is inspecting an existing model class, and not just creating new scaffold code.&lt;/p&gt;
&lt;p&gt;Now if we add the missing line (suddenly my model is less concise... nested attributes aren't that easy to use yet!):&lt;/p&gt;
&lt;pre&gt;class Group &amp;lt; ActiveRecord::Base
  has_many :people
  &lt;b&gt;accepts_nested_attributes_for :people,
    :allow_destroy =&amp;gt; true,
    :reject_if =&amp;gt; proc { |attrs| attrs[&amp;#x27;name&amp;#x27;].blank? &amp;amp;&amp;amp; attrs[&amp;#x27;age&amp;#x27;].blank? }&lt;/b&gt;
end&lt;/pre&gt;
&lt;p&gt;&amp;hellip;we can re-run the generator:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate nested_attributes_view_for group containing:people
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/groups
      exists  app/views/layouts/
      exists  test/functional/
      create  test/unit/helpers/
      exists  public/stylesheets/
      create  app/views/groups/index.html.erb
      create  app/views/groups/show.html.erb
      create  app/views/groups/new.html.erb
      create  app/views/groups/edit.html.erb
      create  app/views/layouts/groups.html.erb
      create  public/stylesheets/scaffold.css
      create  app/controllers/groups_controller.rb
      create  test/functional/groups_controller_test.rb
      create  app/helpers/groups_helper.rb
      create  test/unit/helpers/groups_helper_test.rb
       route  map.resources :groups&lt;/pre&gt;
&lt;p&gt;And now if we run our app, we get view scaffolding illustrating how to create and edit people and groups all at the same time:&lt;/p&gt;
&lt;img src="http://patshaughnessy.net/assets/2009/7/24/group_new.png"&gt;
&lt;p&gt;If I save the group&amp;hellip;&lt;/p&gt;
&lt;img src="http://patshaughnessy.net/assets/2009/7/24/group_show.png"&gt;
&lt;p&gt;And re-editing the same group:&lt;/p&gt;
&lt;img src="http://patshaughnessy.net/assets/2009/7/24/group_edit.png"&gt;
&lt;p&gt;More to come&amp;hellip; as I said this is work-in-progress. As a next step I&amp;rsquo;m planning to improve the scaffolding code for nested attributes by adding javascript to dynamically add/delete the child objects. But after that I'm thinking about:
  &lt;ul&gt;
    &lt;li&gt;Adding a &amp;ldquo;paperclip_view_for&amp;rdquo; generator that creates a file upload form for a model that contains a &amp;ldquo;has_attached_file&amp;rdquo; directive.&lt;/li&gt;
    &lt;li&gt;Adding a &amp;ldquo;auto_complete_view_for&amp;rdquo; generator that adds &amp;ldquo;auto_complete_for&amp;rdquo; to the controller and uses &amp;ldquo;text_field_for_auto_complete&amp;rdquo; in the form.&lt;/li&gt;
    &lt;li&gt;Adding the ability for you to extend this with your own scaffolding code.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-06-25:379</id>
    <published>2009-06-25T20:56:00Z</published>
    <updated>2009-06-25T20:57:16Z</updated>
    <category term="Rails" />
    <category term="java" />
    <category term="jruby" />
    <category term="rails" />
    <link href="http://patshaughnessy.net/2009/6/25/taming-the-beast-using-jruby-and-rspec-to-test-a-j2ee-application" rel="alternate" type="text/html" />
    <title>Taming the beast: Using JRuby and RSpec to test a J2EE application</title>
<content type="html">
            &lt;p&gt;Working with J2EE applications is something like wandering in a jungle: you never quite know what wild animal you&amp;rsquo;ll find around the next corner&amp;hellip; it might be an ORM tool like Hibernate; it could be an application framework like Spring or Struts with lots of confusing XML files, or it might just be a long list of obscure JAR files that you need to find and download&amp;hellip; whatever it is, you&amp;rsquo;re guaranteed to spend countless hours wasting time learning things you really didn&amp;rsquo;t want to know. This article will show how you can get your J2EE application under control by using JRuby and RSpec&amp;hellip; but first, let&amp;rsquo;s take a quick look at what RSpec is and how it&amp;rsquo;s normally used with Ruby.&lt;/p&gt;
&lt;p /&gt;
&lt;p&gt;&lt;b&gt;Using RSpec with Ruby&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;If you are a Ruby developer, you would probably write code similar to this to add up an array of numbers:&lt;/p&gt;
&lt;pre&gt;class Calculator
  def self.sum numbers
    numbers.inject do |sum, x|
      sum+x
    end
  end
end&lt;/pre&gt;
&lt;p&gt;This is simple enough to run:&lt;/p&gt;
&lt;pre&gt;$ irb
irb(main):001:0&amp;gt; require &amp;#x27;calculator.rb&amp;#x27;
=&amp;gt; true
irb(main):002:0&amp;gt; Calculator.sum [2, 3]
=&amp;gt; 5&lt;/pre&gt;
&lt;p&gt;One of the best things about Ruby are all of the different testing tools available to you &amp;ndash; for example, you could write a test for this method using RSpec like this:&lt;/p&gt;
&lt;pre&gt;require &amp;#x27;calculator.rb&amp;#x27;
describe &amp;quot;Calculator&amp;quot; do
  it &amp;quot;should add numbers correctly&amp;quot; do
    Calculator.sum([1, 2]).should == 3
    Calculator.sum([2, 2]).should == 4
    Calculator.sum([2, 3, 4]).should == 9
  end
end&lt;/pre&gt;
&lt;p&gt;And then run the spec as follows:&lt;/p&gt;
&lt;pre&gt;$ spec calculator_spec.rb 
.
Finished in 0.001703 seconds
1 example, 0 failures&lt;/pre&gt;
&lt;p&gt;RSpec allows you to write test code that is readable, and also behavior-oriented; that is, the tests reflect the way an end user might actually behave. In fact, RSpec is really just the first step towards behavior-driven-development. The Ruby community also benefits from other tools such as WebRat, Cucumber, etc., that can make testing very easy and effective.&lt;/p&gt;
&lt;p /&gt;
&lt;p&gt;&lt;b&gt;A J2EE sample app&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s rewrite the &amp;ldquo;sum&amp;rdquo; Ruby method above using Java. To make this feel more like an actual J2EE application, we&amp;rsquo;ll use a service class that will perform the actual sum operation for us, and set it up with the Spring framework. We can start by writing an XML file called &amp;ldquo;ApplicationContext.xml&amp;rdquo; for Spring to use, and declare a bean called &amp;ldquo;calculatorService:&amp;rdquo;&lt;/pre&gt;
&lt;pre&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;!DOCTYPE beans PUBLIC &amp;quot;-//SPRING//DTD BEAN//EN&amp;quot;
  &amp;quot;http://www.springframework.org/dtd/spring-beans.dtd&amp;quot;&amp;gt;
&amp;lt;beans&amp;gt;
  &amp;lt;bean id=&amp;quot;calculatorService&amp;quot;
    class=&amp;quot;calculator.CalculatorServiceImpl&amp;quot;&amp;gt;
  &amp;lt;/bean&amp;gt;
&amp;lt;/beans&amp;gt;&lt;/pre&gt;
&lt;p&gt;In a real J2EE app, we would probably have an interface called &amp;ldquo;CalculatorService&amp;rdquo; like this:&lt;/p&gt;
&lt;pre&gt;package calculator;
public interface CalculatorService {
  public int sum(int[] array);
}&lt;/pre&gt;
&lt;p&gt;And then we&amp;rsquo;d implement it using a concrete class, like this:&lt;/p&gt;
&lt;pre&gt;package calculator;
public class CalculatorServiceImpl implements CalculatorService {
  public int sum(int[] array)
  {
    int sum = 0;
    for (int number: array)
    {
      sum += number;
    }
    return sum;
  }
}&lt;/pre&gt;
&lt;p&gt;And finally, let&amp;rsquo;s write a simple Java command line client for this so we can test running it from the command line:&lt;/p&gt;
&lt;pre&gt;package calculator;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CalculatorApp {
  public static void main(String[] args) throws Exception {
    int[] array = { 2, 3 };
    ClassPathXmlApplicationContext application_context =
      new ClassPathXmlApplicationContext(&amp;quot;ApplicationContext.xml&amp;quot;);
    CalculatorService calculator =
      (CalculatorService)application_context.getBean(&amp;quot;calculatorService&amp;quot;);
    System.out.println(&amp;quot;2 + 3 is: &amp;quot; + Integer.toString(calculator.sum(array)));
  }
}&lt;/pre&gt;
&lt;p&gt;This will also help us figure out how to write the ruby spec later. If you run this from Eclipse or your favorite Java IDE, you&amp;rsquo;ll get:&lt;/p&gt;
&lt;pre&gt;Jun 25, 2009 12:21:58 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3479e304: display name [org.springframework.context.support.ClassPathXmlApplicationContext@3479e304]; startup date [Thu Jun 25 12:21:58 EDT 2009]; root of context hierarchy
Jun 25, 2009 12:21:58 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [ApplicationContext.xml]
Jun 25, 2009 12:21:58 PM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@3479e304]: org.springframework.beans.factory.support.DefaultListableBeanFactory@604788d5
Jun 25, 2009 12:21:58 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@604788d5: defining beans [calculatorService]; root of factory hierarchy
2 + 3 is: 5&lt;/pre&gt;
&lt;p&gt;This is starting to feel like an actual &amp;ldquo;Enterprise&amp;rdquo; J2EE application now that we have an XML config file and lots of confusing information being logged!&lt;/p&gt;
&lt;p /&gt;
&lt;p&gt;&lt;b&gt;Running RSpec with JRuby&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Now that we have a J2EE application to test, let&amp;rsquo;s get started with JRuby. First, you will need to &lt;a href="http://jruby.codehaus.org/Getting+Started"&gt;download and install JRuby&lt;/a&gt;. This is really just a matter of downloading the TAR file and then placing the JRuby bin folder on your path. Test that you have it setup properly by running this command:&lt;/p&gt;
&lt;pre&gt;$ jruby --version
jruby 1.1.5 (ruby 1.8.6 patchlevel 114) (2008-11-03 rev 7996) [x86_64-java]&lt;/pre&gt;
&lt;p&gt;Now let&amp;rsquo;s update our Ruby spec from above and get it to work with Java. Here&amp;rsquo;s what we had for Ruby:&lt;/p&gt;
&lt;pre&gt;require &amp;#x27;calculator.rb&amp;#x27;
describe &amp;quot;Calculator&amp;quot; do
  it &amp;quot;should add numbers correctly&amp;quot; do
    Calculator.add([1, 2]).should == 3
    Calculator.add([2, 2]).should == 4
    Calculator.add([2, 3, 4]).should == 9
  end
end&lt;/pre&gt;
&lt;p&gt;The key to using JRuby to test Java is to add this line at the top of the spec:&lt;/p&gt;
&lt;pre&gt;require 'java'&lt;/pre&gt;
&lt;p&gt;This tells JRuby that we want to allow the Ruby code to call Java directly. But what code should we try to call? The nice thing about the Spring framework is that is makes a series of &amp;ldquo;beans,&amp;rdquo; i.e. Java objects, available to us. The reason I went to the trouble of adding the Spring framework to this sample app is that for a real J2EE application using Spring to create and load a Java object will be the simplest path towards testing your target application. What I did while testing a real J2EE application was to:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Identify what business logic I wanted to test&lt;/li&gt;
  &lt;li&gt;Look for the Java object that was the top-level, simplest interface to that business logic under the user interface layer&lt;/li&gt;
  &lt;li&gt;Find a bean in the ApplicationContext.xml file that corresponded to that Java object. In my case, there actually was no such bean, and I had to slightly modify the application I was testing by adding a new &amp;lt;bean&amp;gt; tag to one of the Spring XML files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If your application is not using Spring, you might simply be able to create a Java object directly from your Ruby code, or in the worst case scenario you might have to make Java code changes to the target J2EE app to break dependencies that the object you&amp;rsquo;d like to test has on other objects, interfaces, services, etc., allowing you to create it in isolation. Michael Feathers has written an entire &lt;a href="http://amzn.com/0131177052"&gt;book on dependency breaking techniques&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Back to this sample app: here in our Ruby spec we can follow the same pattern that I used above in the command line Java client: calling &amp;ldquo;ClassPathXmlApplicationContext&amp;rdquo; to get the application context, and then creating a bean with getBean. The other thing we need to add are &amp;ldquo;include_class&amp;rdquo; directives that indicate to JRuby which Java classes should be loaded from the classpath and made available to the Ruby script. Here&amp;rsquo;s the spec code with the new JRuby code changes in bold:&lt;/p&gt;
&lt;pre&gt;&lt;b&gt;require &amp;#x27;java&amp;#x27;
include_class &amp;#x27;org.springframework.context.ApplicationContext&amp;#x27;
include_class
  &amp;#x27;org.springframework.context.support.ClassPathXmlApplicationContext&amp;#x27;&lt;/b&gt;
describe &amp;quot;Calculator&amp;quot; do
  it &amp;quot;should add numbers correctly&amp;quot; do
    &lt;b&gt;application_context =
      ClassPathXmlApplicationContext.new &amp;quot;ApplicationContext.xml&amp;quot;
    calculator =  application_context.getBean &amp;quot;calculatorService&amp;quot;&lt;/b&gt;
    calculator.sum([1, 2]).should == 3
    calculator.sum([2, 2]).should == 4
    calculator.sum([2, 3, 4]).should == 9
  end
end&lt;/pre&gt;
&lt;p&gt;Now let&amp;rsquo;s try to run it using JRuby. Another trick with JRuby is knowing how to use the &amp;ldquo;-S&amp;rdquo; option &amp;ndash; this allows you to run a Ruby command like &amp;ldquo;gem&amp;rdquo; or &amp;ldquo;spec,&amp;rdquo; but inside a JRuby session. So here&amp;rsquo;s how to run our new spec using JRuby:&lt;/p&gt;
&lt;pre&gt;$ jruby -S spec calculator_spec.rb 
(eval):1:in `include_class&amp;#x27;: cannot load Java class
  org.springframework.context.ApplicationContext (NameError)
  from /Users/pat/src/jruby-1.1.5/lib/ruby/site_ruby/1.8/builtin/javasupport/core_ext/object.rb:38:in `eval&amp;#x27;
  from /Users/pat/src/jruby-1.1.5/lib/ruby/site_ruby/1.8/builtin/javasupport/core_ext/object.rb:67:in `include_class&amp;#x27;
  from /Users/pat/src/jruby-1.1.5/lib/ruby/site_ruby/1.8/builtin/javasupport/core_ext/object.rb:38:in `each&amp;#x27;
  from /Users/pat/src/jruby-1.1.5/lib/ruby/site_ruby/1.8/builtin/javasupport/core_ext/object.rb:38:in `include_class&amp;#x27;
  from calculator_spec.rb:2&lt;/pre&gt;
&lt;p&gt;So what is the error message all about? This just means that JRuby wasn&amp;rsquo;t able to find the ApplicationContext class from Spring on the classpath. But what is the classpath anyway? It would be nice to be able to simply specify the classpath using a command line option, the way you do with a java command line using &amp;ldquo;-cp&amp;rdquo; for example. But for JRuby you need to specify the classpath as an environment setting. To make this easier, I wrote a simple shell script for running a JRuby spec:&lt;/p&gt;
&lt;pre&gt;BASE=`pwd`
CLASSPATH=$BASE/lib/spring-2.5.1.jar
export CLASSPATH
jruby -S spec $1&lt;/pre&gt;
&lt;p&gt;This just gets the current working directory and constructs the classpath setting, indicating where to find the Spring JAR file. Finally we export the classpath value and call JRuby. This will work on the Mac and Linux; for Windows you would need something slightly different. Anyway, now I can run my specs like this:&lt;/p&gt;
&lt;pre&gt;$ ./jruby-spec.sh calculator_spec.rb 
F
1)
NativeException in &amp;#x27;Calculator should add numbers correctly&amp;#x27;
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
org/springframework/util/ClassUtils.java:73:in `&amp;lt;clinit&amp;gt;&amp;#x27;
org/springframework/core/io/DefaultResourceLoader.java:52:in `&amp;lt;init&amp;gt;&amp;#x27;
org/springframework/context/support/AbstractApplicationContext.java:198:in `&amp;lt;init&amp;gt;&amp;#x27;
org/springframework/context/support/AbstractRefreshableApplicationContext.java:80:in `&amp;lt;init&amp;gt;&amp;#x27;
org/springframework/context/support/AbstractXmlApplicationContext.java:58:in `&amp;lt;init&amp;gt;&amp;#x27;
org/springframework/context/support/ClassPathXmlApplicationContext.java:119:in `&amp;lt;init&amp;gt;&amp;#x27;
org/springframework/context/support/ClassPathXmlApplicationContext.java:66:in `&amp;lt;init&amp;gt;&amp;#x27;
sun/reflect/NativeConstructorAccessorImpl.java:-2:in `newInstance0&amp;#x27;
sun/reflect/NativeConstructorAccessorImpl.java:39:in `newInstance&amp;#x27;
sun/reflect/DelegatingConstructorAccessorImpl.java:27:in `newInstance&amp;#x27;
java/lang/reflect/Constructor.java:513:in `newInstance&amp;#x27;
org/jruby/javasupport/JavaConstructor.java:226:in `new_instance&amp;#x27;
org/jruby/java/invokers/ConstructorInvoker.java:100:in `call&amp;#x27;
org/jruby/java/invokers/ConstructorInvoker.java:180:in `call&amp;#x27;
etc...&lt;/pre&gt;
&lt;p&gt;Oops &amp;ndash; it turns out that Spring actually requires the Apache Commons logging JAR file to be on the classpath also. This sample app is definitely reminding me of a complex J2EE app running on WebSphere or WebLogic! Let&amp;rsquo;s add commons-logging-1.0.4.jar to the classpath in my shell script and try again:&lt;/p&gt;
&lt;pre&gt;$ ./jruby-spec.sh calculator_spec.rb 
Jun 25, 2009 1:58:15 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4c6c3e: display name [org.springframework.context.support.ClassPathXmlApplicationContext@4c6c3e]; startup date [Thu Jun 25 13:58:15 EDT 2009]; root of context hierarchy
Jun 25, 2009 1:58:15 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [ApplicationContext.xml]
F
1)
NativeException in &amp;#x27;Calculator should add numbers correctly&amp;#x27;
org.springframework.beans.factory.BeanDefinitionStoreException:
  IOException parsing XML document from class path resource
  [ApplicationContext.xml]; nested exception is java.io.FileNotFoundException:
  class path resource [ApplicationContext.xml] cannot be opened because
  it does not exist
org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java:334:in `loadBeanDefinitions&amp;#x27;
org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java:295:in `loadBeanDefinitions&amp;#x27;&lt;/pre&gt;
&lt;p&gt;Once again, I&amp;rsquo;ve forgotten something in my class path: this time it&amp;rsquo;s the ApplicationContext.xml file which I passed into ClassPathXmlApplicationContext in the spec. As the name implies, I need to put the XML file on the classpath in order for Spring to be able to find it. Let&amp;rsquo;s cut to the chase and put everything I need onto the classpath&amp;hellip; here&amp;rsquo;s the final version of jruby-spec.sh (the classpath line split into two for readability):&lt;/p&gt;
&lt;pre&gt;BASE=`pwd`
CLASSPATH=$BASE/bin:$BASE/resources:$BASE/lib/spring-2.5.1.jar:
  $BASE/lib/commons-logging-1.0.4.jar
export CLASSPATH
jruby -S spec $1&lt;/pre&gt;
&lt;p&gt;Now JRuby will be able to find everything that it needs: Spring, Apache Common Logging, the ApplicationContext.xml file, and also the application&amp;rsquo;s class files saved under &amp;ldquo;bin&amp;rdquo; by Eclipse. Now if I run the spec once more it should all work:&lt;/p&gt;
&lt;pre&gt;$ ./jruby-spec.sh calculator_spec.rb 
Jun 25, 2009 2:02:22 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1717d968: display name [org.springframework.context.support.ClassPathXmlApplicationContext@1717d968]; startup date [Thu Jun 25 14:02:22 EDT 2009]; root of context hierarchy
Jun 25, 2009 2:02:22 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [ApplicationContext.xml]
Jun 25, 2009 2:02:22 PM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@1717d968]: org.springframework.beans.factory.support.DefaultListableBeanFactory@5a21fdc8
Jun 25, 2009 2:02:22 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5a21fdc8: defining beans [calculatorService]; root of factory hierarchy
F
1)
TypeError in &amp;#x27;Calculator should add numbers correctly&amp;#x27;
for method sum expected [[I]; got: [org.jruby.RubyArray];
  error: argument type mismatch calculator_spec.rb:8:
Finished in 0.70559 seconds
1 example, 1 failure&lt;/pre&gt;
&lt;p&gt;What&amp;rsquo;s this error all about? I do have the correct classpath now, but what does &amp;ldquo;RubyArray&amp;rdquo; mean? I thought I passed an array of integers into the calculator service:&lt;/p&gt;
&lt;pre&gt;calculator.sum([1, 2]).should == 3&lt;/pre&gt;
&lt;p&gt;Well it turns out that Ruby and JRuby aren&amp;rsquo;t quite the same thing. Since JRuby is actually a Java application itself, it implements each Ruby class with a corresponding Java class. For the Ruby Array class, JRuby has created a class called &amp;ldquo;org.jruby.RubyArray.&amp;rdquo; When you call Java code and pass in Ruby objects, JRuby actually provides the Java equivalent of these Ruby objects to the Java code. That&amp;rsquo;s why we get an error here; our calculator service doesn&amp;rsquo;t expect a RubyArray &amp;ndash; it expects int[] instead.&lt;/p&gt;
&lt;p&gt;To avoid this error, we need to convert the RubyArray into a normal Java array, using a JRuby method called &amp;ldquo;to_java()&amp;rdquo;, like this:&lt;/p&gt;
&lt;pre&gt;calculator.sum([1, 2].to_java(:int)).should == 3&lt;/pre&gt;
&lt;p&gt;To_java takes a symbol as a parameter, which indicates what type each element of the Ruby array should be converted into. Now our spec will pass!&lt;/p&gt;
&lt;pre&gt;$ ./jruby-spec.sh calculator_spec.rb 
Jun 25, 2009 2:15:37 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1717d968: display name [org.springframework.context.support.ClassPathXmlApplicationContext@1717d968]; startup date [Thu Jun 25 14:15:37 EDT 2009]; root of context hierarchy
Jun 25, 2009 2:15:37 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [ApplicationContext.xml]
Jun 25, 2009 2:15:37 PM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@1717d968]: org.springframework.beans.factory.support.DefaultListableBeanFactory@5a21fdc8
Jun 25, 2009 2:15:37 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5a21fdc8: defining beans [calculatorService]; root of factory hierarchy
.
Finished in 0.28237 seconds
1 example, 0 failures&lt;/pre&gt;
&lt;p&gt;Taking a step back, I think what we&amp;rsquo;ve done is quite interesting; we have:
  &lt;ul&gt;
    &lt;li&gt;Pulled a J2EE application out of Eclipse, IntelliJ or whatever IDE you project uses, and started to run it from the command line instead. For me, avoiding a confusing and complex IDE makes the application easier to work with&amp;hellip; more like a Rails app.&lt;/li&gt;
    &lt;li&gt;Documented what the classpath needs to be and what JAR files the application requires in an understandable text file format, rather than having it hidden away in a confusing Eclipse dialog box.&lt;/li&gt;
    &lt;li&gt;Exposed the J2EE application&amp;rsquo;s business logic to testing below the user interface layer &amp;ndash; nothing here involves a web browser or user interface testing tool like Selenium.&lt;/li&gt;
    &lt;li&gt;Started to apply behavior driven development to a J2EE application, using the best tools available, which happen to be written in Ruby.&lt;/li&gt;
  &lt;/ul&gt;
  In a future post, I&amp;rsquo;ll try to take the next step of using Cucumber features to test this same J2EE sample app. It will be interesting to find out if Cucumber works will with JRuby.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-06-15:331</id>
    <published>2009-06-15T03:13:00Z</published>
    <updated>2009-06-15T03:37:50Z</updated>
    <category term="auto_complete" />
    <category term="Rails" />
    <link href="http://patshaughnessy.net/2009/6/15/auto-complete-for-complex-forms-using-nested-attributes-in-rails-2-3" rel="alternate" type="text/html" />
    <title>Auto complete for complex forms using nested attributes in Rails 2.3</title>
<content type="html">
            &lt;p&gt;I just updated &lt;a href="http://github.com/patshaughnessy/auto_complete"&gt;my fork of the auto_complete plugin&lt;/a&gt; to support Rails 2.3 nested attributes. Thanks to Anthony Frustagli for the code and ideas that I used as the basis for this fix.&lt;/p&gt;
&lt;p&gt;&amp;lt;u&gt;Basic usage:&amp;lt;/u&gt;&lt;/p&gt;
&lt;p&gt;To use auto_complete on a complex form with nested attributes, just call &amp;ldquo;text_field_for_auto_complete&amp;rdquo; right on the form builder object yielded by form_for or fields_for, like in this example:&lt;/p&gt;
&lt;pre&gt;&amp;lt;% parent_form.fields_for :children do |child_form| %&amp;gt;
  &amp;lt;%= child_form.text_field_with_auto_complete :name, {},
        { :method =&amp;gt; :get, :skip_style =&amp;gt; true } %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/pre&gt;
&lt;p&gt;If you have Rails 2.3, this code will iterate over each child object and display a text field with auto complete support. My plugin will generate HTML and Javascript that works even when repeated in a loop like this. Also note that I&amp;rsquo;ve left off the object name parameter from text_field_with_auto_complete. It&amp;rsquo;s not needed now, since the object is indicated by the surrounding call to fields_for. The other parameters are optional and are taken unchanged from the original auto_complete plugin:
  &lt;ul&gt;
    &lt;li&gt;&amp;ldquo;:method =&amp;gt; :get&amp;rdquo; indicates GET requests should be used by the AJAX calls to load the pick list values, avoiding problems with CSRF protection.&lt;/li&gt;
    &lt;li&gt;And &amp;ldquo;:skip =&amp;gt; :true&amp;rdquo; indicates that the inline CSS stylesheet used by the auto complete drop down Prototype code should be skipped. Since we&amp;rsquo;re iterating over child objects we don&amp;rsquo;t want the same CSS code repeated once for each; instead include it once in a parent object&amp;rsquo;s call to text_field_for_auto_complete or else just include it manually somewhere.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it &amp;ndash; it should just work. If you&amp;rsquo;re interested in learning more about how to use nested attributes and what my plugin is actually doing, read on&amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;lt;u&gt;Details:&amp;lt;/u&gt;&lt;/p&gt;
&lt;p&gt;To learn more, let&amp;rsquo;s take a look at a simple nested attribute example, using the Projects/Tasks models from &lt;a href="http://railscasts.com/episodes/73-complex-forms-part-1"&gt;Ryan Bates' complex forms screen cast&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;class Project &amp;lt; ActiveRecord::Base
  has_many :tasks
  accepts_nested_attributes_for :tasks, :allow_destroy =&amp;gt; true
end
class Task &amp;lt; ActiveRecord::Base
  belongs_to :project
end&lt;/pre&gt;
&lt;p&gt;A project has many tasks, and each task belongs to a project. Here I&amp;rsquo;ve also declared that each project &amp;ldquo;accepts nested attributes for&amp;rdquo; tasks. This is a new method added to ActiveRecord in Rails 2.3&amp;hellip; for lots of examples and explanation just take a look directly at the &lt;a href="http://github.com/rails/rails/blob/d32965399ccfa2052a4d52b70db1bae0ca16830b/activerecord/lib/active_record/nested_attributes.rb"&gt;new nested_attributes.rb code file in Rails 2.3&lt;/a&gt;. In a nutshell, &amp;ldquo;accepts_nested_attributes_for&amp;rdquo; tells ActiveRecord that the project model should be able to save the attributes of the associated task model objects when a project is saved. This means that when I submit my project form, it can also contain a series of task fields as well. For example, my view code might look something like this:&lt;/p&gt;
&lt;pre&gt;&amp;lt;% form_for @project do |project_form| %&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= project_form.label :name, &amp;quot;Project:&amp;quot; %&amp;gt;
    &amp;lt;%= project_form.text_field :name %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;% project_form.fields_for :tasks do |task_form| %&amp;gt;
    &amp;lt;%= task_form.label :name, &amp;quot;Task:&amp;quot; %&amp;gt;
    &amp;lt;%= task_form.text_field :name %&amp;gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/pre&gt;
&lt;p&gt;This displays a name text field for the project, and then calls &amp;ldquo;fields_for&amp;rdquo; again right on the form builder yielded by form_for. This is new for Rails 2.3. In earlier versions of Rails you had to explicitly iterate over the child objects and call fields_for for each one. Now in Rails 2.3, you can call fields_for as a method of the parent form and it will automatically iterate over all of the child objects and call fields_for. If we take a look at the HTML generated by this example form, we&amp;rsquo;ll find something like:&lt;/p&gt;
&lt;pre&gt;&amp;lt;input id=&amp;quot;project_name&amp;quot; name=&amp;quot;project[name]&amp;quot;
  size=&amp;quot;30&amp;quot; type=&amp;quot;text&amp;quot; value=&amp;quot;Some project&amp;quot; /&amp;gt;
&amp;lt;input id=&amp;quot;project_tasks_attributes_0_id&amp;quot;
  name=&amp;quot;project[tasks_attributes][0][id]&amp;quot; type=&amp;quot;hidden&amp;quot; value=&amp;quot;1&amp;quot; /&amp;gt;
&amp;lt;input id=&amp;quot;project_tasks_attributes_0_name&amp;quot;
  name=&amp;quot;project[tasks_attributes][0][name]&amp;quot; type=&amp;quot;text&amp;quot; value=&amp;quot;Task one&amp;quot; /&amp;gt;
&amp;lt;input id=&amp;quot;project_tasks_attributes_1_id&amp;quot;
  name=&amp;quot;project[tasks_attributes][1][id]&amp;quot; type=&amp;quot;hidden&amp;quot; value=&amp;quot;2&amp;quot; /&amp;gt;
&amp;lt;input id=&amp;quot;project_tasks_attributes_1_name&amp;quot;
  name=&amp;quot;project[tasks_attributes][1][name]&amp;quot; type=&amp;quot;text&amp;quot; value=&amp;quot;Task two&amp;quot; /&amp;gt;&lt;/pre&gt;
&lt;p&gt;I&amp;rsquo;ve simplified this to make it more readable. You can see the iteration by project_form.fields_for :tasks, and that for each task there&amp;rsquo;s an &amp;lt;input&amp;gt; tag for the &amp;ldquo;name&amp;rdquo; field, along with another hidden &amp;lt;input&amp;gt; tag containing the task&amp;rsquo;s &amp;ldquo;id&amp;rdquo; attribute. The most important detail here is the name given to each of these tags: &amp;ldquo;project[tasks_attributes][0][name]&amp;rdquo; for example. Since the tasks are nested attributes of the project, they are displayed using the PARENT_OBJECT[CHILD_OBJECTS_attributes][INDEX][FIELD] pattern, while for the project we get the simple OBJECT[FIELD] pattern. This is the key to making nested attributes work. In our project model, when we called &amp;ldquo;has_many :tasks&amp;rdquo;, Rails defined some new methods for us on the Project class to handle tasks: tasks, tasks=, task_ids, task_ids= and a couple of others as well. Now with Rails 2.3, when we call &amp;ldquo;accepts_nested_attributes_for :tasks&amp;rdquo; Rails defines another new method for Project called tasks_attributes= in order to process all of the new nested parameters for tasks when the complex project form is submitted. This is the reason for the &amp;ldquo;_attributes&amp;rdquo; in the naming pattern used in the form.&lt;/p&gt;
&lt;p&gt;Now&amp;hellip; how do we get auto complete to work for this form? The problem with auto complete on a complex form has always been that the Javascript and HMTL used by the Prototype library assumes that the &amp;lt;input&amp;gt; tag, &amp;lt;div&amp;gt; tag and related Javascript code would be unique on the HTML page. If you just call the text_field_with_auto_complete macro from the standard auto_complete plugin like this&amp;hellip;&lt;/p&gt;
&lt;pre&gt;&amp;lt;% project_form.fields_for :tasks do |task_form| %&amp;gt;
  &amp;lt;%= text_field_with_auto_complete :task, :name, {},
        { :method =&amp;gt; :get, :skip_style =&amp;gt; true } %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;hellip; it will not work. The first problem is that text_field_with_auto_complete does not know that fields_for is iterating over the child tasks, or which task is currently being processed in the iteration. But even if you were able to identify the current task object somehow, you would still get HTML like this:&lt;/p&gt;
&lt;pre&gt;&amp;lt;input id=&amp;quot;task_name&amp;quot; name=&amp;quot;task[name]&amp;quot; size=&amp;quot;30&amp;quot; type=&amp;quot;text&amp;quot; /&amp;gt;
&amp;lt;div class=&amp;quot;auto_complete&amp;quot; id=&amp;quot;task_name_auto_complete&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
//&amp;lt;![CDATA[
var task_name_auto_completer = new Ajax.Autocompleter(&amp;#x27;task_name&amp;#x27;,
  &amp;#x27;task_name_auto_complete&amp;#x27;, &amp;#x27;/projects/auto_complete_for_task_name&amp;#x27;,
  {method:&amp;#x27;get&amp;#x27;})
//]]&amp;gt;
&amp;lt;/script&amp;gt;

&amp;hellip;

&amp;lt;input id=&amp;quot;task_name&amp;quot; name=&amp;quot;task[name]&amp;quot; size=&amp;quot;30&amp;quot; type=&amp;quot;text&amp;quot; /&amp;gt;
&amp;lt;div class=&amp;quot;auto_complete&amp;quot; id=&amp;quot;task_name_auto_complete&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
//&amp;lt;![CDATA[
var task_name_auto_completer = new Ajax.Autocompleter(&amp;#x27;task_name&amp;#x27;,
  &amp;#x27;task_name_auto_complete&amp;#x27;, &amp;#x27;/projects/auto_complete_for_task_name&amp;#x27;,
  {method:&amp;#x27;get&amp;#x27;})
//]]&amp;gt;
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;Now the &amp;lt;input id=&amp;ldquo;task_name&amp;rdquo;&amp;gt; tag is repeated on the same page, and the Javascript call to Ajax.Autocompleter(&amp;#x27;task_name&amp;#x27;, &amp;hellip; ) will not work since the browser will not be able to identify which &amp;lt;input&amp;gt; tag to use.&lt;/p&gt;
&lt;p&gt;If you use my plugin instead of the original auto_complete plugin&amp;hellip;&lt;/p&gt;
&lt;pre&gt;$ rm -rf vendor/plugins/auto_complete
$ ./script/plugin install git://github.com/patshaughnessy/auto_complete.git
Initialized empty Git repository in /Users/pat/rails-app/vendor/plugins/auto_complete/.git/
remote: Counting objects: 20, done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 20 (delta 5), reused 0 (delta 0)
Unpacking objects: 100% (20/20), done.
From git://github.com/patshaughnessy/auto_complete
 * branch            HEAD       -&amp;gt; FETCH_HEAD
&lt;/pre&gt;
&lt;p&gt;&amp;hellip; and restart your Rails app, then you can change your view to call text_field_with_auto_complete as a method of the form builder, like this:&lt;/p&gt;
&lt;pre&gt;&amp;lt;% project_form.fields_for :tasks do |task_form| %&amp;gt;
  &amp;lt;%= &lt;b&gt;task_form.&lt;/b&gt;text_field_with_auto_complete :name, {},
  { :method =&amp;gt; :get, :skip_style =&amp;gt; true } %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/pre&gt;
&lt;p&gt;Note that I&amp;rsquo;ve also dropped :task as a parameter since that&amp;rsquo;s implicit in the call to fields_for. In fact, since text_field_with_auto_complete is now a method of the FormBuilder object (&amp;ldquo;task_form&amp;rdquo;), it has access to the task object currently being processed in the iteration. Now if you refresh the same form you&amp;rsquo;ll instead get this HTML instead:&lt;/p&gt;
&lt;pre&gt;&amp;lt;input id=&amp;quot;project_tasks_attributes_0_name&amp;quot;
  name=&amp;quot;project[tasks_attributes][0][name]&amp;quot;
  size=&amp;quot;30&amp;quot; type=&amp;quot;text&amp;quot; value=&amp;quot;Task one&amp;quot; /&amp;gt;
&amp;lt;div class=&amp;quot;auto_complete&amp;quot; id=&amp;quot;project_tasks_attributes_0_name_auto_complete&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
//&amp;lt;![CDATA[
var project_tasks_attributes_0_name_auto_completer =
  new Ajax.Autocompleter(&amp;#x27;project_tasks_attributes_0_name&amp;#x27;,
  &amp;#x27;project_tasks_attributes_0_name_auto_complete&amp;#x27;,
  &amp;#x27;/projects/auto_complete_for_task_name&amp;#x27;,
  {method:&amp;#x27;get&amp;#x27;, paramName:&amp;#x27;task[name]&amp;#x27;})
//]]&amp;gt;
&amp;lt;/script&amp;gt;

&amp;hellip;

&amp;lt;input id=&amp;quot;project_tasks_attributes_1_name&amp;quot;
  name=&amp;quot;project[tasks_attributes][1][name]&amp;quot;
  size=&amp;quot;30&amp;quot; type=&amp;quot;text&amp;quot; value=&amp;quot;Task two&amp;quot; /&amp;gt;
&amp;lt;div class=&amp;quot;auto_complete&amp;quot; id=&amp;quot;project_tasks_attributes_1_name_auto_complete&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
//&amp;lt;![CDATA[
var project_tasks_attributes_1_name_auto_completer =
  new Ajax.Autocompleter(&amp;#x27;project_tasks_attributes_1_name&amp;#x27;,
  &amp;#x27;project_tasks_attributes_1_name_auto_complete&amp;#x27;,
  &amp;#x27;/projects/auto_complete_for_task_name&amp;#x27;,
  {method:&amp;#x27;get&amp;#x27;, paramName:&amp;#x27;task[name]&amp;#x27;})
//]]&amp;gt;
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;This looks much better, and will actually work for the following reasons:
  &lt;ul&gt;
    &lt;li&gt;The &amp;lt;input&amp;gt; tags have the correct names, using the PARENT_OBJECT[CHILD_OBJECTS_attributes][INDEX][FIELD] pattern from fields_for. This means that the field values will be processed properly by ActiveRecord when the form is submitted.&lt;/li&gt;
    &lt;li&gt;My changes to the auto_complete plugin have picked up the child object index, 0 and 1 in this example, and included it in the &amp;lt;input&amp;gt; tag&amp;rsquo;s id, the &amp;lt;div&amp;gt; tag id and well as the associated Javascript code that calls Ajax.Autocompleter. Since all of the tag id&amp;rsquo;s are unique, the auto complete behavior works properly again for each text field.&lt;/li&gt;
    &lt;li&gt;The original &amp;ldquo;task&amp;rdquo; class name and &amp;ldquo;name&amp;rdquo; field name are passed unchanged into the Ajax calls to the server. This means that in your controller you can continue to use &amp;ldquo;auto_complete_for :task, :name&amp;rdquo; as usual, without worrying about the complex form and the fact that the task fields are repeated multiple times, etc.:
&lt;pre&gt;Ajax.Autocompleter(&amp;#x27;project_tasks_attributes_1_name&amp;#x27;,     
  &amp;#x27;project_tasks_attributes_1_name_auto_complete&amp;#x27;,
  &amp;#x27;/projects/auto_complete_for_task_name&amp;#x27;,
  {method:&amp;#x27;get&amp;#x27;, paramName:&amp;#x27;task[name]&amp;#x27;})&lt;/pre&gt;
  Here the third parameter to Ajax.Autocompleter, "/projects/auto_complete_for_task_name", is the AJAX URL which you need to account for in routes.rb, and paramName:'task[name]' tells the auto_complete_for handler in your controller to get the task names as usual, and protects the server side code from all of the complexity around the tag id, names, child object index, etc.
  &lt;/ul&gt;
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-06-15:330</id>
    <published>2009-06-15T03:11:00Z</published>
    <updated>2009-06-15T03:12:26Z</updated>
    <category term="auto_complete" />
    <category term="Rails" />
    <link href="http://patshaughnessy.net/2009/6/15/repeated-auto-complete-plugin-usage-change" rel="alternate" type="text/html" />
    <title>Repeated auto complete plugin usage change</title>
<content type="html">
            &lt;p&gt;I&amp;rsquo;ve forked the auto_complete plugin to support repeated text fields in a complex form; see &lt;a href="http://patshaughnessy.net/repeated_auto_complete"&gt;http://patshaughnessy.net/repeated_auto_complete&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;If you had downloaded my plugin in the past, I&amp;rsquo;ve just made a couple of changes that will require some simple code changes to your app:
  &lt;ul&gt;
    &lt;li&gt;You no longer need to or are able to use &amp;ldquo;auto_complete_form_for&amp;rdquo; or &amp;ldquo;auto_complete_fields_for.&amp;rdquo; I decided this was confusing and unnecessary. Now my plugin just mixes the text_field_with_auto_complete method right  into the standard FormBuilder class. Just use form_for or fields_for as usual.&lt;/li&gt;
    &lt;li&gt;I also dropped the object name parameter from text_field_with_auto_complete. Since text_field_with_auto_complete is a method of the form builder, the target object is indicated by the surrounding call to fields_for or form_for and so doesn&amp;rsquo;t need to be repeated. Now using form.text_field_with_auto_complete is very similar to using form.text_field or the other form builder methods: you just need to specify the column/field name.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;So if you are using my old plugin with a Rails 2.2 or earlier app like this:&lt;/p&gt;
&lt;pre&gt;&amp;lt;% for person in @group.people %&amp;gt;
  &amp;lt;% &lt;b&gt;auto_complete_&lt;/b&gt;fields_for &amp;quot;group[person_attributes][]&amp;quot;, person do |form| %&amp;gt;
    Person &amp;lt;%= person_form.label :name %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= form.text_field_with_auto_complete &lt;b&gt;:person,&lt;/b&gt; :name, {},
                                           {:method =&amp;gt; :get}  %&amp;gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;hellip; you should drop &amp;ldquo;auto_complete_&amp;rdquo; and &amp;ldquo;:person&amp;rdquo; and just use code like this instead:&lt;/p&gt;
&lt;pre&gt;&amp;lt;% for person in @group.people %&amp;gt;
  &amp;lt;% fields_for &amp;quot;group[person_attributes][]&amp;quot;, person do |form| %&amp;gt;
    Person &amp;lt;%= person_form.label :name %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= form.text_field_with_auto_complete :name, {},
                                           {:method =&amp;gt; :get}  %&amp;gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/pre&gt;
&lt;p&gt;And if you have Rails 2.3 or later and are using nested attributes, this would become:&lt;/p&gt;
&lt;pre&gt;&amp;lt;% form_for @group do |group_form| -%&amp;gt;
  &amp;lt;% group_form.fields_for :people do |person_form| %&amp;gt;
    Person &amp;lt;%= person_form.label :name %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= person_form.text_field_with_auto_complete :name, {},
          { :method =&gt; :get, :skip_style =&gt; true } %&gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/pre&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-05-29:299</id>
    <published>2009-05-29T22:51:00Z</published>
    <updated>2009-05-30T12:38:27Z</updated>
    <category term="paperclip" />
    <category term="Rails" />
    <category term="paperclip" />
    <category term="rails" />
    <link href="http://patshaughnessy.net/2009/5/29/paperclip-sample-app-part-3-saving-file-attachments-in-a-database-blob-column" rel="alternate" type="text/html" />
    <title>Paperclip sample app part 3: saving file attachments in a database BLOB column</title>
<content type="html">
            &lt;p&gt;&lt;a href="http://patshaughnessy.net/2009/4/30/paperclip-sample-app"&gt;In part 1 of this series&lt;/a&gt;, I showed how to create a simple Rails web site that uses the Paperclip plugin from Thoughtbot to upload and display image files. &lt;a href="http://patshaughnessy.net/2009/5/16/paperclip-sample-app-part-2-downloading-files-through-a-controller"&gt;Then in part 2&lt;/a&gt;, I went on to change the sample app to download the image files through a Rails controller and not just through a direct call to Apache. This would be useful if you wanted to implement security for file attachments or for a variety of other reasons.&lt;/p&gt;
&lt;p&gt;This time I&amp;rsquo;d like to show how to modify the same sample application to save the file attachments in a database BLOB column, instead of on your web server&amp;rsquo;s file system. To jump ahead and just get the working code, look at the &amp;ldquo;part3&amp;rdquo; folder in the github repo: &lt;a href="http://github.com/patshaughnessy/paperclip-sample-app"&gt;http://github.com/patshaughnessy/paperclip-sample-app&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But before we actually work on the sample app, a disclaimer: Don&amp;rsquo;t try this at home! Serving file content directly from the file system via Apache or some other web server will always be faster and simpler than loading the file attachments from a database table&amp;hellip; Apache and other web servers were designed to load and serve files quickly, and there&amp;rsquo;s normally no need to issue an expensive SQL query or to make another network connection to a database server just to send files to a web browser.&lt;/p&gt;
&lt;p&gt;So why in the world would you ever want to pay the extra performance penalty and move the files into a database table? Here are a couple of reasons:
  &lt;ol&gt;
    &lt;li&gt;Your client or employer wants you to. Some companies insist on using a commercial, &amp;ldquo;enterprise&amp;rdquo; RDMS system to save file contents for one reason or another. My employer, for example, has many years of experience using Oracle and is comfortable managing large numbers of files that are stored in an Oracle table, while the thought of managing, replicating, backing up, etc., files that are simply saved on a Linux file system seems much more complex and unfamiliar.&lt;/li&gt;
    &lt;li&gt;Security. If you need to encrypt the contents of super-secret file attachments, storing them in a database might be an easier solution if you&amp;rsquo;re willing to spend money on a database server like Oracle. And database encryption aside, generally information in a database server can be more easily protected and audited than files on your web server's file system can be.&lt;/li&gt;
  &lt;/ol&gt;
&lt;/p&gt;
&lt;p&gt;Anyway, let&amp;rsquo;s move on and actually change the sample app to save the files in a BLOB column. The first thing we will need to do is to use the version of Paperclip that I modified; the actual Paperclip plugin from Thoughtbot does not support storing files in a BLOB column. I added some code to Paperclip &amp;ndash; a new &amp;ldquo;storage module&amp;rdquo; &amp;ndash; to make this possible. See &lt;a href="http://github.com/patshaughnessy/paperclip/blob/9556fab3e1659a5c8690db82394cea55714b5da4/lib/paperclip/storage.rb#L236"&gt;my code changes&lt;/a&gt; to learn more.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s delete the original plugin and install my version:&lt;/p&gt;
&lt;pre&gt;$ cd /path/to/paperclip-sample-app
$ rm -rf vendor/plugins/paperclip
$ ./script/plugin install git://github.com/patshaughnessy/paperclip.git&lt;/pre&gt;
&lt;p&gt;Now that we have the modified plugin installed, let&amp;rsquo;s go ahead and create the BLOB columns that we will use to save the files. I tried to design the database storage module to be easy to use; one of the decisions I made was around what these BLOB columns should be called. I decided by default to use &amp;ldquo;[attachment]_file&amp;rdquo; as the name for the primary file attachment, and &amp;ldquo;[attachment]_[style]_file&amp;rdquo; for the other styles. If you want to use other column names, you just need to specify the names in the call to &amp;ldquo;has_attached_file&amp;rdquo; in the model. See &lt;a href="http://patshaughnessy.net/2009/4/14/database-storage-for-paperclip-rewritten-to-use-a-single-table"&gt;my usage post&lt;/a&gt; for more info.&lt;/p&gt;
&lt;p&gt;For this sample app I&amp;rsquo;ll go ahead and use the default column names: &amp;ldquo;avatar_file,&amp;rdquo; &amp;ldquo;avatar_small_file&amp;rdquo; and &amp;ldquo;avatar_thumb_file.&amp;rdquo; Here&amp;rsquo;s how to create those columns for a MySQL database. First create a new migration as usual:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate migration add_attachments_blob_avatar_to_user
exists  db/migrate
create  db/migrate/20090528173400_add_attachments_blob_avatar_to_user.rb&lt;/pre&gt;
&lt;p&gt;&amp;hellip; and then edit the new migration file and add the bolded code to it:&lt;/p&gt;
&lt;pre&gt;class AddAttachmentsBlobAvatarToUser &amp;lt; ActiveRecord::Migration
  def self.up&lt;b&gt;
    execute &amp;#x27;ALTER TABLE users ADD COLUMN avatar_file LONGBLOB&amp;#x27;
    execute &amp;#x27;ALTER TABLE users ADD COLUMN avatar_small_file LONGBLOB&amp;#x27;
    execute &amp;#x27;ALTER TABLE users ADD COLUMN avatar_thumb_file LONGBLOB&amp;#x27;&lt;/b&gt;
  end

  def self.down&lt;b&gt;
    remove_column :users, :avatar_file
    remove_column :users, :avatar_small_file
    remove_column :users, :avatar_thumb_file&lt;/b&gt;
  end
end&lt;/pre&gt;
&lt;p&gt;Normally to create a BLOB column you would use &amp;ldquo;add_column :users, :avatar_file, :binary.&amp;rdquo; This would work fine for Oracle and other database servers. MySQL, however, supports four different types of BLOBs: TINYBLOB (256 bytes), BLOB (64k bytes), MEDIUMBLOB (16MB) and LONGBLOB (4GB). (See &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html"&gt;http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html&lt;/a&gt; for more information.) If we used the Rails migrations :binary column type, then we would get normal BLOBs and have an upper limit for the file attachment size of 64k, which is not normally enough. Unfortunately, there&amp;rsquo;s no way to specify LONGBLOB for MySQL using Rails migrations, so you have to use the &amp;ldquo;execute&amp;rdquo; migration and write an actual SQL statement to add the column.&lt;/p&gt;
&lt;p&gt;Next go ahead and run your migrations and create the new columns:&lt;/p&gt;
&lt;pre&gt;$ rake db:migrate
(in /path/to/paperclip-sample-app)
==  AddAttachmentsBlobAvatarToUser: migrating =================================
-- execute(&amp;quot;ALTER TABLE users ADD COLUMN avatar_file LONGBLOB&amp;quot;)
   -&amp;gt; 0.0585s
-- execute(&amp;quot;ALTER TABLE users ADD COLUMN avatar_small_file LONGBLOB&amp;quot;)
   -&amp;gt; 0.0266s
-- execute(&amp;quot;ALTER TABLE users ADD COLUMN avatar_thumb_file LONGBLOB&amp;quot;)
   -&amp;gt; 0.0116s
==  AddAttachmentsBlobAvatarToUser: migrated (0.0973s) ========================&lt;/pre&gt;
&lt;p&gt;Now we just need to tell Paperclip to use database storage instead of the default file system storage and we&amp;rsquo;re ready to try our app and see if it saves the files into the new BLOB columns. Add the bolded parameter to has_attached_file in the User model:&lt;/p&gt;
&lt;pre&gt;class User &amp;lt; ActiveRecord::Base
  has_attached_file :avatar,
                    &lt;b&gt;:storage =&amp;gt; :database,&lt;/b&gt;
                    :styles =&amp;gt; { :thumb =&amp;gt; &amp;quot;75x75&amp;gt;&amp;quot;, :small =&amp;gt; &amp;quot;150x150&amp;gt;&amp;quot; },
                    :url =&amp;gt; &amp;#x27;/:class/:id/:attachment?style=:style&amp;#x27;
end&lt;/pre&gt;
&lt;p&gt;Note that I also removed the &amp;ldquo;:path&amp;rdquo; parameter; this value would be ignored by the database storage module anyway since the files will be stored in the DB. Let&amp;rsquo;s try it out! Start up the sample app, and re-edit a user record to upload a new image file:&lt;br /&gt;
  &lt;img src="http://patshaughnessy.net/assets/2009/4/30/mickey-edit.png"&gt;
&lt;/p&gt;
&lt;p&gt;Select a file, click &amp;ldquo;Update&amp;rdquo; to submit the form and the file will be processed by ImageMagick, and saved into our new BLOB columns by the database storage module in Paperclip&amp;hellip;&lt;br /&gt;
  &lt;img src="http://patshaughnessy.net/assets/2009/5/29/mickey-missing.png"&gt;
&lt;/p&gt;
&lt;p&gt;What? Where&amp;rsquo;s the image? It turns out that we still need to make a code change to the UsersController to download the image file from the BLOB column instead of from the file system. I&amp;rsquo;ll get to this in a moment. But first, let&amp;rsquo;s look at the console and see if the new files were saved into the database properly:&lt;/p&gt;
&lt;pre&gt;$ ./script/console 
Loading development environment (Rails 2.3.2)
&amp;gt;&amp;gt; User.first
=&amp;gt; #&amp;lt;User id: 1, name: &amp;quot;Mickey Mouse&amp;quot;, email: &amp;quot;mickey@disney.com&amp;quot;,
created_at: &amp;quot;2009-05-28 17:27:00&amp;quot;, updated_at: &amp;quot;2009-05-28 17:37:42&amp;quot;,
avatar_file_name: &amp;quot;mickey-mouse.jpg&amp;quot;, avatar_content_type: &amp;quot;image/jpeg&amp;quot;,
avatar_file_size: 137233, avatar_updated_at: &amp;quot;2009-05-28 17:37:42&amp;quot;,
avatar_file: &amp;quot;\377???JFIF\000\001\002\001\001h\001h\000\000\377?\021\b\002\210\001?\001\021\000\002\021\001\003\021\001\377?\204\000\001\001\001\001\001\001\001...&amp;quot;,
avatar_small_file: &amp;quot;\377???JFIF\000\001\001\001\001h\001h\000\000\377?C\000\003\002\002\002\002\002\003\002\002\002\003\003\003\003\004\006\004\004\004\004\004\b\006\006\005\006...&amp;quot;,
avatar_thumb_file: &amp;quot;\377???JFIF\000\001\001\001\001h\001h\000\000\377?C\000\003\002\002\002\002\002\003\002\002\002\003\003\003\003\004\006\004\004\004\004\004\b\006\006\005\006...&amp;quot;&amp;gt;&lt;/pre&gt;
&lt;p&gt;Here you can see the three new BLOB columns, avatar_file, avatar_small_file and avatar_medium_file, and the first few bytes of each column&amp;rsquo;s value. In fact, if you&amp;rsquo;re a real geek you&amp;rsquo;ll notice that the first few bytes contain &amp;ldquo;JFIF,&amp;rdquo; which is probably the image file type specification (not sure)&amp;hellip; so we know we are seeing the binary contents of the three versions of the Mickey image here. Great!&lt;/p&gt;
&lt;p&gt;Actually, not so great: there&amp;rsquo;s a subtle problem here we need to worry about. I actually typed in a very simple ActiveRecord command, &amp;ldquo;User.first,&amp;rdquo; and it loaded all three of the image files&amp;rsquo; contents into memory just so that I could inspect the value of the user record in the console. This was convenient now, since I was actually interested in knowing whether or not each of the files was saved properly in the DB. However, this is potentially a big performance problem in general. Imagine if the files were very large&amp;hellip; it could take a long time for all 3 of the files to be fetched by a SQL query and returned to the Rails ActiveRecord object. Do I really want or need this to happen every time I access a User record? Usually when I load a User record it&amp;rsquo;s just because I need to check the value of one of the metadata columns, like the user&amp;rsquo;s name, email address or something else. And if I do need one of the files, why should I have to load all three files? Spending the time required to load the file contents for each image style is a big performance penalty that isn&amp;rsquo;t usually necessary.&lt;/p&gt;
&lt;p&gt;The solution I came up for this problem was to enable Paperclip to add a method to your model class called &amp;ldquo;select_without_file_columns_for&amp;rdquo; that you can use as a named scope or, even better, a default scope. It returns a :select scope hash that will exclude the BLOB columns from the SQL query that ActiveRecord issues to load each record. If you&amp;rsquo;re using Rails 2.3 or higher, you can use select_without_file_columns_for as a default scope in your model like this:&lt;/p&gt;
&lt;pre&gt;class User &amp;lt; ActiveRecord::Base
  has_attached_file :avatar, :storage =&amp;gt; :database,
                    :styles =&amp;gt; { :thumb =&amp;gt; &amp;quot;75x75&amp;gt;&amp;quot;, :small =&amp;gt; &amp;quot;150x150&amp;gt;&amp;quot; },
                    :url =&amp;gt; &amp;#x27;/:class/:id/:attachment?style=:style&amp;#x27;
  &lt;b&gt;default_scope select_without_file_columns_for(:avatar)&lt;/b&gt;
end&lt;/pre&gt;
&lt;p&gt;To learn more about default scopes and to see a couple of other examples, read this: &lt;a href="http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping"&gt;http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping&lt;/a&gt;   &amp;hellip; or &lt;a href="http://m.onkey.org/2009/3/24/default-scopes-and-inheritance-to-the-rescue"&gt;http://m.onkey.org/2009/3/24/default-scopes-and-inheritance-to-the-rescue&lt;/a&gt;. Let&amp;rsquo;s see how this works in the console again after adding the default scope:&lt;/p&gt;
&lt;pre&gt;$ ./script/console 
Loading development environment (Rails 2.3.2)
&amp;gt;&amp;gt; User.first
=&amp;gt; #&amp;lt;User id: 1, name: &amp;quot;Mickey Mouse&amp;quot;, email: &amp;quot;mickey@disney.com&amp;quot;,
created_at: &amp;quot;2009-05-28 17:27:00&amp;quot;, updated_at: &amp;quot;2009-05-28 17:37:42&amp;quot;,
avatar_file_name: &amp;quot;mickey-mouse.jpg&amp;quot;, avatar_content_type: &amp;quot;image/jpeg&amp;quot;,
avatar_file_size: 137233, avatar_updated_at: &amp;quot;2009-05-28 17:37:42&amp;quot;&amp;gt;&lt;/pre&gt;
&lt;p&gt;Cool. Now the BLOB columns are not displayed. &amp;ldquo;Default scope&amp;rdquo; refers to the fact that the SQL used by ActiveRecord by default to load records is automatically changed. I didn&amp;rsquo;t have to pay the price of loading each of the files, and I was still able to load all of the other User columns using ActiveRecord the way I normally would. To see what happened, execute the &amp;ldquo;select_without_file_columns_for&amp;rdquo; method directly in the console:&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt; User.select_without_file_columns_for :avatar
=&amp;gt; {:select=&amp;gt;&amp;quot;id,name,email,created_at,updated_at,avatar_file_name,
  avatar_content_type,avatar_file_size,avatar_updated_at&amp;quot;}&lt;/pre&gt;
&lt;p&gt;It&amp;lsquo;s a lot more common to use a default or named scope with :conditions (to modify the WHERE clause) or :order (to modify the ORDER BY clause) but in this case I&amp;rsquo;ve used :select to specify which columns should be loaded by ActiveRecord (the SELECT portion of the SQL). If you look at the hash, you&amp;rsquo;ll see all of the User columns listed, except for avatar_file, avatar_small_file and avatar_thumb_file.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re using Rails 2.2 or earlier default scope is not available yet, and you will need to use a named scope, like this:&lt;/p&gt;
&lt;pre&gt;class User &amp;lt; ActiveRecord::Base
  has_attached_file :avatar,
                    :storage =&amp;gt; :database,
                    :styles =&amp;gt; { :thumb =&amp;gt; &amp;quot;75x75&amp;gt;&amp;quot;, :small =&amp;gt; &amp;quot;150x150&amp;gt;&amp;quot; },
                    :url =&amp;gt; &amp;#x27;/:class/:id/:attachment?style=:style&amp;#x27;
  &lt;b&gt;named_scope :without_file_data, select_without_file_columns_for(:avatar)&lt;/b&gt;
end&lt;/pre&gt;
&lt;p&gt;And you will need to use the named scope explicitly to avoid loading the files, like this:&lt;/p&gt;
&lt;pre&gt;$ ./script/console 
Loading development environment (Rails 2.3.2)
&amp;gt;&amp;gt; User.without_file_data.first
=&amp;gt; #&amp;lt;User id: 1, name: &amp;quot;Mickey Mouse&amp;quot;, email: &amp;quot;mickey@disney.com&amp;quot;,
created_at: &amp;quot;2009-05-30 12:14:03&amp;quot;, updated_at: &amp;quot;2009-05-30 12:14:03&amp;quot;,
avatar_file_name: &amp;quot;mickey-mouse.jpg&amp;quot;, avatar_content_type: &amp;quot;image/jpeg&amp;quot;,
avatar_file_size: 137233, avatar_updated_at: &amp;quot;2009-05-30 12:14:03&amp;quot;&amp;gt;&lt;/pre&gt;
&lt;p&gt;A good way to understand exactly what ActiveRecord is doing is to use a Ruby trick and open up the User class and add some debug code to it. Try entering this code into your console:&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt; class User &amp;lt; ActiveRecord::Base
&amp;gt;&amp;gt;   def self.find_by_sql(sql)
&amp;gt;&amp;gt;     puts &amp;quot;DEBUG: #{sql}&amp;quot;
&amp;gt;&amp;gt;     super
&amp;gt;&amp;gt;   end
&amp;gt;&amp;gt; end
=&amp;gt; nil&lt;/pre&gt;
&lt;p&gt;What this code does is open up our User model class, and override the &amp;ldquo;find_by_sql&amp;rdquo; ActiveRecord method to display the SQL statement before calling the original base class method to execute it. Find_by_sql is the method that the various different ActiveRecord find methods all call once they have constructed a SQL statement. For example, find :first,  find :all, first, last&amp;hellip; all of these eventually call find_by_sql.
Assuming we have the version of User with the named_scope, we can see what SQL statements are issued with or without the select_without_file_columns_for scope:&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt; User.first
&lt;b&gt;DEBUG: SELECT * FROM `users`  LIMIT 1&lt;/b&gt;
=&amp;gt; #&amp;lt;User id: 1, name: &amp;quot;Mickey Mouse&amp;quot;, email: &amp;quot;mickey@disney.com&amp;quot;,
created_at: &amp;quot;2009-05-28 17:27:00&amp;quot;, updated_at: &amp;quot;2009-05-28 17:37:42&amp;quot;,
avatar_file_name: &amp;quot;mickey-mouse.jpg&amp;quot;, avatar_content_type: &amp;quot;image/jpeg&amp;quot;,
avatar_file_size: 137233, avatar_updated_at: &amp;quot;2009-05-28 17:37:42&amp;quot;,
avatar_file: &amp;quot;\377???JFIF\000\001\002\001\001h\001h\000\000\377?\021\b\002\210\001?\001\021\000\002\021\001\003\021\001\377?\204\000\001\001\001\001\001\001\001...&amp;quot;,
avatar_small_file: &amp;quot;\377???JFIF\000\001\001\001\001h\001h\000\000\377?C\000\003\002\002\002\002\002\003\002\002\002\003\003\003\003\004\006\004\004\004\004\004\b\006\006\005\006...&amp;quot;,
avatar_thumb_file: &amp;quot;\377???JFIF\000\001\001\001\001h\001h\000\000\377?C\000\003\002\002\002\002\002\003\002\002\002\003\003\003\003\004\006\004\004\004\004\004\b\006\006\005\006...&amp;quot;&amp;gt;
&amp;gt;&amp;gt; User.without_file_data.first
&lt;b&gt;DEBUG: SELECT id,name,email,created_at,updated_at,avatar_file_name,
  avatar_content_type, avatar_file_size,avatar_updated_at FROM `users` LIMIT 1&lt;/b&gt;
=&amp;gt; #&amp;lt;User id: 1, name: &amp;quot;Mickey Mouse&amp;quot;, email: &amp;quot;mickey@disney.com&amp;quot;,
created_at: &amp;quot;2009-05-28 17:27:00&amp;quot;, updated_at: &amp;quot;2009-05-28 17:37:42&amp;quot;,
avatar_file_name: &amp;quot;mickey-mouse.jpg&amp;quot;, avatar_content_type: &amp;quot;image/jpeg&amp;quot;,
avatar_file_size: 137233, avatar_updated_at: &amp;quot;2009-05-28 17:37:42&amp;quot;&amp;gt;&lt;/pre&gt;
&lt;p&gt;Here we can see that ActiveRecord will load all of the User columns that are listed above in the hash we pass to named_scope&amp;hellip; all of the columns except for the BLOB columns. This is different from what ActiveRecord does by default, which is a simple SELECT * FROM &amp;hellip;. statement.&lt;/p&gt;
&lt;p&gt;Enough about ActiveRecord internals&amp;hellip; let&amp;rsquo;s get back to the sample app and finish it up:&lt;br /&gt;
    &lt;img src="http://patshaughnessy.net/assets/2009/5/29/mickey-missing.png"&gt;
  &lt;/p&gt;
&lt;p&gt;So why didn&amp;rsquo;t the image appear here properly? The reason is that in UsersController I&amp;rsquo;m still using the code that accesses the file on the file system and streams it to the client using send_file (see &lt;a href="http://patshaughnessy.net/2009/5/16/paperclip-sample-app-part-2-downloading-files-through-a-controller"&gt;my last post&lt;/a&gt; for more info):&lt;/p&gt;
&lt;pre&gt;def avatars
    user = User.find(params[:id])
    style = params[:style] ? params[:style] : &amp;#x27;original&amp;#x27;
    send_file user.avatar.path(style),
              :type =&amp;gt; user.avatar_content_type
  end&lt;/pre&gt;
&lt;p&gt;Obviously send_file is no longer going to work for us. Instead we need to use a similar function in ActionController::Streaming called send_data, which takes the binary data directly as a parameter instead of a file. And to access the file&amp;rsquo;s contents, I&amp;rsquo;ve added a method called &amp;ldquo;file_contents&amp;rdquo; to Paperclip that returns the actual file contents for the given style, or for the original style by default. Here&amp;rsquo;s how to put it all together; replace the &amp;ldquo;avatars&amp;rdquo; method in UsersController with this new version instead:&lt;/p&gt;
&lt;pre&gt;def avatars
    user = User.find(params[:id])
    style = params[:style] ? params[:style] : &amp;#x27;original&amp;#x27;
    &lt;b&gt;send_data user.avatar.file_contents(style),
              :type =&amp;gt; user.avatar_content_type&lt;/b&gt;
  end&lt;/pre&gt;
&lt;p&gt;  Only the line in bold has changed. We just call user.avatar.file_contents, pass in the specified style and then pass along the data to send_data.
  If you restart the app and refresh your browser, now you should see the image again:&lt;br /&gt;
      &lt;img src="http://patshaughnessy.net/assets/2009/5/29/mickey-small2.png"&gt;
    &lt;/p&gt;
&lt;p&gt;Now we are seeing the binary image file data loaded from the BLOB column by ActiveRecord and streamed down to the browser by send_data.&lt;/p&gt;
&lt;p&gt;One last detail about this: since usually everyone will use the same controller code to load the file contents for a given style from the BLOB, and then pass it along to send_data, I enabled Paperclip to add another utility method, this time to your controller, to make this even easier:&lt;/p&gt;
&lt;pre&gt;class UsersController &amp;lt; ApplicationController
  &lt;b&gt;downloads_files_for :user, :avatar&lt;/b&gt;
etc&amp;hellip;&lt;/pre&gt;
&lt;p&gt;If you call &amp;ldquo;downloads_files_for&amp;rdquo; from your controller like this and specify the model and file attachment, it will automatically generate the correct controller method for you, and call it &amp;ldquo;avatars&amp;rdquo; or whatever the plural version of your attachment name is. I chose the name to make it easy and natural to create a route to it in routes.rb. No need to even think about send_data or how to get the file contents from Paperclip at all! Nothing could be simpler. However, if you need to implement security or some other business rules around downloading files, then you might need to add that business logic to the &amp;ldquo;avatars&amp;rdquo; method above. Either way, it&amp;rsquo;s very simple.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-05-16:285</id>
    <published>2009-05-16T22:14:00Z</published>
    <updated>2009-05-17T12:20:19Z</updated>
    <category term="paperclip" />
    <category term="Rails" />
    <category term="paperclip" />
    <category term="rails" />
    <link href="http://patshaughnessy.net/2009/5/16/paperclip-sample-app-part-2-downloading-files-through-a-controller" rel="alternate" type="text/html" />
    <title>Paperclip sample app part 2: downloading files through a controller</title>
<content type="html">
            &lt;p&gt;&lt;a href="http://patshaughnessy.net/2009/4/30/paperclip-sample-app"&gt;Last time&lt;/a&gt; I wrote about how to quickly setup a Rails application using scaffolding that allows users to upload image files and then display them using the &lt;a href="http://www.thoughtbot.com/projects/paperclip"&gt;Paperclip plugin&lt;/a&gt;. Paperclip does the simplest thing possible by default: it saves the file attachments right on the file system of your web server, allowing you to download them to users easily using Apache or whatever web server you have installed.&lt;/p&gt;
&lt;p&gt;Today I&amp;rsquo;d like to take that sample app one step further and show how to use a Rails controller to download the files, instead of directly through Apache. To get the finished code just go to &lt;a href="http://github.com/patshaughnessy/paperclip-sample-app"&gt;http://github.com/patshaughnessy/paperclip-sample-app&lt;/a&gt; and look at the &amp;ldquo;part2&amp;rdquo; folder.&lt;/p&gt;
&lt;p&gt;There are a variety of reasons why you might want to do this, including:
  &lt;ul&gt;
    &lt;li&gt;Security: you don&amp;rsquo;t want to expose all of the file attachments to all users of your web site. Instead, you want to implement some business rules and show some files to some users, but not to others.&lt;/li&gt;
    &lt;li&gt;Auditing/logging: you want to keep track of who is viewing which files, or how many times they are viewing them.&lt;/li&gt;
    &lt;li&gt;You want to hide the actual location of the files from users, and instead map the files to URLs in some other pattern or manner.&lt;/li&gt;
    &lt;li&gt;Or, you might want not want to store the files on your web server&amp;rsquo;s file system at all, but instead in a database table or somewhere else. In Part 3 of this series, I&amp;rsquo;ll show how to do this&amp;hellip;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;The common thread here is that you want to execute some Ruby code every time a users accesses a file, and the way to do that is by routing the download requests through a controller.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s pick up where we left off &lt;a href="http://patshaughnessy.net/2009/4/30/paperclip-sample-app"&gt;last time&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://patshaughnessy.net/assets/2009/4/30/mickey-index.png"&gt;&lt;/p&gt;
&lt;p&gt;If we take a look at some of the HTML source for this page:&lt;/p&gt;
&lt;pre&gt;&amp;lt;h1&amp;gt;Listing users&amp;lt;/h1&amp;gt;
&amp;lt;table&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;th&amp;gt;Photo&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Name&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Email&amp;lt;/th&amp;gt;
  &amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;img alt=&amp;quot;Mickey-mouse&amp;quot;
      src=&amp;quot;&lt;b&gt;/system/avatars/1/thumb/mickey-mouse.jpg?1242395876&lt;/b&gt;&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;Mickey Mouse&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;mickey@disney.com&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;a href=&amp;quot;/users/1&amp;quot;&amp;gt;Show&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;a href=&amp;quot;/users/1/edit&amp;quot;&amp;gt;Edit&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;hellip; we can see that Paperclip&amp;rsquo;s &amp;ldquo;url&amp;rdquo; function which we called in index.html.erb is returning a pointer to the actual location of the file on the web server&amp;rsquo;s hard drive, under the public/system folder:&lt;/p&gt;
&lt;pre&gt;$ find public/system
public/system
public/system/avatars
public/system/avatars/1
public/system/avatars/1/original
public/system/avatars/1/original/mickey-mouse.jpg
public/system/avatars/1/small
public/system/avatars/1/small/mickey-mouse.jpg
public/system/avatars/1/thumb
public/system/avatars/1/thumb/mickey-mouse.jpg&lt;/pre&gt;
&lt;p&gt;Now let&amp;rsquo;s say that we want to implement some simple security around these images&amp;hellip;. reason #1 from my list above. The first thing we&amp;rsquo;ll need to do, then, is to remove the image files from the public folder and instead save them in some non-public place on our web server, for example:&lt;/p&gt;
&lt;pre&gt;$ mkdir non-public
$ mv public/system non-public/.&lt;/pre&gt;
&lt;p&gt;Now let&amp;rsquo;s double check that Apache can&amp;rsquo;t find the files in their new location:&lt;br /&gt;
  &lt;img src="http://patshaughnessy.net/assets/2009/5/15/mickey-index-missing.png"&gt;&lt;/p&gt;
&lt;p&gt;Great! We see a missing image as expected. No users can see the files unless we run some bit of Ruby code to enable access. Now&amp;hellip; how can we use a controller to download the files through Rails, instead of through Apache? The first thing we need to do is add a route to routes.rb for accessing the files.&lt;/p&gt;
&lt;p&gt;If you open up routes.rb and look at what the scaffolding generator created for us, you&amp;rsquo;ll see this:&lt;/p&gt;
&lt;pre&gt;ActionController::Routing::Routes.draw do |map|
  map.resources :users
  ...etc...
  map.connect ':controller/:action/:id'
  map.connect ':controller/:action/:id.:format'
end&lt;/pre&gt;
&lt;p&gt;The map.resources line indicates that our application supports a series of routes that handle the four REST actions: GET, POST, PUT and DELETE. The best way to get a handle on how the routes work is by running &amp;ldquo;rake routes&amp;rdquo; to list out all the URL patterns that Rails will match on:&lt;/p&gt;
&lt;pre&gt;$ rake routes
(in /Users/pat/rails-apps/paperclip-sample-app)
    users GET    /users(.:format)          {:action=&amp;gt;&amp;quot;index&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
          POST   /users(.:format)          {:action=&amp;gt;&amp;quot;create&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
 new_user GET    /users/new(.:format)      {:action=&amp;gt;&amp;quot;new&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
edit_user GET    /users/:id/edit(.:format) {:action=&amp;gt;&amp;quot;edit&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
     user GET    /users/:id(.:format)      {:action=&amp;gt;&amp;quot;show&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
          PUT    /users/:id(.:format)      {:action=&amp;gt;&amp;quot;update&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
          DELETE /users/:id(.:format)      {:action=&amp;gt;&amp;quot;destroy&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
                 /:controller/:action/:id           
                 /:controller/:action/:id(.:format)&lt;/pre&gt;
&lt;p&gt;The last two lines are the &amp;ldquo;default routes,&amp;rdquo; which connect any URL matching the pattern controller/action/id to the corresponding controller. We could just go ahead and use the default routes, but to learn a bit more about how map.resources works, let&amp;rsquo;s create a new URL pattern for our users that we&amp;rsquo;ll use in a minute to download the avatar file attachments with. Edit routes.rb and add the :member parameter in bold:&lt;/p&gt;
&lt;pre&gt;ActionController::Routing::Routes.draw do |map|
  map.resources :users&lt;b&gt;, :member =&gt; { :avatars =&gt; :get }&lt;/b&gt;
etc...&lt;/pre&gt;
&lt;p&gt;If we now re-run rake routes, we can see that a new URL pattern was created for us that we can use to download the avatar images via a GET request:&lt;/p&gt;
&lt;pre&gt;$ rake routes
(in /Users/pat/rails-apps/paperclip-sample-app)
      users GET    /users(.:format)          {:action=&amp;gt;&amp;quot;index&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
            POST   /users(.:format)          {:action=&amp;gt;&amp;quot;create&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
   new_user GET    /users/new(.:format)      {:action=&amp;gt;&amp;quot;new&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
  edit_user GET    /users/:id/edit(.:format) {:action=&amp;gt;&amp;quot;edit&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
&lt;b&gt;avatars_user GET   /users/:id/avatars(.:format) {
                                              :action=&amp;gt;&amp;quot;avatars&amp;quot;,
                                              :controller=&amp;gt;&amp;quot;users&amp;quot;
                                             }&lt;/b&gt;
       user GET    /users/:id(.:format)      {:action=&amp;gt;&amp;quot;show&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
            PUT    /users/:id(.:format)      {:action=&amp;gt;&amp;quot;update&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
            DELETE /users/:id(.:format)      {:action=&amp;gt;&amp;quot;destroy&amp;quot;, :controller=&amp;gt;&amp;quot;users&amp;quot;}
                   /:controller/:action/:id           
                   /:controller/:action/:id(.:format)&lt;/pre&gt;
&lt;p&gt;Now to get the avatar for user 7, for example, we can issue a URL like this:&lt;/p&gt;
&lt;pre&gt;http://localhost:3000/users/7/avatars&lt;/pre&gt;
&lt;p&gt;&amp;hellip; and the request will be routed to the &amp;ldquo;avatars&amp;rdquo; action in the &amp;ldquo;users&amp;rdquo; controller (plural since a user might have more than one style of avatar). So now let&amp;rsquo;s go right ahead and implement the avatars method and add some code to download a file to the client. The way to do that is to use &lt;a href="http://api.rubyonrails.org/classes/ActionController/Streaming.html"&gt;ActionController::Streaming::send_file&lt;/a&gt;. It&amp;rsquo;s simple enough; we just need to pass the file&amp;rsquo;s path to send_file as well as the MIME content type which the client uses as a clue for deciding how to display the file, and that&amp;rsquo;s it! Let&amp;rsquo;s hard code these values for now and see if it all works (update the path here for your machine):&lt;/p&gt;
&lt;pre&gt;class UsersController &amp;lt; ApplicationController
  def avatars
    send_file &amp;#x27;/path/to/non-public/system/avatars/1/original/mickey-mouse.jpg&amp;#x27;,
      :type =&amp;gt; &amp;#x27;image/jpeg&amp;#x27;
  end&lt;/pre&gt;
&lt;p&gt;Now if you type &lt;a href="http://localhost:3000/users/1/avatars"&gt;http://localhost:3000/users/1/avatars&lt;/a&gt; into your browser you should see the mickey image again. If not, then double check your code changes, where the files are actually located on the hard drive now and also try stopping and reloading the Rails app since changes to routes.rb are cached and are only loaded when Rails is initialized.&lt;/p&gt;
&lt;p&gt;Instead of hard coding the path in the avatars method, we obviously need to be able to handle requests for any avatar file attachment for any user record. Before we enhance our code to do this, let&amp;rsquo;s take a few minutes to configure Paperclip and tell it where the files are now stored on the file system, and which URL we have configured our routes.rb file to use. This will make our work coding in the controller a lot easier, and also indicate to Paperclip where new file attachments should be uploaded to. To do this, we need to add a couple of parameters to our call to has_attached_file in our User model (user.rb), shown here in bold (again, update the path for your machine):&lt;/p&gt;
&lt;pre&gt;class User &amp;lt; ActiveRecord::Base
  has_attached_file :avatar,
    :styles =&amp;gt; { :thumb =&amp;gt; &amp;quot;75x75&amp;gt;&amp;quot;, :small =&amp;gt; &amp;quot;150x150&amp;gt;&amp;quot; },
    &lt;b&gt;:path =&amp;gt; &amp;#x27;/path/to/non-public/system/avatars/1/original/mickey-mouse.jpg&amp;#x27;,
    :url =&amp;gt; &amp;#x27;users/1/avatars&amp;#x27;&lt;/b&gt;
end&lt;/pre&gt;
&lt;p&gt;Just to take one step at a time, I&amp;rsquo;ve hard coded the URL and path again here in the model. But now we can generalize our code in UserController to handle any user, like this:&lt;/p&gt;
&lt;pre&gt;def avatars
  user = User.find(params[:id])
  send_file user.avatar.path, :type =&amp;gt; user.avatar_content_type
end&lt;/pre&gt;
&lt;p&gt;Now we can test &lt;a href="http://localhost:3000/users/1/avatars"&gt;http://localhost:3000/users/1/avatars&lt;/a&gt; again to be sure that we haven&amp;rsquo;t broken anything. If it&amp;rsquo;s all working, lets&amp;rsquo; proceed to clean up the hard coding in user.rb. It turns out that Paperclip uses the same interpolations idea that we saw above in routes.rb. So I can use symbols like :rails_root, :id, :style, etc., and they will be evaluated to the values I expect and need. Here&amp;rsquo;s the finished code in my model:&lt;/p&gt;
&lt;pre&gt;
has_attached_file :avatar,
  :styles =&amp;gt; { :thumb =&amp;gt; &amp;quot;75x75&amp;gt;&amp;quot;, :small =&amp;gt; &amp;quot;150x150&amp;gt;&amp;quot; },
  :path =&amp;gt; 
    &amp;#x27;:rails_root/non-public/system/:attachment/:id/:style/:basename.:extension&amp;#x27;,
  :url =&amp;gt; &amp;#x27;/:class/:id/:attachment&amp;#x27;                    
&lt;/pre&gt;
&lt;p&gt;If we open up the console and take a look at our user object there, we can see that Paperclip is substituting the correct values for each of the symbols I&amp;rsquo;ve provided:&lt;/p&gt;
&lt;pre&gt;$ ./script/console
Loading development environment (Rails 2.3.2)
&amp;gt;&amp;gt; User.first.avatar.url
=&amp;gt; &amp;quot;/users/1/avatars?1242395876&amp;quot;       (time stamp appended here automatically)
&amp;gt;&amp;gt; User.first.avatar.path
=&amp;gt; &amp;quot;/Users/pat/.../non-public/system/avatars/1/original/mickey-mouse.jpg&amp;quot;&lt;/pre&gt;
&lt;p&gt;Now let&amp;rsquo;s go back and test our original application again with our new code:
  &lt;ul&gt;
    &lt;li&gt;The new route in routes.rb&lt;/li&gt;
    &lt;li&gt;The new action in UserController&lt;/li&gt;
    &lt;li&gt;And the :url and :path parameters added to has_attached_file in the User model.&lt;/li&gt;
  &lt;/ul&gt;&lt;br /&gt;
  &lt;img src="http://patshaughnessy.net/assets/2009/5/15/mickey-index-large.png"&gt;&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;Oops&amp;hellip; we see the large image again. It doesn&amp;rsquo;t work! What happened? Well, it turns our that we forgot one detail in our new avatars method in UserController. Our code always returns the default, or &amp;ldquo;original&amp;rdquo; style of the file attachment, but in the users index view we actually display the thumbnail image using image_tag user.avatar.url(:thumb). So our controller code needs to be able to handle requests for other styles as well. To do this, we need to pass the requested style somehow. The simplest thing to do is just to add the style as a URL parameter to the download request, like this:&lt;/p&gt;
&lt;pre&gt;
  http://localhost:3000/users/1/avatar?style=thumb
&lt;/pre&gt;
&lt;p&gt;(We could also add the style to the URL's path, but that would require another change to routes.rb.) To make this work, first I need to tell Paperclip about how I want to handle the style value in the URL:&lt;/p&gt;
&lt;pre&gt;
has_attached_file :avatar,
  :styles =&amp;gt; { :thumb =&amp;gt; &amp;quot;75x75&amp;gt;&amp;quot;, :small =&amp;gt; &amp;quot;150x150&amp;gt;&amp;quot; },
  :path =&amp;gt; 
    &amp;#x27;:rails_root/non-public/system/:attachment/:id/:style/:basename.:extension&amp;#x27;,
  :url =&amp;gt; &amp;#x27;/:class/:id/avatar&lt;b&gt;?style=:style&lt;/b&gt;&amp;#x27;
&lt;/pre&gt;
&lt;p&gt;And now I need to handle this new parameter in my controller:&lt;/p&gt;
&lt;pre&gt;def avatars
  user = User.find(params[:id])
  &lt;b&gt;style = params[:style] ? params[:style] : &amp;#x27;original&amp;#x27;&lt;/b&gt;
  send_file user.avatar.path&lt;b&gt;(style)&lt;/b&gt;,
            :type =&amp;gt; user.avatar_content_type
end&lt;/pre&gt;
&lt;p&gt;I don&amp;rsquo;t need to change anything in index.html.erb since there we call image_tag user.avatar.url(:thumb) which picks up the new URL pattern from Paperclip.&lt;/p&gt;
&lt;p&gt;And now, if I&amp;rsquo;ve got all of this correct, I should be able to finally see the thumbnail image again on the index page:&lt;br /&gt;
  &lt;img src="http://patshaughnessy.net/assets/2009/4/30/mickey-index.png"&gt;&lt;/p&gt;
&lt;p&gt;And finally we have files being downloaded by Ruby code present in the UserController class. If we actually wanted to implement security, logging or some other sort of logic we would just add code to the avatars method in UserController. For example, avatars could return a 401 (unauthorized) error if the user wasn&amp;rsquo;t logged in, or didn&amp;rsquo;t have access to view Mickey&amp;rsquo;s image for some reason.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it for now; next time I&amp;rsquo;ll modify this sample app once more to demonstrate how we can store the image files in a database table, instead of in the &amp;ldquo;non-public&amp;rdquo; folder or anywhere on the file system.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-04-30:214</id>
    <published>2009-04-30T19:20:00Z</published>
    <updated>2009-10-17T00:17:10Z</updated>
    <category term="paperclip" />
    <category term="Rails" />
    <category term="paperclip" />
    <category term="rails" />
    <link href="http://patshaughnessy.net/2009/4/30/paperclip-sample-app" rel="alternate" type="text/html" />
    <title>Paperclip sample app</title>
<content type="html">
            &lt;p&gt;(Update October 2009)&lt;br /&gt;I just updated a gem I wrote called &lt;a href="http://patshaughnessy.net/view_mapper"&gt;View Mapper&lt;/a&gt; that will generate all of the code I describe below&amp;hellip; you can use View Mapper to generate working scaffolding code that uploads/downloads files using Paperclip, or only view scaffolding code that works with an existing model in your app; for more details see: &lt;a href="http://patshaughnessy.net/2009/10/16/paperclip-scaffolding"&gt;http://patshaughnessy.net/2009/10/16/paperclip-scaffolding&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I love scaffolding. Many experienced Rails developers scoff at the idea of using scaffolding to generate Rails code: it&amp;rsquo;s ugly; it probably means you don&amp;rsquo;t understand how to write the code yourself; it generates a lot more code than you need, etc., etc. However, for a beginning Rails developer working on her/his own like me who isn&amp;rsquo;t surrounded by a team of Ruby experts, scaffolding is an essential tool and can help to get started in the right direction. Also, even for experienced Rubyists scaffolding can be a great way to quickly (minutes, not hours or days) get a simple app up and running to use for demos, UI wireframes, spiking some technical issue, etc.&lt;/p&gt;
&lt;p&gt;This post will demonstrate how to use scaffolding to create a new Rails app from scratch that uses the Paperclip plugin to upload and display an image file. Feel free to copy/paste pieces of code from the narrative below and use them in your app, or you can just skip to the chase and &lt;a href="http://github.com/patshaughnessy/paperclip-sample-app"&gt;get the finished version from github&lt;/a&gt; and run that on your machine.&lt;/p&gt;
&lt;p&gt;There are a lot of other good tutorials out there about this; see:
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="http://burm.net/2008/10/07/the-ruby-on-rails-paperclip-plugin-tutorial-easy-image-attachments"&gt;http://burm.net/2008/10/07/the-ruby-on-rails-paperclip-plugin-tutorial-easy-image-attachments&lt;/a&gt;, or&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://jimneath.org/2008/04/17/paperclip-attaching-files-in-rails"&gt;http://jimneath.org/2008/04/17/paperclip-attaching-files-in-rails&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;and of course Ryan Bates has a &lt;a href="http://railscasts.com/episodes/134-paperclip"&gt;screen cast on this topic also&lt;/a&gt;.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll take on the risk of repeating material that&amp;rsquo;s already out there in order to show how easy it is to get a working Paperclip application up and running using scaffolding. The fact that just a few commands and lines of code are required illustrates just how simple and powerful Paperclip&amp;rsquo;s design is. In my next post, I&amp;rsquo;ll proceed to change this sample app to demonstrate how to save the uploaded files in a database column instead of on the web server&amp;rsquo;s file system, using &lt;a href="http://github.com/patshaughnessy/paperclip"&gt;my modified version of Paperclip&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;FYI At the time I wrote this, Rails was at version 2.3.2:&lt;/p&gt;
&lt;pre&gt;$ rails --version
Rails 2.3.2&lt;/pre&gt;
&lt;p&gt;Let&amp;rsquo;s get started by creating a new Rails application:&lt;/p&gt;
&lt;pre&gt;$ rails paperclip-sample-app
      create  
      create  app/controllers
      create  app/helpers
      create  app/models
      create  app/views/layouts
      create  config/environments
      create  config/initializers
      create  config/locales
      create  db
      create  doc
      create  lib
      create  lib/tasks
      create  log
      etc...&lt;/pre&gt;
&lt;p&gt;Before we go any farther, let&amp;rsquo;s setup our database.yml file and create a new MySQL database to use with the sample app. Replace the contents of config/database.yml with this:&lt;/p&gt;
&lt;pre&gt;development:
    adapter: mysql
    database: paperclip_sample_app_development
    username: root
    password: 
    host: localhost&lt;/pre&gt;
&lt;p&gt;Enter the proper username and password for MySQL if they are not &amp;ldquo;root&amp;rdquo; and null. And then run this from the command line:&lt;/p&gt;
&lt;pre&gt;$ cd paperclip-sample-app
$ rake db:create
(in /Users/pat/rails-apps/paperclip-sample-app)&lt;/pre&gt;
&lt;p&gt;Ok, now we have a MySQL database to work with. Next, let&amp;rsquo;s go ahead and install the Paperclip plugin. The best thing to do is just to get the latest version from github; Thoughtbot frequently updates it with bug fixes, enhancements, etc.:&lt;/p&gt;
&lt;pre&gt;$ ./script/plugin install git://github.com/thoughtbot/paperclip.git
Initialized empty Git repository in /Users/pat/rails-apps/paperclip-sample-app/vendor/plugins/paperclip/.git/
remote: Counting objects: 62, done.
remote: Compressing objects: 100% (50/50), done.
remote: Total 62 (delta 6), reused 39 (delta 4)
Unpacking objects: 100% (62/62), done.
From git://github.com/thoughtbot/paperclip
 * branch            HEAD       -&amp;gt; FETCH_HEAD&lt;/pre&gt;
&lt;p&gt;Now that we have an empty, shell application created and the Paperclip plugin installed, we can use scaffolding to add some working code to it. Let&amp;rsquo;s use the same &amp;ldquo;user&amp;rdquo; and &amp;ldquo;avatar&amp;rdquo; example Thoughtbot does on the &lt;a href="http://thoughtbot.com/projects/paperclip"&gt;Paperclip project page&lt;/a&gt;. The idea is that the sample will contain a table of users, and each user will have an avatar image displayed in the web site. So to get started, I&amp;rsquo;ll just create a new &amp;ldquo;user&amp;rdquo; model with string columns for the name and email address:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate scaffold user name:string email:string
      exists  app/models/
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/users
      exists  app/views/layouts/
      exists  test/functional/
      exists  test/unit/
      create  test/unit/helpers/
      exists  public/stylesheets/
      create  app/views/users/index.html.erb
      create  app/views/users/show.html.erb
      etc...&lt;/pre&gt;
&lt;p&gt;Now we need to generate the database columns necessary for Paperclip on our new model object using script/generate:&lt;/p&gt;
&lt;pre&gt;$ ./script/generate paperclip user avatar
      exists  db/migrate
      create  db/migrate/20090430084151_add_attachments_avatar_to_user.rb&lt;/pre&gt;
&lt;p&gt;And let&amp;rsquo;s go ahead and create the users table using db:migrate:&lt;/p&gt;
&lt;pre&gt;$ rake db:migrate
(in /Users/pat/rails-apps/paperclip-sample-app)
==  CreateUsers: migrating ====================================================
-- create_table(:users)
   -&amp;gt; 0.0031s
==  CreateUsers: migrated (0.0032s) ===========================================

==  AddAttachmentsAvatarToUser: migrating =====================================
-- add_column(:users, :avatar_file_name, :string)
   -&amp;gt; 0.0063s
-- add_column(:users, :avatar_content_type, :string)
   -&amp;gt; 0.0069s
-- add_column(:users, :avatar_file_size, :integer)
   -&amp;gt; 0.0085s
-- add_column(:users, :avatar_updated_at, :datetime)
   -&amp;gt; 0.0081s
==  AddAttachmentsAvatarToUser: migrated (0.0311s) ============================&lt;/pre&gt;
&lt;p&gt;You can see that the Paperclip generator created columns in the users table called &amp;ldquo;avatar_file_name,&amp;rdquo; &amp;ldquo;avatar_content_type,&amp;rdquo; &amp;ldquo;avatar_file_size&amp;rdquo; and &amp;ldquo;avatar_updated_at.&amp;rdquo; Now we have our database schema setup. The next step is to just modify the code that was generated for us by the scaffolding and make the changes necessary for Paperclip. The first thing to do is to add a line to the user model and indicate that it has a file attachment called &amp;ldquo;avatar.&amp;rdquo; To do this, open app/models/user.rb and just add this one line:&lt;/p&gt;
&lt;pre&gt;class User &amp;lt; ActiveRecord::Base
  has_attached_file :avatar
end&lt;/pre&gt;
&lt;p&gt;And then edit the new user form (app/views/users/new.html.erb) and add a file field to use to upload files. There are actually two code changes you need to make: first you need to set the HTML form to encode the uploaded file data (and other fields) using MIME multiple part syntax, and then second you need to actually add the file upload field. Here&amp;rsquo;s the finished new.html.erb file with these two changes in bold:&lt;/p&gt;
&lt;pre&gt;&amp;lt;h1&amp;gt;New user&amp;lt;/h1&amp;gt;

&amp;lt;% form_for(@user&lt;b&gt;, :html =&amp;gt; { :multipart =&amp;gt; true }&lt;/b&gt;) do |f| %&amp;gt;
  &amp;lt;%= f.error_messages %&amp;gt;

  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :name %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= f.text_field :name %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :email %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= f.text_field :email %&amp;gt;
  &amp;lt;/p&amp;gt;
  &lt;b&gt;&amp;lt;p&amp;gt;
    &amp;lt;%= f.label :avatar %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= f.file_field :avatar %&amp;gt;
  &amp;lt;/p&amp;gt;&lt;/b&gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.submit &amp;#x27;Create&amp;#x27; %&amp;gt;
  &amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;

&amp;lt;%= link_to &amp;#x27;Back&amp;#x27;, users_path %&amp;gt;&lt;/pre&gt;
&lt;p&gt;Also make the same changes to the edit form that was generated by the scaffolding: app/views/users/edit.html.erb. The best thing to do would be to include the same ERB file (maybe called &amp;ldquo;_form.html.erb&amp;rdquo;) in both the new and edit form files. Ideally the scaffolding generator would have done this for us&amp;hellip;&lt;/p&gt;
&lt;p&gt;Now if we run our application we can upload an image file and attach it to a user:&lt;br /&gt;
&lt;img src="http://patshaughnessy.net/assets/2009/4/30/mickey-new.png" /&gt;&lt;/p&gt;
&lt;p&gt;If you submit this form, the image file will be uploaded to the server and saved on the file system. By default, Paperclip saves files inside a &amp;ldquo;system&amp;rdquo; folder it creates in your Rails app&amp;rsquo;s public folder. Let&amp;rsquo;s take a look at my public folder and see where the file went:&lt;/p&gt;
&lt;pre&gt;$ find public/system
public/system
public/system/avatars
public/system/avatars/1
public/system/avatars/1/original
public/system/avatars/1/original/mickey-mouse.jpg&lt;/pre&gt;
&lt;p&gt;This is one of the nice things about Paperclip: it just works. I don&amp;rsquo;t have to think about or worry about where the files are going to go; Thoughtbot has chosen simple default values that make sense. Here we can see that there are a series of folders created that correspond to the attachment name, model primary key and also the &amp;ldquo;style&amp;rdquo; of the attachment (more on that below).&lt;/p&gt;
&lt;p&gt;If you want to or need to save the files in some other place on your server&amp;rsquo;s file system you can specify different options to has_attached_file in your model; see this write up for an example: &lt;a href="http://travisonrails.com/2009/01/11/Changing-Paperclip-File-Storage-Location"&gt;http://travisonrails.com/2009/01/11/Changing-Paperclip-File-Storage-Location&lt;/a&gt;. Paperclip also supports saving the files in Amazon&amp;rsquo;s S3 storage service, and in my next post I&amp;rsquo;ll demonstrate how to save the file data inside the database itself, right in the users table in this example.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m almost done; now I just need to display the uploaded image somewhere; the simplest thing to do is just to add an image tag to the users show page. Again, my changes to the standard scaffolding code are in bold:&lt;/p&gt;
&lt;pre&gt;&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Name:&amp;lt;/b&amp;gt;
  &amp;lt;%=h @user.name %&amp;gt;
&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Email:&amp;lt;/b&amp;gt;
  &amp;lt;%=h @user.email %&amp;gt;
&amp;lt;/p&amp;gt;

&lt;b&gt;&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Avatar:&amp;lt;/b&amp;gt;
  &amp;lt;%= image_tag @user.avatar.url %&amp;gt;
&amp;lt;/p&amp;gt;&lt;/b&gt;

&amp;lt;%= link_to &amp;#x27;Edit&amp;#x27;, edit_user_path(@user) %&amp;gt; |
&amp;lt;%= link_to &amp;#x27;Back&amp;#x27;, users_path %&amp;gt;&lt;/pre&gt;
&lt;p&gt;Now we can see the image for our new user:&lt;br /&gt;
&lt;img src="http://patshaughnessy.net/assets/2009/4/30/mickey-large.png"&gt;&lt;/p&gt;
&lt;p&gt;Since this image is bigger that what I would like, I can take advantage of Paperclip &amp;ldquo;styles&amp;rdquo; feature to generate a smaller version of it. To do that you will need to be sure you have ImageMagick installed on your server, which is what Paperclip uses behind the scenes to modify image files. Then all you need to do is just add two &amp;ldquo;styles&amp;rdquo; to your model, like this:&lt;/p&gt;
&lt;pre&gt;class User &amp;lt; ActiveRecord::Base
  has_attached_file :avatar,
                    :styles =&amp;gt; {
                      :thumb =&amp;gt; &amp;quot;75x75&amp;gt;&amp;quot;,
                      :small =&amp;gt; &amp;quot;150x150&amp;gt;&amp;quot;
                    }
end&lt;/pre&gt;
&lt;p&gt;The strings we pass in are actually options for ImageMagick's "convert" command; see &lt;a href="http://www.imagemagick.org/script/convert.php"&gt;it&amp;rsquo;s documentation&lt;/a&gt; for more details. And now in the show ERB we can just specify the &amp;ldquo;small&amp;rdquo; style in the image tag instead:&lt;/p&gt;
&lt;pre&gt;&amp;lt;%= image_tag @user.avatar.url(:small) %&amp;gt;&lt;/pre&gt;
&lt;p&gt;To see it, first I need to re-edit and re-upload the image (remember to add the file field code to edit.html.erb just like for new.html.erb):&lt;br /&gt;
&lt;img src="http://patshaughnessy.net/assets/2009/4/30/mickey-edit.png"&gt;&lt;/p&gt;
&lt;p&gt;Now when this form is submitted we will see the smaller image:&lt;br /&gt;
  &lt;img src="http://patshaughnessy.net/assets/2009/4/30/mickey-small.png"&gt;&lt;/p&gt;
And let&amp;rsquo;s take another look at the public/system folder and see what Paperclip and ImageMagick have done for us:&lt;/p&gt;
&lt;pre&gt;$ find public/system
public/system
public/system/avatars
public/system/avatars/1
public/system/avatars/1/original
public/system/avatars/1/original/mickey-mouse.jpg
public/system/avatars/1/small
public/system/avatars/1/small/mickey-mouse.jpg
public/system/avatars/1/thumb
public/system/avatars/1/thumb/mickey-mouse.jpg&lt;/pre&gt;
&lt;p&gt;Again, this is very simple and just works! As a last step, let&amp;rsquo;s add the thumbnail image to the users index page so we can see Mickey without even clicking on that user record. This is as simple as editing app/views/users/index.html.erb and adding a new table column:&lt;/p&gt;
&lt;pre&gt;&amp;lt;table&amp;gt;
  &amp;lt;tr&amp;gt;
    &lt;b&gt;&amp;lt;th&amp;gt;Photo&amp;lt;/th&amp;gt;&lt;/b&gt;
    &amp;lt;th&amp;gt;Name&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Email&amp;lt;/th&amp;gt;
  &amp;lt;/tr&amp;gt;

&amp;lt;% @users.each do |user| %&amp;gt;
  &amp;lt;tr&amp;gt;
    &lt;b&gt;&amp;lt;td&amp;gt;&amp;lt;%= image_tag user.avatar.url(:thumb) %&amp;gt;&amp;lt;/td&amp;gt;&lt;/b&gt;
    &amp;lt;td&amp;gt;&amp;lt;%=h user.name %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%=h user.email %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;#x27;Show&amp;#x27;, user %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;#x27;Edit&amp;#x27;, edit_user_path(user) %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;#x27;Destroy&amp;#x27;, user, :confirm =&amp;gt; &amp;#x27;Are you sure?&amp;#x27;, :method =&amp;gt; :delete %&amp;gt;&amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;
&amp;lt;% end %&amp;gt;
&amp;lt;/table&amp;gt;&lt;/pre&gt;
&lt;p&gt;And now we just need to refresh the index page since the thumb image file was already generated:&lt;br /&gt;
  &lt;img src="http://patshaughnessy.net/assets/2009/4/30/mickey-index.png"&gt;&lt;/p&gt;
&lt;p&gt;And there you have it: a working file upload web site written in minutes. This was made possible by Rails scaffolding, and Paperclip's simple, elegant design.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-04-14:179</id>
    <published>2009-04-14T17:48:00Z</published>
    <updated>2009-04-14T17:48:00Z</updated>
    <category term="paperclip" />
    <category term="paperclip-database-storage" />
    <category term="Rails" />
    <category term="paperclip" />
    <category term="rails" />
    <link href="http://patshaughnessy.net/2009/4/14/database-storage-for-paperclip-rewritten-to-use-a-single-table" rel="alternate" type="text/html" />
    <title>Database storage for Paperclip: rewritten to use a single table</title>
<content type="html">
            &lt;p&gt;Back in February I wrote an &lt;a href="http://patshaughnessy.net/2009/2/19/database-storage-for-paperclip"&gt;implementation of a new storage module for Paperclip&lt;/a&gt; that supports saving file attachments in a database table. My original implementation saved the file attachments in a separate database table, which was internally managed using a &amp;ldquo;has_many&amp;rdquo; relationship from the target model.&lt;/p&gt;
&lt;p&gt;This month I decided to rewrite the code to use a simpler, single table approach. Instead of saving the files in a separate table, each file is saved in a BLOB column in the same table as the target model. This makes the database storage module easier and more intuitive to use, and moves it closer to the original intent of the Paperclip design.&lt;/p&gt;
&lt;p&gt;Code: &lt;a href="http://github.com/patshaughnessy/paperclip"&gt;http://github.com/patshaughnessy/paperclip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;New usage:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Install and use my version of the plugin:
    &lt;pre&gt;script/plugin install git://github.com/patshaughnessy/paperclip.git&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;In your model specify the &amp;quot;database&amp;quot; storage option; for example:
    &lt;pre&gt;has_attached_file :avatar, :storage =&amp;gt; :database&lt;/pre&gt;
    The file will be stored in a column called [attachment name]_file (e.g. &amp;quot;avatar_file&amp;quot;) by default. To specify a different BLOB column name, use :column, like this:
    &lt;pre&gt;has_attached_file :avatar,
                  :storage =&amp;gt; :database,
                  :column =&amp;gt; &amp;#x27;avatar_data&amp;#x27;&lt;/pre&gt;
    &lt;/li&gt;
  &lt;li&gt;If you have defined different styles, these files will be stored in additional columns called [attachment name]_[style name]_file (e.g. &amp;quot;avatar_thumb_file&amp;quot;) by default. To specify different column names for each style, use :column in the style definition, like this:&lt;/li&gt;
  &lt;pre&gt;has_attached_file :avatar,
                  :storage =&gt; :database,
                  :styles =&gt; { 
                    :medium =&gt; {
                      :geometry =&gt; "300x300&gt;",
                      :column =&gt; 'medium_file'
                    },
                    :thumb =&gt; {
                      :geometry =&gt; "100x100&gt;",
                      :column =&gt; 'thumb_file'
                    }
                  }&lt;/pre&gt;
  &lt;li&gt;You need to create these new columns in your migrations or you&amp;#x27;ll get an exception. Example:
    &lt;pre&gt;add_column :users, :avatar_file, :binary
add_column :users, :avatar_medium_file, :binary
add_column :users, :avatar_thumb_file, :binary&lt;/pre&gt;
    Note the migration for the &amp;quot;binary&amp;quot; column type will not work for LONGBLOBs in MySQL. Here&amp;#x27;s an example migration for MySQL:
    &lt;pre&gt;execute 'ALTER TABLE users ADD COLUMN avatar_file LONGBLOB'
execute 'ALTER TABLE users ADD COLUMN avatar_medium_file LONGBLOB'
execute 'ALTER TABLE users ADD COLUMN avatar_thumb_file LONGBLOB'&lt;/pre&gt;
    &lt;/li&gt;
  &lt;li&gt;
    To avoid performance problems loading all of the BLOB columns every time you access your ActiveRecord object, a class method is provided on your model called &amp;ldquo;select_without_file_columns_for.&amp;rdquo; This is set to a hash that will instruct ActiveRecord::Base.find to load all of the columns &amp;lt;u&gt;except&amp;lt;/u&gt; the BLOB/file data columns, for example:
&lt;pre&gt;{:select=&amp;gt;&amp;quot;id,name,avatar_file_name,avatar_content_type,...&amp;quot;}&lt;/pre&gt;
    If you&amp;rsquo;re using Rails 2.3, you can specify this as a default scope:
    &lt;pre&gt;default_scope select_without_file_columns_for(:avatar)&lt;/pre&gt;
    Or if you&amp;rsquo;re using Rails 2.1 or 2.2 you can use it to create a named scope:
    &lt;pre&gt;named_scope :without_file_data, select_without_file_columns_for(:avatar)&lt;/pre&gt;
    &lt;/li&gt;
  &lt;li&gt;By default, URLs will be set to this pattern:
    &lt;pre&gt;/:relative_root/:class/:attachment/:id?style=:style&lt;/pre&gt;
    Example:
    &lt;pre&gt;/app-root-url/users/avatars/23?style=original&lt;/pre&gt;
    The idea here is that to retrieve a file from the database storage, you will need some controller&amp;#x27;s code to be executed. Once you pick a controller to use for downloading, you can add this line to generate the download action for the default URL/action (the plural attachment name), &amp;quot;avatars&amp;quot; in this example:
      &lt;pre&gt;downloads_files_for :user, :avatar&lt;/pre&gt;
      Or you can write a download method manually if there are security, logging or other requirements. If you prefer a different URL for downloading files you can specify that in the model; e.g.:
      &lt;pre&gt;has_attached_file :avatar,
                  :storage =&amp;gt; :database,
                  :url =&amp;gt;&amp;#x27;/users/show_avatar/:id/:style&amp;#x27;&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;Add a route for the download to the controller which will handle downloads, if necessary. The default URL, /:relative_root/:class/:attachment/:id?style=:style, will be matched by the default route: :controller/:action/:id&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For now, I’ve overwritten my code from February. I believe this implementation is cleaner and easier to use; if anyone did download and use my code from February let me know and I can help you migrate the file data from the separate table back to columns in primary table. I will be writing a script to do this for my own application.&lt;/p&gt;
&lt;p&gt;When I have time in the next few days or weeks, I’ll post a sample application that illustrates all of these steps and shows exactly how to do all of this. If anyone has any questions or suggestions please let me know.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://patshaughnessy.net/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:patshaughnessy.net,2009-04-03:139</id>
    <published>2009-04-03T03:50:00Z</published>
    <updated>2009-04-03T03:50:00Z</updated>
    <category term="auto_complete" />
    <category term="Rails" />
    <category term="auto_complete" />
    <category term="rails" />
    <link href="http://patshaughnessy.net/2009/4/3/filtering-auto_complete-pick-lists-part-2-using-named-scopes" rel="alternate" type="text/html" />
    <title>Filtering auto_complete pick lists – part 2: using named scopes</title>
<content type="html">
            &lt;p&gt;I just updated my customized version of the auto_complete plugin to allow you to provide a named scope to auto_complete_for, in order to filter the auto_complete pick list options differently than the plugin does by default. The updated code is now on github:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://github.com/patshaughnessy/auto_complete"&gt;http://github.com/patshaughnessy/auto_complete&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is based on the ideas from &lt;a href="http://patshaughnessy.net/2009/3/14/filtering-auto_complete-pick-lists"&gt;my last post&lt;/a&gt;, &lt;a href="http://blog.andrewng.com/2008/09/08/autocomplete-with-multiple-related-form-fields-in-rails/"&gt;Andrew Ng&amp;rsquo;s original post&lt;/a&gt; and &lt;a href="http://www.alexrothenberg.com/2009/03/using-scopes-in-autocomplete-plugin.html"&gt;my friend Alex&amp;rsquo;s suggestion&lt;/a&gt; to use named scopes instead of manually modifying the find options. Here&amp;rsquo;s an example of how to use it taken from the &lt;a href="http://patshaughnessy.net/2009/1/30/sample-app-for-auto-complete-on-a-complex-form"&gt;auto_complete sample app I posted in January&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;
  &lt;ol&gt;
    &lt;li&gt;Add a named scope to your target model: For example suppose tasks belong to projects and have a named scope &amp;ldquo;by_project&amp;rdquo; which joins on the projects table and returns the tasks belonging to the project with the given name:&lt;pre&gt;class Task &amp;lt; ActiveRecord::Base
  belongs_to :project
  named_scope :by_project,
    lambda { |project_name| {
      :include =&amp;gt; :project,
      :conditions =&amp;gt; [ &amp;quot;projects.name = ?&amp;quot;, project_name ]
    } }
end&lt;/pre&gt;&lt;/li&gt;
    &lt;li&gt;In the controller, pass a block to auto_complete_for to specify that a named scope should be used to generate the competion options. Here the &amp;ldquo;by_project&amp;rdquo; named scope will be used to handle the task auto complete requests, using the &amp;ldquo;project&amp;rdquo; HTTP parameter:&lt;pre&gt;auto_complete_for :task, :name do | items, params |
  items.by_project(params[&amp;#x27;project&amp;#x27;])
end&lt;/pre&gt;&lt;/li&gt;
  &lt;li&gt;In the view, optionally specify additional parameters you might want to pass into your named scope: in my sample app I have a field called &amp;ldquo;project_name&amp;rdquo; elsewhere on my form:&lt;pre&gt;&amp;lt;% fields_for_task task do |f| -%&amp;gt;
  &amp;hellip;
  &amp;lt;%= f.text_field_with_auto_complete :task,
        :name,
        {},
        {
          :method =&amp;gt; :get,
          :with =&amp;gt;&amp;quot;value + &amp;#x27;&amp;amp;project=&amp;#x27; + $F(&amp;#x27;project_name&amp;#x27;)&amp;quot;
        } %&amp;gt;
  &amp;hellip;
  &amp;lt;% end -%&amp;gt;&lt;/pre&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/p&gt;
&lt;p&gt;So how does this work? Let&amp;rsquo;s take a look at my new implementation of auto_complete_for:&lt;/p&gt;
&lt;pre&gt;def auto_complete_for(object, method, options = {})
  define_method(&amp;quot;auto_complete_for_#{object}_#{method}&amp;quot;) do
    model = object.to_s.camelize.constantize
    find_options = { 
      :conditions =&amp;gt; [ &amp;quot;LOWER(#{model.quoted_table_name}.#{method}) LIKE ?&amp;quot;,
        &amp;#x27;%&amp;#x27; + params[object][method].downcase + &amp;#x27;%&amp;#x27; ], 
      :order =&amp;gt; &amp;quot;#{model.quoted_table_name}.#{method} ASC&amp;quot;,
      :limit =&amp;gt; 10 }.merge!(options)
    &lt;b&gt;@items = model.scoped(find_options)
    @items = yield(@items, params) if block_given?&lt;/b&gt;
    render :inline =&amp;gt; &amp;quot;&amp;lt;%= auto_complete_result @items, &amp;#x27;#{method}&amp;#x27; %&amp;gt;&amp;quot;
  end
end&lt;/pre&gt;
&lt;p&gt;One minor change I made here was to call &amp;ldquo;quoted_table_name&amp;rdquo; on the given model to specify the table name in the SQL generated to retrieve the auto complete results later. This was needed in case, like in &lt;a href="http://patshaughnessy.net/2009/1/30/sample-app-for-auto-complete-on-a-complex-form"&gt;my sample application&lt;/a&gt;, the controller specifies a named scope that joins with another table containing columns with the same name as the target model. If this isn&amp;rsquo;t the case, adding the table name to the SQL is harmless.&lt;/p&gt;
&lt;p&gt;However, the most important 2 lines here are in bold: first we call a function called &amp;ldquo;scoped&amp;rdquo; to create an anonymous named scope based on the default auto_complete options &amp;ldquo;find_options:&amp;rdquo;&lt;/p&gt;
&lt;pre&gt;@items = model.scoped(find_options)&lt;/pre&gt;
&lt;p&gt;The exciting thing about this line, which &lt;a href="http://www.alexrothenberg.com/2009/03/using-scopes-in-autocomplete-plugin.html"&gt;Alex explained in his blog post&lt;/a&gt;, is that the use of named scopes delays the corresponding SQL statement from being executed until later when we actually access the query results in auto_complete_result. What happens instead is that an ActiveRecord:: NamedScope::Scope object is created, containing a temporary cache of the find options.&lt;/p&gt;
&lt;p&gt;A good way to understand how this works is to try it in the Rails console:&lt;/p&gt;
&lt;pre&gt;complex-form-examples pat$ ./script/console 
Loading development environment (Rails 2.1.0)
&amp;gt;&amp;gt; find_options = { 
?&amp;gt;   :conditions =&amp;gt; [ &amp;quot;LOWER(`tasks`.name) LIKE ?&amp;quot;, &amp;#x27;%t%&amp;#x27; ], 
?&amp;gt;   :order =&amp;gt; &amp;quot;`tasks`.name ASC&amp;quot;,
?&amp;gt;   :limit =&amp;gt; 10 }
=&amp;gt; {:order=&amp;gt;&amp;quot;name ASC&amp;quot;, :conditions=&amp;gt;[&amp;quot;LOWER(name) LIKE ?&amp;quot;, &amp;quot;%t%&amp;quot;], :limit=&amp;gt;10}
&amp;gt;&amp;gt; Task.scoped(find_options)
=&amp;gt; [#&amp;lt;Task id: 4, project_id: 2, name: &amp;quot;Task 2a&amp;quot;, due_at: nil, created_at: &amp;quot;2009-04-02 16:21:54&amp;quot;,
updated_at: &amp;quot;2009-04-02 16:21:54&amp;quot;&amp;gt;, #&amp;lt;Task id: 5, project_id: 2, name: &amp;quot;Task 2b&amp;quot;, due_at: nil,
created_at: &amp;quot;2009-04-02 16:21:54&amp;quot;, updated_at: &amp;quot;2009-04-02 16:21:54&amp;quot;&amp;gt;, #&amp;lt;Task id: 6, project_id: 2,
name: &amp;quot;Task 2c&amp;quot;, due_at: nil, created_at: &amp;quot;2009-04-02 16:21:54&amp;quot;, updated_at: &amp;quot;2009-04-02
16:21:54&amp;quot;&amp;gt;, #&amp;lt;Task id: 1, project_id: 1, name: &amp;quot;Task One&amp;quot;, due_at: nil, created_at: &amp;quot;2009-04-02
16:21:30&amp;quot;, updated_at: &amp;quot;2009-04-02 16:21:30&amp;quot;&amp;gt;, #&amp;lt;Task id: 3, project_id: 1, name: &amp;quot;Task
Three&amp;quot;, due_at: nil, created_at: &amp;quot;2009-04-02 16:21:30&amp;quot;, updated_at: &amp;quot;2009-04-02 16:21:30&amp;quot;&amp;gt;,
#&amp;lt;Task id: 2, project_id: 1, name: &amp;quot;Task Two&amp;quot;, due_at: nil, created_at: &amp;quot;2009-04-02 16:21:30&amp;quot;,
updated_at: &amp;quot;2009-04-02 16:21:30&amp;quot;&amp;gt;]&lt;/pre&gt;
&lt;p&gt;Wait a minute! I thought the actual SQL execution was delayed by named scopes until I needed to access the results? Here the console has already displayed the query results, so the SQL statement must have been executed already. How and why did this happen? In this case, when you enter an expression into the Rails console and press ENTER, the expression is evaluated and then the &amp;ldquo;inspect&amp;rdquo; method is called on it. The problem is that the named scopes implementation has delegated the &amp;ldquo;inspect&amp;rdquo; method to another method, which executes the SQL statement and loads the query results.&lt;/p&gt;
&lt;p&gt;We can use a trick in the console to open the ActiveRecord::NamedScope::Scope class and override the inspect method so the SQL is not executed, and prove to ourselves that &amp;ldquo;scoped()&amp;rdquo; actually does return a named scope object without executing the SQL statement:&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt; module ActiveRecord
&amp;gt;&amp;gt; module NamedScope
&amp;gt;&amp;gt; class Scope
&amp;gt;&amp;gt; def inspect
&amp;gt;&amp;gt;   super # Avoids calling ActiveRecord::Base.find and calls Object.inspect
&amp;gt;&amp;gt; end
&amp;gt;&amp;gt; end
&amp;gt;&amp;gt; end
&amp;gt;&amp;gt; end
=&amp;gt; nil
&amp;gt;&amp;gt; Task.scoped(find_options)
=&amp;gt; #&amp;lt;ActiveRecord::NamedScope::Scope:0x21e65d4
      @proxy_options={:conditions=&amp;gt;[&amp;quot;LOWER(`tasks`.name) LIKE ?&amp;quot;, &amp;quot;%t%&amp;quot;],
          :order=&amp;gt;&amp;quot;`tasks`.name ASC&amp;quot;, :limit=&amp;gt;10},
      @proxy_scope=Task(id: integer, project_id: integer, name: string,
          due_at: datetime, created_at: datetime, updated_at: datetime)&amp;gt;&lt;/pre&gt;
&lt;p&gt;So here we can see that &amp;ldquo;scoped&amp;rdquo; returns an ActiveRecord::NamedScope::Scope object, and that it has two interesting instance variables: proxy_scope and proxy_options. The first of these, proxy_options, contains the find options that were passed into the scoped() function, or into the &amp;ldquo;named_scope&amp;rdquo; declaration in your model. The second value, proxy_scope, indicates the parent scope or context in which this named scope object&amp;rsquo;s SQL statement should be run. In this example, that is the Task model itself. The named scope object is essentially a cache of the query options that will be user later when the query is executed.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see how this works in the auto_complete plugin. Back again to the new implementation of auto_complete_for, we have:&lt;/p&gt;
&lt;pre&gt;@items = model.scoped(find_options)
@items = yield(@items, params) if block_given?&lt;/pre&gt;
&lt;p&gt;The first line generates a ActiveRecord::NamedScope::Scope object, which is then passed into the block provided by the controller code, if any. Let&amp;rsquo;s take a look at my sample app&amp;rsquo;s implementation of the controller:&lt;/p&gt;
&lt;pre&gt;auto_complete_for :task, :name do | items, params |
  items.by_project(params[&amp;#x27;project&amp;#x27;])
end&lt;/pre&gt;
&lt;p&gt;This is a good example of the second very cool feature of named scopes: that they are composable&amp;hellip; in other words, that two or more named scopes can be combined together to form a single SQL statement that is executed only once! Let&amp;rsquo;s return to the same Rails console session with our redefined &amp;ldquo;inspect&amp;rdquo; method and see if we can understand a bit more about this:&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt; Task.scoped(find_options).by_project &amp;#x27;Project One&amp;#x27;
=&amp;gt; #&amp;lt;ActiveRecord::NamedScope::Scope:0x21d1864
  @proxy_options={
    :conditions=&amp;gt;[&amp;quot;projects.name = ?&amp;quot;, &amp;quot;Project One&amp;quot;],
    :include=&amp;gt;:project},
  @proxy_scope=
    #&amp;lt;ActiveRecord::NamedScope::Scope:0x21d1a30
      @proxy_options={
        :conditions=&amp;gt;[&amp;quot;LOWER(`tasks`.name) LIKE ?&amp;quot;, &amp;quot;%t%&amp;quot;],
        :order=&amp;gt;&amp;quot;`tasks`.name ASC&amp;quot;,
        :limit=&amp;gt;10},
      @proxy_scope=Task(id: integer, project_id: integer, name: string, due_at: datetime, created_at: datetime, updated_at: datetime)
    &amp;gt;
  &amp;gt;&lt;/pre&gt;
&lt;p&gt;Now we can see that calling scoped(find_options).by_project just returns a chain of two named scopes: the first scope object with @proxy_scope set to the second one, and the second one with @proxy_scope set to the base model class. Later when this SQL query is executed, the code in NamedScope and ActiveRecord::Base will simply walk this chain of objects, accumulate the options into a single hash, convert the hash to SQL and execute it.&lt;/p&gt;
&lt;p&gt;In auto_complete_for after the controller&amp;rsquo;s block returns, the &amp;ldquo;@items&amp;rdquo; value in auto_complete_for above is set to the parent/child named scope chain of objects, and then passed into auto_complete_result:&lt;/p&gt;
&lt;pre&gt;render :inline =&amp;gt; &amp;quot;&amp;lt;%= auto_complete_result @items, &amp;#x27;#{method}&amp;#x27; %&amp;gt;&amp;quot;&lt;/pre&gt;
&lt;p&gt;Inside of auto_complete_result the @items value is used as if it were an array&amp;hellip; like this:&lt;/p&gt;
&lt;pre&gt;def auto_complete_result(entries, field, phrase = nil)
  return unless entries
  items = entries.map { |entry|
    content_tag(&amp;quot;li&amp;quot;,
                phrase ? highlight(entry[field], phrase) : h(entry[field]))
  }
  content_tag(&amp;quot;ul&amp;quot;, items.uniq)
end&lt;/pre&gt;
&lt;p&gt;&amp;hellip; to generate the HTML needed for the Prototype library&amp;rsquo;s implementation of the auto complete drop down box. The interesting thing here is that the SQL statement is executed as soon as the call to &amp;ldquo;map&amp;rdquo; is executed, accessing the elements of the &amp;ldquo;@items&amp;rdquo; array. This works because the ActiveRecord::NamedScope::Scope class redirects or delegates the [] and other array methods to ActiveRecord::Base.find. Here's the single SQL that is executed with the combined, accumulated query options:&lt;/p&gt;
&lt;pre&gt;SELECT `tasks`.`id` AS t0_r0, `tasks`.`project_id` AS t0_r1,
  `tasks`.`name` AS t0_r2, `tasks`.`due_at` AS t0_r3,
  `tasks`.`created_at` AS t0_r4, `tasks`.`updated_at` AS t0_r5,
  `projects`.`id` AS t1_r0, `projects`.`name` AS t1_r1,
  `projects`.`created_at` AS t1_r2, `projects`.`updated_at` AS t1_r3
FROM `tasks`
LEFT OUTER JOIN `projects` ON `projects`.id = `tasks`.project_id
WHERE ((projects.name = 'Project One') AND
  (LOWER(`tasks`.name) LIKE '%t%'))
ORDER BY `tasks`.name ASC LIMIT 10&lt;/pre&gt;
&lt;p&gt;In fact, in the original version of the auto_complete plugin before my changes to it for named scopes, the value passed into auto_complete_result &lt;i&gt;was&lt;/i&gt; a simple array. The fact that named scopes are used now is entirely hidden from this code!&lt;/p&gt;
&lt;p&gt;One last note here about named scope: as described in a comment in named_scope.rb from the Rails source code, the &amp;ldquo;proxy_options&amp;rdquo; method provides a convenient way to test the behavior of named scopes without actually checking the results of an actual SQL query. Here&amp;rsquo;s one of the tests I wrote for my new version of auto_complete_for:&lt;/p&gt;
&lt;pre&gt;def test_default_auto_complete_for
  get :auto_complete_for_some_model_some_field,
      :some_model =&amp;gt; { :some_field =&amp;gt; &amp;quot;some_value&amp;quot; }
  default_auto_complete_find_options = @controller.items.proxy_options
  assert_equal &amp;quot;`some_models`.some_field ASC&amp;quot;, 
               default_auto_complete_find_options[:order]
  assert_equal 10, default_auto_complete_find_options[:limit]
  assert_equal [&amp;quot;LOWER(`some_models`.some_field) LIKE ?&amp;quot;, &amp;quot;%some_value%&amp;quot;],
               default_auto_complete_find_options[:conditions]
end&lt;/pre&gt;
&lt;p&gt;Since I didn&amp;rsquo;t want to go to the trouble of setting up an actual in-memory database using SQLite, or to introduce mocha or some other mocking framework to the auto_complete tests, all I had to do was just call @controller.items.proxy_options and check that the find options are as expected. (I also had to expose &amp;ldquo;items&amp;rdquo; in the mock controller using attr_reader.) I have another test that checks that the controller&amp;rsquo;s block is called and it&amp;rsquo;s named scope options are present as expected&amp;hellip; this test uses the proxy_scope method to walk up the chain to the parent named scope and get it&amp;rsquo;s proxy_options. See &lt;a href="http://github.com/patshaughnessy/auto_complete/blob/f2703895ab7ae0748152557c3e5738a4e83ca9ee/test/auto_complete_test.rb"&gt;auto_complete_test.rb&lt;/a&gt; for details.&lt;/p&gt;
          </content>  </entry>
</feed>
