Scaffolding

While you’re developing Rails applications, especially those which are mainly providing you with a simple interface to data in a database, it can often be useful to use the scaffold method.

Scaffolding provides more than cheap demo thrills. Here are some benefits −

  • You can quickly get code in front of your users for feedback.
  • You are motivated by faster success.
  • You can learn how Rails works by looking at the generated code.
  • You can use scaffolding as a foundation to jump start your development.

To understand scaffolding, let’s start by creating a new Rails application named cookbook. It will have database called cookbook and a table called recipes.

Creating an Empty Rails Web Application

Open a command window and navigate to where you want to create this cookbook web application and run the following command to create a complete project structure.

rails new cookbook

Rails uses SQLite as the default database. To specify other database type, use -d option. For example, the following command creates a Rail application with mysql as its backend database.

rails new cookbook -d mysql

Rails supports PostgreSql, Oracle, SQL Server and Maria DB databases also.

By default, Rails includes importmaps for JavaScript, but you can choose a different frontend framework such as Webpack, Tailwind CSS, Bootstrap or ESBuild.

If you are using RubyMine IDE, the new project wizard lets you choose the database and the frontend framework.

Creating an Empty Rails Web Application

Rails generates database.yml configuration file inside the config/ directory. It has the configuration for development as well as production environment.

default:&default
  adapter: sqlite3
  pool:<%=ENV.fetch("RAILS_MAX_THREADS"){5}%>
  timeout:5000

development:<<:*default
  database: storage/cookbook.sqlite3

test:<<:*default
  database: storage/test.sqlite3
production:
  primary:<<:*default
database: storage/cookbook.sqlite3
cache:<<:*default
database: storage/production_cache.sqlite3
migrations_paths: db/cache_migrate
queue:<<:*default
database: storage/production_queue.sqlite3
migrations_paths: db/queue_migrate
cable:<<:*default
database: storage/production_cable.sqlite3
migrations_paths: db/cable_migrate

If you specify -d option with mysql as the database, database.yml file must contain the database credentials.

development:
   adapter: mysql
   database: cookbook
   username: root
   password:[password]
   host: localhost
	
test:
   adapter: mysql
   database: cookbook
   username: root
   password:[password]
   host: localhost
	
production:
   adapter: mysql
   database: cookbook
   username: root
   password:[password]
   host: localhost

If you prefer to use MySQL or PostgreSQL, you will need to run the command:

rails db:create

Generated Scaffold Code

With the scaffold action, Rails generates all the code it needs dynamically. By running scaffold as a script, we can get all the code written to disk, where we can investigate it and then start tailoring it to our requirements.

Run the scaffold generator to create a Recipe model with title (string) and instructions (text):

rails g scaffold Recipe tittle:string instructions:text

The command prompt terminal (terminal in Ubuntu) shows the following log as different files are created:

Generated Scaffold Code

This command creates:

  • Model: app/models/recipe.rb
  • Migration: db/migrate/ rb
  • Controller: app/controllers/recipes_controller.rb
  • Views: app/views/recipes/
  • Routes: Updates config/routes.rb

Run the Migration

You can use Rails Migrations to create and maintain tables. Apply the migration to create the recipes table in MySQL:

rake db:migrateRAILS_ENV=development

The command terminal shows the following log:

rake db:migrateRAILS_ENV=development
==20250220120618CreateRecipes: migrating ====================================-- create_table(:recipes)->0.0026s
==20250220120618CreateRecipes: migrated (0.0035s)===========================

This will create the recipes table with the following structure:

CREATETABLE recipes (
id           INTEGERPRIMARYKEY AUTOINCREMENT
                          NOTNULL,
tittle       VARCHAR,
instructions TEXT,
created_at   DATETIME(6)NOTNULL,
updated_at   DATETIME(6)NOTNULL);</pre>

The Controller

Let's look at the code behind the controller. This code is generated by the scaffold generator. If you open app/controllers/recipes_controller.rb, then you will find something as follows

classRecipesController<ApplicationController
  before_action :set_recipe, only:%i[ show edit update destroy ]# GET /recipes or /recipes.jsondefindex@recipes=Recipe.all
  end# GET /recipes/1 or /recipes/1.jsondefshowend# GET /recipes/newdefnew@recipe=Recipe.newend# GET /recipes/1/editdefeditend# POST /recipes or /recipes.jsondefcreate@recipe=Recipe.new(recipe_params)

respond_to do|format|[email protected]
    format.html { redirect_to @recipe, notice:"Recipe was successfully created."}
    format.json { render :show, status::created, location:@recipe}else
    format.html { render :new, status::unprocessable_entity}
    format.json { render json:@recipe.errors, status::unprocessable_entity}endendend# PATCH/PUT /recipes/1 or /recipes/1.jsondefupdate
respond_to do|format|[email protected](recipe_params)
    format.html { redirect_to @recipe, notice:"Recipe was successfully updated."}
    format.json { render :show, status::ok, location:@recipe}else
    format.html { render :edit, status::unprocessable_entity}
    format.json { render json:@recipe.errors, status::unprocessable_entity}endendend# DELETE /recipes/1 or /recipes/[email protected]!
respond_to do|format|
  format.html { redirect_to recipes_path, status::see_other, notice:"Recipe was successfully destroyed."}
  format.json { head :no_content}endendprivate# Use callbacks to share common setup or constraints between actions.defset_recipe@recipe=Recipe.find(params.expect(:id))end# Only allow a list of trusted parameters through.defrecipe_params
  params.expect(recipe:[:tittle,:instructions])endend</pre>

When the user of a Rails application selects an action, e.g. "Show" - the controller will execute any code in the appropriate section - "def show" - and then by default will render a template of the same name - "show.html.erb". This default behavior can be overwritten.

The controller uses ActiveRecord methods such as find, find_all, new, save, update_attributes, and destroy to move data to and from the database tables. Note that you do not have to write any SQL statements, rails will take care of it automatically.

This single line of code will bring the database table to life. It will provide with a simple interface to your data, and ways of −

  • Creating new entries
  • Editing current entries
  • Viewing current entries
  • Destroying current entries

When creating or editing an entry, scaffold will do all the hard work like form generation and handling for you, and will even provide clever form generation, supporting the following types of inputs −

  • Simple text strings
  • Text areas (or large blocks of text)
  • Date selectors
  • Date-time selectors

Now, go to the cookbook directory and run the Web Server using the following command −

rails server

Now, open a browser and navigate to http://127.0.0.1:3000/recipes/new. This will provide you a screen to create new entries in the recipes table. A screenshot is shown below

The Controller

Once you press the Create button to create a new recipe, your record is added into the recipes table and it shows the following result

The Controller 1

You can see the option to edit, show, and destroy the records. So, play around with these options.

The Controller 2

Enhancing the Model

Rails gives you a lot of error handling for free. To understand this, add some validation rules to the empty recipe model −

Modify app/models/recipe.rb as follows and then test your application −

classRecipe<ActiveRecord::Base
   validates_length_of :title,:within=>1..20
   validates_uniqueness_of :title,:message=>"already exists"end

These entries will give automatic checking.

  • validates_length_of − the field is not blank and not too long.
  • validates_uniqueness_of − duplicate values are trapped. Instead of the default Rails error message, we have given a custom message here.

The Views

All the views and corresponding all the controller methods are created by scaffold command and they are available in the app/views/recipes directory.

How Scaffolding is Different?

Although we can manually create the methods to list, show, delete and create data etc., but scaffolding does that job automatically.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *