iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Rails Intro

Rails is the convention-over-configuration web framework that taught the industry MVC, migrations, REST, and asset pipelines. Modern Rails is still the most productive option for full-stack apps when youre comfortable with its opinions. This lesson sketches the parts you touch on day one — generate, model, route, controller, view.

Generate a resource end-to-end with Rails 7

EXAMPLE
# 1) Generate a new app (modern defaults — esbuild + Tailwind + Hotwire)
# rails new shop --css=tailwind --javascript=esbuild --database=postgresql

# 2) Scaffold a resource — model, migration, controller, views, routes, tests
# bin/rails g scaffold Product name:string price_cents:integer slug:string:index
# bin/rails db:migrate

# config/routes.rb
Rails.application.routes.draw do
  resources :products
  root "products#index"
end

# app/models/product.rb
class Product < ApplicationRecord
  validates :name, presence: true, length: { maximum: 120 }
  validates :slug, presence: true, uniqueness: true
  validates :price_cents, numericality: { greater_than_or_equal_to: 0 }

  before_validation :generate_slug, on: :create
  scope :active, -> { where(archived_at: nil) }

  def price_dollars = (price_cents / 100.0).round(2)

  private
  def generate_slug
    self.slug ||= name.to_s.parameterize
  end
end

# app/controllers/products_controller.rb
class ProductsController < ApplicationController
  before_action :set_product, only: %i[show edit update destroy]

  def index
    @products = Product.active.order(created_at: :desc).page(params[:page])
  end

  def show; end

  def new;  @product = Product.new end
  def edit; end

  def create
    @product = Product.new(product_params)
    if @product.save
      redirect_to @product, notice: "Product created"
    else
      render :new, status: :unprocessable_entity
    end
  end

  def update
    if @product.update(product_params)
      redirect_to @product, notice: "Updated"
    else
      render :edit, status: :unprocessable_entity
    end
  end

  def destroy
    @product.update!(archived_at: Time.current)
    redirect_to products_path, notice: "Archived"
  end

  private
  def set_product;     @product = Product.find_by!(slug: params[:id]) end
  def product_params;  params.require(:product).permit(:name, :price_cents) end
end

# app/views/products/index.html.erb
<h1>Products</h1>
<%= link_to "New product", new_product_path, class: "btn" %>
<ul>
  <% @products.each do |p| %>
    <li>
      <%= link_to p.name, p %> — \$<%= p.price_dollars %>
      <%= button_to "Archive", p, method: :delete, data: { turbo_confirm: "Sure?" } %>
    </li>
  <% end %>
</ul>

# spec/models/product_spec.rb (RSpec) — or use Minitest under test/
require "rails_helper"
RSpec.describe Product, type: :model do
  it { should validate_presence_of(:name) }
  it { should validate_uniqueness_of(:slug) }
  it "auto-generates a slug on create" do
    p = Product.create!(name: "Wool Jacket", price_cents: 19900)
    expect(p.slug).to eq("wool-jacket")
  end
end

# Run it
# bin/dev          # esbuild + Tailwind + Puma together
# bin/rails test   # or bin/rspec
# bin/rails routes -g products

Why it matters

Rails 7s Hotwire (Turbo + Stimulus) brings SPA-feel responsiveness without ever shipping a JSON API or a heavy front-end framework. For most CRUD apps, Hotwire + Tailwind is faster to build, lighter to ship, and easier to maintain than React/Vue + a separate Rails API.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
# Create + run a Rails app
rails new blog
cd blog && bin/rails server
Try it Yourself »

Exercise

Create a new Rails app.

rails blog

Test yourself

Q1. Rails follows the pattern…
Q2. Generate a new Rails app with…
Q3. The ORM that ships with Rails is…

Discussion

Loading…