Intro to Rails

Rails Logo

Lesson Objectives

After this lesson, students will be able to:

  • Initialize a Rails project using the --api flag
  • Use a postgresql db with Rails
  • Run a migration to create a table
  • Run migrations to create and rename columns
  • Make models and query them with ActiveRecord



What is Rails?

Rails is a server-side web application framework written in Ruby.




Rails Features:

  • Open Source - free to use, anyone can contribute
  • Vast collection of open source code available within Rails community
  • MVC framework (Model View Controller)
  • RESTful application design
  • Built-in ORM (Object Relational Mapping - programming technique for converting data between incompatible type systems using OOP.

    • Example: converting data that is in rows/columns/tables into JSON)
    • Called Active Record, based on Active Record Pattern
  • Encourages Agile web development
  • Strong focus on testing, and utilizing testing for documentation

Rails is a server environment just like Node. The big difference is that Rails favors convention over configuration.

Rails can get things up and running quickly and effectively -- as long as you do it exactly the way Rails tell you to. For example:

  • Rails wants you to name your models and controllers a certain way, otherwise it won't work.
  • Rails requires you to run a small program called a migration in order to change any database fields.

Node, by comparison is a blank slate where all things are possible. The tradeoff, with Rails, is ease-of-use for large-scale applications. Whether this is a straightjacket or a wonderful gift is up to you as a developer.




