This is the blog application from
Getting Started with Rails with some minor modifications, TailwindCSS
. It is a simple blog application that allows users to create, edit, and delete articles.The application is built using Ruby on Rails, a popular web application framework written in the Ruby programming language. It follows the Model-View-Controller (MVC) architectural pattern and uses Active Record as the Object-Relational Mapping (ORM) system. It also uses Embedded Ruby (ERB) as the templating language for generating dynamic content in views.
My personal breakdown of concepts and topics covered in the Getting Started with Rails guide. This is a great resource for learning the basics of Ruby on Rails. I highly recommend it for anyone who is new to the framework.
- Introducing Ruby
- Introducing rbenv
- Introducing gems
- Introducing Rails
- The Rails directory
- Starting up the Web Server
- Introducing puma
- MVC
- Introducing Active Record
- Introducing irb (Interactive Ruby)
- Introducing ERB (Embedded Ruby)
- Introducing Form Builder
- Introducing Strong Parameters
- Introducing HTTP on Rails
- Introducing psych
- Introducing Fly.io
Ruby is a dynamic, open source programming language developed by Yukihiro "Matz" Matsumoto in the mid-1990s. Ruby's combination of expressiveness, simplicity, and flexibility has made it a popular choice for both beginners and experienced developers. It's used for a wide range of applications, from web development with Ruby on Rails to scripting and automation. The language continues to evolve with new features and improvements while maintaining its core principles.
rbenv is a versatile Ruby version manager that provides a lightweight and flexible solution for managing Ruby environments. It's particularly beneficial for developers working on multiple projects with varying Ruby version requirements.
Without impacting the version of Ruby that ships with macOS, rbenv lets you seamlessly switch between multiple Ruby versions and allows you to set Ruby versions on a per-project basis.
# Install Ruby version 3.2.2 with rbenv
rbenv install 3.2.2
gems play a crucial role in the Ruby ecosystem by promoting code reuse, collaboration, and efficient management of project dependencies. They simplify the process of sharing and distributing Ruby code, contributing to the vibrancy and productivity of the Ruby programming community.
# Install the bundler gem
gem install bundler
Ruby on Rails is a web application framework that is built on the Ruby programming language. It simplifies web development by providing conventions, abstractions, and tools that enable developers to build robust and maintainable applications with less boilerplate code. The combination of Ruby's expressiveness and Rails' conventions contributes to the popularity and effectiveness of the framework in creating modern web applications.
# Install Rails with gem
gem install rails
The blog-on-rails
directory will have a number of generated files and folders that make
up the structure of a Rails application. Most of the work in this tutorial will
happen in the app
folder, but here's a basic rundown on the function of each
of the files and folders that Rails creates by default:
File/Folder | Purpose |
---|---|
app/ | Contains the controllers, models, views, helpers, mailers, channels, jobs, and assets for your application. You'll focus on this folder for the remainder of this guide. |
bin/ | Contains the rails script that starts your app and can contain other scripts you use to set up, update, deploy, or run your application. |
config/ | Contains configuration for your application's routes, database, and more. This is covered in more detail in Configuring Rails Applications. |
config.ru | Rack configuration for Rack-based servers used to start the application. For more information about Rack, see the Rack website. |
db/ | Contains your current database schema, as well as the database migrations. |
Dockerfile | Configuration file for Docker. |
Gemfile Gemfile.lock |
These files allow you to specify what gem dependencies are needed for your Rails application. These files are used by the Bundler gem. For more information about Bundler, see the Bundler website. |
lib/ | Extended modules for your application. |
log/ | Application log files. |
public/ | Contains static files and compiled assets. When your app is running, this directory will be exposed as-is. |
Rakefile | This file locates and loads tasks that can be run from the command line. The task definitions are defined throughout the components of Rails. Rather than changing Rakefile , you should add your own tasks by adding files to the lib/tasks directory of your application. |
README.md | This is a brief instruction manual for your application. You should edit this file to tell others what your application does, how to set it up, and so on. |
storage/ | Active Storage files for Disk Service. This is covered in Active Storage Overview. |
test/ | Unit tests, fixtures, and other test apparatus. These are covered in Testing Rails Applications. |
tmp/ | Temporary files (like cache and pid files). |
vendor/ | A place for all third-party code. In a typical Rails application this includes vendored gems. |
.dockerignore | This file tells Docker which files it should not copy into the container. |
.gitattributes | This file defines metadata for specific paths in a git repository. This metadata can be used by git and other tools to enhance their behavior. See the gitattributes documentation for more information. |
.gitignore | This file tells git which files (or patterns) it should ignore. See GitHub - Ignoring files for more information about ignoring files. |
.ruby-version | This file contains the default Ruby version. |
Blog-on-Rails is a functional Rails application. To see it, you need to start a web server on your development machine. You can do this by running the following in the blog-on-rails
directory:
# Start the web server
bin/rails server
Puma is a versatile web server designed to handle concurrent requests efficiently, making it a suitable choice for serving Ruby on Rails applications. Its multi-process and multi-threaded architecture, along with features like load balancing and graceful restarts, make it well-suited for deploying web applications in production environments. By default, Puma is distributed by Rails with every new application generated by the rails new
command.
Ruby on Rails follows the Model-View-Controller architectural pattern to structure web applications. This separation of concerns enhances maintainability, scalability, and code organization. Each component plays a specific role in handling user requests, managing data, and presenting the user interface. The Rails framework provides a set of conventions and tools that make it easy for developers to follow MVC principles while building robust and scalable web applications
- The Model is typically implemented as Ruby classes that interact with the database. Each model class corresponds to a database table, and instances of the class represent records in that table.
- Rails uses an Object-Relational Mapping (ORM) system called Active Record to facilitate communication between the application and the database. Active Record simplifies database operations and allows developers to work with databases using Ruby objects.
- The View is implemented using templates. Templates are typically written in Embedded Ruby (ERB) or another templating language. ERB allows Ruby code to be embedded within HTML, facilitating dynamic content generation.
- Views in Rails are associated with Controller actions, and they render the HTML that is sent to the user's browser. Views can access data provided by the Controller and present it to the user.
- The Controller is implemented as Ruby classes. Each Controller class is associated with a set of actions (methods) that correspond to user requests. For example, a UserController might have actions like
index
,show
,create
, etc. - The Controller communicates with the Model to retrieve or modify data and then selects the appropriate View to render. Controllers handle routing, request processing, and coordinating the flow of data between the Model and View.
Active Record is a core component of Ruby on Rails, serving as the ORM that connects Rails models to database tables. It simplifies database interactions, provides a rich set of functionalities for working with data, and aligns with Rails conventions to enhance developer productivity and code maintainability
Object-Relational Mapping (ORM)
ORM is a programming technique that maps objects in a programming language (like Ruby) to tables in a relational database. It simplifies database interactions by allowing developers to interact with the database using high-level programming constructs rather than writing raw SQL queries
# Define a model in Rails
# To define a model in Rails, you create a Ruby class that inherits from ActiveRecord::Base. This base class provides a set of methods and functionalities that allow the model to interact with the database
class User < ApplicationRecord::Base
end
# DB table mapping
# By convention, Active Record infers the database table name based on the class name and pluralization.
#For example, the User class maps to the users table
class User < ApplicationRecord::Base
self.table_name = "my_users"
self.primary_key = "user_id"
end
# CRUD operations
# Active Record provides methods for performing CRUD (Create, Read, Update, Delete) operations on database records
# Create a new user
user = User.new(name: "Elton John", email: "elton@rocketman.com")
user.save
# Find a user by ID
found_user = User.find(1)
# Update a user's attributes
found_user.update(name: "Elton Hercules John")
# Delete a user
found_user.destroy
# Associations
# Active Record supports defining associations between models, such as `has_many`, `belongs_to`, and `has_and_belongs_to_many`. These associations simplify the representation of relationships between tables.
class User < ApplicationRecord::Base
has_many :posts
end
class Post < ApplicationRecord::Base
belongs_to :user
end
# Validations
# Active Record includes validation mechanisms that allow developers to specify rules for data integrity. Common validations include presence, uniqueness, format, and custom validations
class User < ApplicationRecord::Base
validates :email, presence: true
end
# Callbacks
# Active Record provides callbacks, such as `before_save`, `after_create`, and `before_validation`, allowing developers to execute code at specific points in the lifecycle of a model
class User < ApplicationRecord::Base
before_save :normalize_name
private
def normalize_name
self.name = name.downcase.titleize
end
end
# Querying
# Active Record includes a powerful query interface that allows developers to construct complex database queries using a Ruby-like syntax
User.where(name: "Elton John")
# Connecting to a database
# Active Record manages database connections, and Rails provides configuration settings (in `config/database.yml`) for specifying database connection details
development:
adapter: sqlite3
database: db/development.sqlite3
# Migrations
# Active Record includes a migration system that allows developers to version-control and automate changes to the database schema over time
class CreateUsers < ActiveRecord::Migration[6.1]
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
IRB is an interactive Ruby shell that provides a convenient way for developers to experiment with Ruby code. When used within the context of a Rails application, such as through the rails console command, IRB becomes a powerful tool for interacting with and testing various aspects of the Rails environment, including models, controllers, and the database. It's a valuable tool for debugging, exploration, and quick testing within the Rails ecosystem.
Let's launch the Rails console with this command:
$ bin/rails console
You should see an irb
prompt like:
Loading development environment (Rails 7.2.0)
irb(main):001:0>
At this prompt, we can initialize a new Article
object:
irb> article = Article.new(title: "Hello Rails", body: "I am on Rails!")
It's important to note that we have only initialized this object. This object
is not saved to the database at all. It's only available in the console at the
moment. To save the object to the database, we must call save
:
irb> article.save
(0.1ms) begin transaction
Article Create (0.4ms) INSERT INTO "articles" ("title", "body", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["title", "Hello Rails"], ["body", "I am on Rails!"], ["created_at", "2020-01-18 23:47:30.734416"], ["updated_at", "2020-01-18 23:47:30.734416"]]
(0.9ms) commit transaction
=> true
The above output shows an INSERT INTO "articles" ...
database query. This
indicates that the article has been inserted into our table. And if we take a
look at the article
object again, we see something interesting has happened:
irb> article
=> #<Article id: 1, title: "Hello Rails", body: "I am on Rails!", created_at: "2020-01-18 23:47:30", updated_at: "2020-01-18 23:47:30">
The id
, created_at
, and updated_at
attributes of the object are now set.
Rails did this for us when we saved the object.
When we want to fetch this article from the database, we can call find
on the model and pass the id
as an argument:
irb> Article.find(1)
=> #<Article id: 1, title: "Hello Rails", body: "I am on Rails!", created_at: "2020-01-18 23:47:30", updated_at: "2020-01-18 23:47:30">
And when we want to fetch all articles from the database, we can call all
on the model:
irb> Article.all
=> #<ActiveRecord::Relation [#<Article id: 1, title: "Hello Rails", body: "I am on Rails!", created_at: "2020-01-18 23:47:30", updated_at: "2020-01-18 23:47:30">]>
This method returns an ActiveRecord::Relation
object, which
you can think of as a super-powered array.
To learn more about models, see Active Record Basics and Active Record Query Interface.
Ruby on Rails primarily uses ERB (Embedded RuBy) as its default templating system for generating dynamic content in views. ERB allows developers to embed Ruby code within HTML or other text documents, making it easy to create dynamic web pages.
Templating Languages
Templating languages enable the seamless integration of dynamic content, facilitate the separation of concerns, and provide tools for handling user input and generating HTML with embedded code. They contribute to the overall efficiency and structure of web development projects
<!-- Basic ERB syntax -->
<!-- ERB tags are delimited by <% %> and <%= %> -->
<!-- The <% %> tag is used for embedding Ruby code that doesn't need to be displayed -->
<!-- The <%= %> tag is used for embedding Ruby code that needs to be displayed -->
<!-- app/views/users/index.html.erb -->
<h1> Hello, <%= @user.name %>! </h1>
<!-- ERB control flow -->
<!-- ERB tags can be used to implement control flow constructs like if/else, while, and for loops -->
<!-- app/views/users/index.html.erb -->
<% if @user.name == "Elton John" %>
<h1> Hello, <%= @user.name %>! </h1>
<% else %>
<h1> Hello, stranger! </h1>
<% end %>
<!-- ERB partials -->
<!-- ERB partials are reusable templates that can be rendered within other templates -->
<!-- Partials are typically used to render common elements like headers, footers, and navigation bars -->
<!-- app/views/users/index.html.erb -->
<%= render partial: "header" %>
<h1> Hello, <%= @user.name %>! </h1>
<%= render partial: "footer" %>
Form Builder in Ruby on Rails is a powerful tool for generating HTML forms. It simplifies the process of creating form elements, handling form submissions, and displaying validation errors. Form builders are closely tied to models, making it convenient to work with model-backed forms. The form_for
helper, combined with form builders, provides a clean and efficient way to create dynamic and interactive forms in Rails applications.
<!-- Basic form -->
<!-- The form_for helper generates a form that is backed by a model -->
<!-- The form builder provides methods for generating form elements like text fields, text areas, checkboxes, radio buttons, and select boxes -->
<!-- app/views/users/new.html.erb -->
<%= form_for @user do |form| %>
<%= form.label :name %>
<%= form.text_field :name %>
<%= form.submit %>
<% end %>
<!-- Form with nested attributes -->
<!-- Form builders can be used to generate forms with nested attributes -->
<!-- Nested attributes allow you to save associated records from a single form -->
<!-- app/views/users/new.html.erb -->
<%= form_for @user do |form| %>
<%= form.label :name %>
<%= form.text_field :name %>
<%= form.fields_for :posts do |post_form| %>
<%= post_form.label :title %>
<%= post_form.text_field :title %>
<% end %>
<%= form.submit %>
<% end %>
<!-- Form with validation errors -->
<!-- Form builders can be used to display validation errors -->
<!-- Validation errors are displayed using the error_messages_for helper -->
<!-- app/views/users/new.html.erb -->
<%= form_for @user do |form| %>
<%= form.label :name %>
<%= form.text_field :name %>
<%= form.submit %>
<%= error_messages_for @user %>
<% end %>
<!-- app/helpers/application_helper.rb -->
module ApplicationHelper
def error_messages_for(object)
render partial: "shared/error_messages", locals: { object: object }
end
end
<!-- app/views/shared/_error_messages.html.erb -->
<% if object.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(object.errors.count, "error") %> prohibited this <%= object.class.name.downcase %> from being saved:</h2>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Strong Parameters in Ruby on Rails provides a mechanism for whitelisting parameters that are allowed for mass assignment. It helps prevent mass assignment vulnerabilities by requiring explicit definition of permitted parameters in controllers. This is a crucial security feature to ensure that only intended attributes are allowed to be modified through user input.
# Strong parameters
# Strong parameters are defined using the permit method in controllers
# The permit method takes a list of permitted attributes as arguments
class UsersController < ApplicationController
def create
@user = User.new(user_params)
if @user.save
redirect_to @user
else
render "new"
end
end
private
def user_params
params.require(:user).permit(:name, :email)
end
end
http_basic_authenticate_with
is a method in Rails that simplifies the implementation of HTTP Basic Authentication for controller actions. It provides a quick way to add a basic layer of authentication to certain parts of your application, particularly for scenarios where a full-fledged user authentication system may be unnecessary.
When a user tries to access an action protected by HTTP Basic Authentication, the browser prompts the user for a username and password. Rails decodes the provided credentials and compares them against the specified name and password. If the credentials match, the user is granted access to the action; otherwise, access is denied.
the **psych**
gem is a YAML parser and emitter that is integral to Ruby and, consequently, to Ruby on Rails. It plays a crucial role in handling YAML configurations, parsing YAML front matter in views, and providing secure and efficient YAML processing capabilities for various aspects of Rails applications.
Fly.io is a great place to run Rails applications, especially if you plan on running them on multiple servers around the world so your users have a fast, snappy, low-latency experience. Fly provides a simple and efficient way to deploy and scale applications across multiple regions and is a great choice for deploying Ruby on Rails applications because it provides a seamless experience for deploying and managing applications with minimal configuration.