5.3. When Should You Use Scaffolding?

You should never use scaffolding just for the sake of it. There are Rails developers who never use scaffolding and always build everything manually. I find scaffolding quite useful for quickly getting into a new project. But it is always just the beginning.

Example for a Minimal Project

Let's assume we need a web page quickly with which we can list products and represent them individually. But we do not require an editing or deleting function. In that case, a large part of the code created via scaffold would be useless and have to be deleted. Let's try it out as follows:
$ rails new read-only-shop
  [...]
$ cd read-only-shop 
$ rails generate scaffold product name 'price:decimal{7,2}' 
      invoke  active_record
      create    db/migrate/20130716202340_create_products.rb
      create    app/models/product.rb
      invoke    test_unit
      create      test/models/product_test.rb
      create      test/fixtures/products.yml
      invoke  resource_route
       route    resources :products
      invoke  scaffold_controller
      create    app/controllers/products_controller.rb
      invoke    erb
      create      app/views/products
      create      app/views/products/index.html.erb
      create      app/views/products/edit.html.erb
      create      app/views/products/show.html.erb
      create      app/views/products/new.html.erb
      create      app/views/products/_form.html.erb
      invoke    test_unit
      create      test/controllers/products_controller_test.rb
      invoke    helper
      create      app/helpers/products_helper.rb
      invoke      test_unit
      create        test/helpers/products_helper_test.rb
      invoke    jbuilder
      create      app/views/products/index.json.jbuilder
      create      app/views/products/show.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/products.js.coffee
      invoke    scss
      create      app/assets/stylesheets/products.css.scss
      invoke  scss
   identical    app/assets/stylesheets/scaffolds.css.scss
$ rake db:migrate
  [...]
$
Now create the db/seeds.rb with some demo products:
Product.create(name: 'Apple', price: 1)
Product.create(name: 'Orange', price: 1)
Product.create(name: 'Pineapple', price: 2.4)
Product.create(name: 'Marble cake', price: 3)
And populate it with this data:
$ rake db:seed
$
As we only need index and show, we should delete the not required views:
$ rm app/views/products/_form.html.erb 
$ rm app/views/products/new.html.erb 
$ rm app/views/products/edit.html.erb 
$ 
The json.jbuilder views are not needed either:
$ rm app/views/products/*.json.jbuilder
$
The file app/controllers/products_controller.rb can be simplified with an editor. It should look like this:
class ProductsController < ApplicationController
  # GET /products
  def index
    @products = Product.all
  end

  # GET /products/1
  def show
    @product = Product.find(params[:id])
  end
end
We only need the routes for index and show. Please open the file config/routes.rb and edit it as follows:
ReadOnlyShop::Application.routes.draw do
  resources :products, only: [:index, :show]
end 
A rake routes shows us that really only index and show are routed now:
$ rake routes
  Prefix Verb URI Pattern             Controller#Action
products GET /products(.:format)     products#index
 product GET /products/:id(.:format) products#show
$ 
If we now start the server rails server and go to the URL http://0.0.0.0:3000/products, we get an error message.
Error message
The same message will be displayed in the log:
$ rails server
=> Booting WEBrick
=> Rails 4.0.0 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
[2013-07-16 22:29:42] INFO  WEBrick 1.3.1
[2013-07-16 22:29:42] INFO  ruby 2.0.0 (2013-06-27) [x86_64-darwin12.4.0]
[2013-07-16 22:29:42] INFO  WEBrick::HTTPServer#start: pid=10182 port=3000


Started GET "/products" for 127.0.0.1 at 2013-07-16 22:29:47 +0200
  ActiveRecord::SchemaMigration Load (0.1ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by ProductsController#index as HTML
  Product Load (0.1ms)  SELECT "products".* FROM "products"
  Rendered products/index.html.erb within layouts/application (21.7ms)
Completed 500 Internal Server Error in 61ms

ActionView::Template::Error (undefined method `edit_product_path' for #<#<Class:0x007f94e6baab08>:0x007f94e6ba9ed8>):
    17:         <td><%= product.name %></td>
    18:         <td><%= product.price %></td>
    19:         <td><%= link_to 'Show', product %></td>
    20:         <td><%= link_to 'Edit', edit_product_path(product) %></td>
    21:         <td><%= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' } %></td>
    22:       </tr>
    23:     <% end %>
  app/views/products/index.html.erb:20:in `block in _app_views_products_index_html_erb__535216393559089744_70138729102480'
  app/views/products/index.html.erb:15:in `_app_views_products_index_html_erb__535216393559089744_70138729102480'

[...]
The error message states that we call an undefined method edit_product_path in the view app/views/products/index.html.erb. As we only route index and show now, there are no more edit, destroy or new methods any more. So we need to adapt the file app/views/products/index.html.erb in the editor as follows:
<h1>Listing products</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Price</th>
      <th></th>
    </tr>
  </thead>

  <tbody>
    <% @products.each do |product| %>
      <tr>
        <td><%= product.name %></td>
        <td><%= product.price %></td>
        <td><%= link_to 'Show', product %></td>
      </tr>
    <% end %>
  </tbody>
</table>
And while we are at it, we also edit the app/views/products/show.html.erb accordingly:
<p>
  <strong>Name:</strong>
  <%= @product.name %>
</p>

<p>
  <strong>Price:</strong>
  <%= @product.price %>
</p>

<%= link_to 'Back', products_path %>
Now our application is finished. Start the Rails server with rails server and open the URL http://0.0.0.0:3000/products in the browser.
Index View

Buy the new Rails 5.1 version of this book.

In this example, I am not commenting on the required changes in the tests, as this is not an exercise for test driven development but meant to demonstrate a way of working with scaffolding. TDD developers will quickly be able to adapt the tests.

Conclusion

Have a go and try it out. Try working with scaffolds one time and without them the next. Then you will soon get a feel for whether it fits into your working method or not. I find that scaffolding makes my work much easier for standard applications.

Thank you for your support and the visibility by linking to this website on Twitter and Facebook. That helps a lot!