Rails Philosophies:

  • DRY (Don't Repeat Yourself)
  • Convention over Configuration

We've seen a lot of similar things in our previous units. That's because the emergence of Rails and its popularity influenced web development as a whole, and many new frameworks continue to use many of the successful patterns and features that Rails developed.

Something we haven't seen yet is a new philosophy called Convention over Configuration.

  • Express is a minimalist framework, where you add in each piece of functionality that you need. Therefore you must also configure everything. There are some recommended patterns, but you can really build the app any way you want.
  • Rails provides you with tons of functionality. However, in order to utilize this right-out-of-the-box functionality you must follow all of the Rails conventions.

    • This means proper pluralization and capitalization will make or break your app (literally)



Express vs. Rails in our course

Comparison Express Rails Comments
Language JavaScript Ruby Still need JS on the front end
Database MongoDB Postgres MongoDB is considered NoSQL, while Postgres is SQL
ODM/ORM Mongoose Active Record Active Record will convert our SQL into JSON
Third Party Code NPM Gem/ bundler/ bundler install Gems are installed globally by default, npm packages are installed locally by default
server-side rendering EJS or Handlebars erb We'll be skipping right into rendering our views with React
run the server nodemon rails s You'll see something called puma running in terminal



How we will be using Rails




Rails 5 / 6 API

Our Rails server will have the same purpose as our Node/Express server from Unit 3. It's going to serve only JSON.

Rails JSON APIs are used as powerful backends for Mobile apps and regular Desktop apps.

Rails 5:

verify that you're running Rails 5 or higher with the command: rails -v

New in Rails 5 is the --api flag that we will be using.

This flag slims Rails down considerably, removing files, folders, and middleware, etc. that is not needed. The --api flag makes Rails much more lightweight.




Build a new Rails App

To start a new rails app, you do not have to make a directory.

We are going to build an app called




intro_app_api

The command to build our rails json api with postgres is the following:

rails new intro_app_api --api -d postgresql --skip-git

In English:

Hey rails make a new project called intro_app_api as just an --api (as opposed to full Rails, because we'll be rendering our views with React later), set the database -d to postgresql, and do not initialize this project with gitxe

What's all this stuff, one more time?

  • rails new will make a new project directory and populate it with folders and files
  • The name of our app is intro_app_api. It's important to name it with _api to differentiate it from other apps later.
  • The --api flag is new in Rails 5 and slims down the app just to serve json.
  • With the -d flag we specify which type of database to use. In our case, we use postgresql.
  • --skip-git skips Rails automatically running a git init in this new folder, in most situations outside this classroom, you don't need this however.

You can learn more about the rails new command by running:

rails new --help

πŸ’₯πŸ’₯ Made a mistake typing rails new?

Just remove the folder that was created and re-run the command. It is far faster to do that than go into the config files and update stuffπŸ’₯πŸ’₯




Terminal feedback will look something like this:

screenshot



Files and Folders

Now let's open up our new app in our text editor:

cd intro_app_api

code .

screenshot

There are many files and folders that Rails makes for us. This is in stark contrast to Express that give us . . . a package.json.

Comparison Express Rails Comments
project meta-data package.json Gemfile Rails 5+ has a package.json by default as well, but that's for extra stuff, not the main meta-data file
Server Express Puma/Rack Puma is the server, Rack deals with the middleware, these are configured and arranged pretty differently from Express, so you won't see a server file in the root
Controllers controllers app/controllers part of MVC
Models models app/models part of MVC
Views we used ejs (handlebars is another common one), but we also used React erb, BUT! We won't use it, when we're ready we'll jump into using React part of MVC

We don't need to look inside these nooks and crannies. The idea is that Rails will do a bunch of stuff for us inside of these 'black boxes'. This is in contrast to Express where we see everything, including all the middleware config.

Rails gives you all this stuff and you just have to play along with it.

Almost everything you will ever do will be in the app folder.

You'll also do a bit in the db folder, in the config folder, and the Gemfile.




For today we're focused only on two directories: app/models and db

Here's what we are going to do today:

  • Step One: make a database with table and columns
  • Step Two: make a model and interact with it

This is all we will do. There are very specific processes for doing these things. Once these foundations are built, we can begin to free ourselves up a bit.




Step One - Creating a Database with a Table and Columns




CREATE DATABASE

rails db:create creates your postgres database based on the name of your Rails app.

screenshot

screenshot

We can check that the database was created by typing

rails dbconsole

This will open up our postgres CLI.

Close it again with \q.




Create Columns for the Database




Migrations

We create our database tables and give them columns through Migrations.

In Mongo, our table was a collection. Its 'columns' were the keys we used in our schema.

In SQL, this is a table that has columns.

In this application, we are going to make yet another ToDos thingy with very simple data.

Open the db folder. We are going to make some changes to it. For the most part we will not interact with it directly, but rather will do so by generating and running migrations.

Migrations are a convenient way for you to alter your database in a structured and organized manner.

Migrations, using Ruby, are database-language independent.

First, create a migration in Terminal. This migration will allow us to make a table in our database:

rails generate migration CreateTodos

=> CREATED db/migrate/20191010152405_create_todos.rb

generate can be shortened to g

Create is a helper that will set up boilerplate for creating a table

  • The migration generated a migrate folder in the db folder.
  • Inside it is the migration file we created: db/migrate/20191010152405_create_todos.rb
  • The migration file we just made will allow us to create a table with the columns we want.

The numbers are just a timestamp. All migration files are kept here in sequence so that we have a permanent record of all alterations to our database.

Why do we use migrations?




Give the Migration Some Data

In the migration file: Use Ruby to specify what the columns and datatypes are for our table:

class CreateTodos < ActiveRecord::Migration[6.0]
  def change
     create_table :todos do |t|
        t.string :title
        t.boolean :completed
     end
  end
end

Note: The column names are symbols

screenshot




Run the migration

We have created the migration, and we have told it what we want it to do. All that's left is to execute it.

When we run the migration it will create/alter our database.

Run the migration with rails db:migrate.

== 20190710152405 CreateTodosTable: migrating ===============================
== 20190710152405 CreateTodosTable: migrated (0.0000s) ======================

screenshot




schema.rb

Running the migration created a schema.rb file. This is the schema for all your data.

screenshot




Do not touch schema.rb

Not to be touched. DO NOT MODIFY IT

Same goes for your migrations. Once you've run a migration DO NOT TOUCH IT.




Check the database itself:

Open up the Postgres console:

$ rails dbconsole

See the columns created for the todos table:

SELECT * FROM todos;

screenshot

Quit with \q.

Now that our database has been constructed with tables and columns, we'll need to get some data in there.

However, first we'll let you practice these first steps




Step 1 complete: Making a database with a table and columns



Blog App




Activity (20 mins)

In a seperate location (NOT inside your Rails project folder), perform the following commands, and look back over the lesson to double-check that you are writing the correct syntax. If you get it wrong, you'll probably have to delete the app and start over.

  • Make a new Rails app called blog_app_api.
  • Remember the --api flag. If you forget, delete this app and start over.
  • Remember the -d postgresql. If you forget, delete this app and start over.
  • cd blog_app_api
  • Create the db with rails db:create
  • Generate a migration for creating a table called posts. rails g migration CreatePosts.
  • In the migration file, set up the posts table to have columns for title, author, and content (all strings).
  • Run the migration.
  • Check the schema, and check the database:

schema.rb correct result:

screenshot

In rails dbconsole

SELECT * FROM posts;

Correct result:

screenshot




Step Two - Creating a Model and Interating with it




Create Model

Navigate back to our intro_app_api where we are making the Todos:

In order to perform database queries using Ruby, we need to create a Todo model in app/models

Make a file called todo.rb in app/models.

todo.rb MUST BE LOWERCASE AND SINGULAR. Rails wants to help you with its conventions.

In the file, tell our model to inherit from ApplicationRecord:

Todo, the class name, MUST BE CAPITALIZED AND SINGULAR. Keep it conventional. A rule of thumb is that model names are singular, but controllers are plural.

class Todo < ApplicationRecord
end

screenshot

All this does for now is wire up our app so that we use Active Record on our Todo model to interface with our database.




Active Record

Active Record, as an ORM Framework, gives us several mechanisms, the most important being the ability to:

  • Represent models and their data
  • Represent associations between these models
  • Represent inheritance hierarchies through related models
  • Validate models before they are saved into the database
  • Perform database operations in an object-oriented fashion

Active Record is the M in MVC - the model - which is the layer of the system responsible for representing business data and logic.

It's like Mongoose. With Mongoose, we did not have to write raw Mongo queries, and instead could use Mongoose's helper methods. With ActiveRecord, we do not have to write raw SQL queries, and can instead write Ruby to query the database.

TLDR: ActiveRecord is to SQL as Mongoose is to Mongo.

In addition, we can open up a console and just write ActiveRecord queries directly (we couldn't do this with Mongoose).




Rails console

Open Rails console

rails console

OR

rails c

screenshot

  • We can see that our Todos model exists and that we can perform ActiveRecord queries on it, and we can see the SQL statement used to query the database:
Todo.all

screenshot

There are no Todos yet, but the query works!

Todo.count

screenshot

Yup, zero todos.




Create and Save new Todos

  • .new (creates a new ActiveRecord object template, but doesn't save it to the DB)
  • .save (saves a new ActiveRecord object template to the database)
  • .create (calls .new + .save)
todo = Todo.new(title: "First todo", completed: true)
todo.save
Todo.create(title: "Something", completed: false)

screenshot




Query Todos

  • .find (finds by id)
Todo.find(1)

screenshot

  • .where (takes a key value pairs as arguments to search by)
Todo.where(title: "Something", completed: false)

screenshot




Update Todos

  • .update (takes key value pairs as arguments, with the fields to update)
todo = Todo.find(2)
todo.update(completed: true)

screenshot

Or chain the commands together:

Todo.find(2).update(completed: true)



Delete Todos

  • .destroy can either be called on an ActiveRecord object or takes the id of an ActiveRecord object
Todo.destroy(1)

screenshot

OR

Todo.find(1).destroy

We will be using these Active Record queries within Rails.




Activity (10 mins)

Using rails console rails c:

  1. Create a new Todo
  2. Query Todo to see how many there are in the db
  3. Create another Todo
  4. Update the second Todo
  5. Query Todo to see all of them
  6. Delete the first Todo

Type exit to leave Rails Console




Step Two complete: Creating a model and interacting with it




Aside

Rails has conventions on how to pluralize and singularize words.

If you would like to check the singular or plural of a word, you can do it by opening rails c and running .pluralize (to quit, type quit).

rails c pluralize, singularize




Review

  1. New Rails project βœ”
  2. Create the database βœ”
  3. Create a migration to make a table βœ”
  4. Insert column fields to the migration file βœ”
  5. Run the migration -- table and schema made βœ”
  6. Create a model βœ”
  7. Test the model with ActiveRecord βœ”



Info

The --api flag from the docs:

screenshot

Read more about using Rails as an API here