Try Live
Add Docs
Rankings
Pricing
Docs
Install
Install
Docs
Pricing
More...
More...
Try Live
Rankings
Enterprise
Create API Key
Add Docs
Ruby on Rails
https://github.com/rails/rails
Admin
Rails is a web-application framework that includes everything needed to create database-backed web
...
Tokens:
665,425
Snippets:
3,676
Trust Score:
7.6
Update:
3 days ago
Context
Skills
Chat
Benchmark
82.4
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Ruby on Rails Framework Ruby on Rails is a full-stack web application framework written in Ruby that follows the Model-View-Controller (MVC) architectural pattern. It provides everything needed to create database-backed web applications with convention over configuration, making development faster and more enjoyable. Rails emphasizes "Don't Repeat Yourself" (DRY) principles and includes integrated support for database migrations, asset management, email delivery, WebSockets, background jobs, file storage, and rich text content. The framework is composed of several interconnected libraries: Active Record (ORM), Action Pack (controllers and routing), Action View (templates), Active Model (model interfaces), Action Mailer (email), Action Cable (WebSockets), Active Job (background processing), Active Storage (file attachments), Action Mailbox (inbound email), and Action Text (rich text). Each component can be used independently or together as part of a complete Rails application. --- ## Getting Started with Rails Rails provides command-line tools to quickly generate new applications and scaffold common patterns. The `rails new` command creates a complete application structure with sensible defaults. ```bash # Install Rails $ gem install rails # Create a new Rails application $ rails new myapp # Change to application directory $ cd myapp # Create the database $ bin/rails db:create # Start the development server $ bin/rails server # Visit http://localhost:3000 in your browser ``` --- ## Active Record - Model Layer Active Record is the Object-Relational Mapping (ORM) layer that connects Ruby classes to database tables. It provides automated mapping between classes and tables, associations between models, validations, callbacks, transactions, and database-agnostic migrations. ```ruby # Define a model with associations and validations class Product < ActiveRecord::Base belongs_to :category has_many :reviews has_many :order_items has_many :orders, through: :order_items validates :name, presence: true validates :price, numericality: { greater_than: 0 } validates :sku, uniqueness: true scope :in_stock, -> { where("quantity > 0") } scope :featured, -> { where(featured: true) } before_save :normalize_name private def normalize_name self.name = name.titleize end end # Create, read, update, delete operations product = Product.create(name: "Widget", price: 29.99, sku: "WGT-001") product = Product.find(1) product = Product.find_by(sku: "WGT-001") products = Product.where(featured: true).order(created_at: :desc).limit(10) product.update(price: 24.99) product.destroy # Transactions for atomic operations Product.transaction do product.decrement!(:quantity) order_item.save! end # Query interface with chaining Product.in_stock .featured .where("price < ?", 50) .includes(:category, :reviews) .order(name: :asc) .page(1) .per(20) ``` --- ## Active Record Associations Associations define relationships between models, enabling navigation between related records and automatic foreign key management. ```ruby # Define model associations class Author < ApplicationRecord has_many :books, -> { order(year_published: :desc) } has_one :profile has_many :reviews, through: :books end class Book < ApplicationRecord belongs_to :author belongs_to :publisher has_many :reviews has_and_belongs_to_many :categories scope :in_print, -> { where(out_of_print: false) } scope :recent, -> { where("year_published > ?", 5.years.ago.year) } end class Review < ApplicationRecord belongs_to :book belongs_to :customer enum :state, [:pending, :published, :hidden] end # Using associations author = Author.find(1) author.books # All books by this author author.books.in_print.recent # Scoped query on association author.books.create(title: "New Book", year_published: 2024) book = Book.includes(:author, :reviews).find(1) # Eager loading book.author.name # Access associated author book.reviews.published.count # Count published reviews ``` --- ## Active Record Migrations Migrations provide a Ruby DSL for evolving database schema over time in a version-controlled, reversible manner. ```ruby # Generate a migration # $ bin/rails generate migration CreateProducts name:string price:decimal # db/migrate/20240502100843_create_products.rb class CreateProducts < ActiveRecord::Migration[8.2] def change create_table :products do |t| t.string :name, null: false t.text :description t.decimal :price, precision: 10, scale: 2 t.integer :quantity, default: 0 t.references :category, foreign_key: true t.boolean :featured, default: false t.timestamps end add_index :products, :name add_index :products, [:category_id, :featured] end end # Add columns to existing table # $ bin/rails generate migration AddSkuToProducts sku:string:uniq class AddSkuToProducts < ActiveRecord::Migration[8.2] def change add_column :products, :sku, :string add_index :products, :sku, unique: true end end # Run migrations # $ bin/rails db:migrate # Rollback last migration # $ bin/rails db:rollback # Check migration status # $ bin/rails db:migrate:status ``` --- ## Active Record Query Interface Active Record provides a powerful query interface that abstracts SQL and works across different database systems. ```ruby # Finding records customer = Customer.find(10) # By primary key (raises if not found) customer = Customer.find_by(email: "user@example.com") # Returns nil if not found customers = Customer.find([1, 5, 10]) # Multiple records by primary keys # Conditional queries Customer.where(active: true) Customer.where("created_at > ?", 1.week.ago) Customer.where(country: ["US", "CA", "UK"]) Customer.where.not(status: "banned") # Ordering and limiting Product.order(created_at: :desc) Product.order(price: :asc, name: :desc) Product.limit(10).offset(20) # Selecting specific columns Product.select(:id, :name, :price) Product.pluck(:name) # Returns array of values # Grouping and aggregations Order.group(:status).count Product.average(:price) Product.where(featured: true).sum(:quantity) Order.group(:customer_id).having("count(*) > 5") # Joins and eager loading Book.joins(:author).where(authors: { country: "US" }) Book.includes(:author, :reviews).where(in_print: true) Book.eager_load(:author).references(:authors) # Exists and presence checks Customer.exists?(email: "user@example.com") Product.in_stock.any? Order.pending.none? ``` --- ## Action Controller - Controller Layer Action Controller handles incoming HTTP requests, processes parameters, interacts with models, and renders responses. Controllers define actions that map to routes. ```ruby class ProductsController < ApplicationController before_action :set_product, only: [:show, :edit, :update, :destroy] before_action :authenticate_user!, except: [:index, :show] def index @products = Product.includes(:category) .where(published: true) .order(created_at: :desc) .page(params[:page]) end def show @related_products = @product.category.products.where.not(id: @product.id).limit(4) end def new @product = Product.new end def create @product = current_user.products.build(product_params) if @product.save redirect_to @product, notice: "Product was successfully created." else render :new, status: :unprocessable_entity end end def update if @product.update(product_params) redirect_to @product, notice: "Product was successfully updated." else render :edit, status: :unprocessable_entity end end def destroy @product.destroy redirect_to products_url, notice: "Product was successfully deleted." end private def set_product @product = Product.find(params[:id]) end # Strong parameters - whitelist permitted attributes def product_params params.expect(product: [:name, :description, :price, :category_id, :featured, images: []]) end end ``` --- ## Rails Routing Routes map incoming URLs to controller actions and generate path/URL helpers. RESTful resource routing provides conventional CRUD routes. ```ruby # config/routes.rb Rails.application.routes.draw do # Root route root "home#index" # RESTful resources resources :products do resources :reviews, only: [:create, :destroy] collection do get :featured get :search end member do post :publish delete :archive end end # Singular resource (no ID in URL) resource :profile, only: [:show, :edit, :update] resource :cart, only: [:show, :update, :destroy] # Nested resources resources :categories do resources :products, only: [:index, :show] end # Namespace for admin area namespace :admin do resources :products resources :orders root "dashboard#index" end # API namespace with versioning namespace :api do namespace :v1 do resources :products, only: [:index, :show] resources :orders, only: [:index, :show, :create] end end # Custom routes get "/about", to: "pages#about" get "/search", to: "search#index" post "/webhooks/stripe", to: "webhooks#stripe" end # Using route helpers in controllers and views products_path # => "/products" product_path(@product) # => "/products/1" new_product_path # => "/products/new" edit_product_path(@product) # => "/products/1/edit" admin_products_path # => "/admin/products" ``` --- ## Action View - View Layer Action View handles template rendering with support for ERB, partials, layouts, and view helpers for building HTML forms, links, and other UI elements. ```erb <%# app/views/products/index.html.erb %> <h1>Products</h1> <%= link_to "New Product", new_product_path, class: "btn btn-primary" %> <div class="products"> <%= render @products %> </div> <%= paginate @products %> <%# app/views/products/_product.html.erb (partial) %> <div class="product" id="<%= dom_id(product) %>"> <%= image_tag product.image.variant(resize_to_limit: [300, 300]) if product.image.attached? %> <h3><%= link_to product.name, product %></h3> <p class="price"><%= number_to_currency(product.price) %></p> <p><%= truncate(product.description, length: 100) %></p> <% if current_user&.admin? %> <%= link_to "Edit", edit_product_path(product) %> <%= button_to "Delete", product, method: :delete, data: { confirm: "Are you sure?" } %> <% end %> </div> <%# app/views/products/_form.html.erb %> <%= form_with model: @product do |form| %> <% if @product.errors.any? %> <div class="errors"> <h4><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h4> <ul> <% @product.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= form.label :name %> <%= form.text_field :name, required: true %> </div> <div class="field"> <%= form.label :description %> <%= form.text_area :description, rows: 5 %> </div> <div class="field"> <%= form.label :price %> <%= form.number_field :price, step: 0.01, min: 0 %> </div> <div class="field"> <%= form.label :category_id %> <%= form.collection_select :category_id, Category.all, :id, :name, prompt: "Select a category" %> </div> <div class="field"> <%= form.label :images %> <%= form.file_field :images, multiple: true, direct_upload: true %> </div> <div class="field"> <%= form.check_box :featured %> <%= form.label :featured %> </div> <%= form.submit %> <% end %> ``` --- ## Active Model - Model Interfaces Active Model provides modules for building model-like classes that work with Action Pack helpers without requiring a database. ```ruby class ContactForm include ActiveModel::API include ActiveModel::Validations attr_accessor :name, :email, :subject, :message validates :name, :email, :message, presence: true validates :email, format: { with: URI::MailTo::EMAIL_REGEXP } validates :message, length: { minimum: 10 } end # Usage in controller class ContactsController < ApplicationController def new @contact = ContactForm.new end def create @contact = ContactForm.new(contact_params) if @contact.valid? ContactMailer.new_inquiry(@contact).deliver_later redirect_to root_path, notice: "Thank you for your message!" else render :new, status: :unprocessable_entity end end private def contact_params params.expect(contact_form: [:name, :email, :subject, :message]) end end # Tracking attribute changes with ActiveModel::Dirty class Person include ActiveModel::Dirty define_attribute_methods :name def name @name end def name=(val) name_will_change! unless val == @name @name = val end def save changes_applied end end person = Person.new person.name = "Alice" person.changed? # => true person.changes # => { "name" => [nil, "Alice"] } person.save person.previous_changes # => { "name" => [nil, "Alice"] } ``` --- ## Action Mailer - Email Delivery Action Mailer provides a framework for designing email service layers using templates similar to controller views. ```ruby # app/mailers/user_mailer.rb class UserMailer < ApplicationMailer default from: "notifications@example.com" def welcome_email(user) @user = user @login_url = login_url attachments["welcome.pdf"] = File.read("path/to/welcome.pdf") mail( to: @user.email, subject: "Welcome to Our App!" ) end def order_confirmation(order) @order = order @user = order.user mail( to: @user.email, subject: "Order ##{@order.number} Confirmed" ) end def password_reset(user) @user = user @reset_url = edit_password_reset_url(@user.reset_token) mail( to: @user.email, subject: "Password Reset Instructions" ) end end # app/views/user_mailer/welcome_email.html.erb <h1>Welcome, <%= @user.name %>!</h1> <p>Thank you for signing up. You can log in at:</p> <p><%= link_to "Log In", @login_url %></p> # Sending emails UserMailer.welcome_email(@user).deliver_now # Synchronous UserMailer.welcome_email(@user).deliver_later # Asynchronous via Active Job # Configuration (config/environments/production.rb) config.action_mailer.smtp_settings = { address: "smtp.example.com", port: 587, user_name: ENV["SMTP_USERNAME"], password: ENV["SMTP_PASSWORD"], authentication: :plain, enable_starttls_auto: true } ``` --- ## Active Job - Background Processing Active Job provides a framework for declaring jobs and running them on various queuing backends like Sidekiq, Resque, or Delayed Job. ```ruby # app/jobs/process_order_job.rb class ProcessOrderJob < ApplicationJob queue_as :default retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3 discard_on ActiveJob::DeserializationError def perform(order) order.process! OrderMailer.confirmation(order).deliver_later InventoryService.update_stock(order.items) end end # app/jobs/cleanup_job.rb class CleanupJob < ApplicationJob queue_as :low_priority def perform # Clean up old records Session.where("updated_at < ?", 30.days.ago).delete_all TempFile.where("created_at < ?", 1.day.ago).destroy_all end end # Enqueuing jobs ProcessOrderJob.perform_later(order) # As soon as possible ProcessOrderJob.set(wait: 1.hour).perform_later(order) # In 1 hour ProcessOrderJob.set(wait_until: Date.tomorrow.noon).perform_later(order) ProcessOrderJob.set(queue: :urgent).perform_later(order) # Configuration (config/application.rb) config.active_job.queue_adapter = :sidekiq # Scheduled jobs with recurring tasks # config/recurring.yml (Rails 8+) production: cleanup: class: CleanupJob schedule: every day at 3am reports: class: GenerateReportsJob schedule: every monday at 9am ``` --- ## Action Cable - WebSockets Action Cable integrates WebSockets with Rails for real-time features like chat, notifications, and live updates. ```ruby # app/channels/application_cable/connection.rb module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user def connect self.current_user = find_verified_user end private def find_verified_user if verified_user = User.find_by(id: cookies.encrypted[:user_id]) verified_user else reject_unauthorized_connection end end end end # app/channels/chat_channel.rb class ChatChannel < ApplicationCable::Channel def subscribed @room = Room.find(params[:room_id]) stream_for @room end def speak(data) message = @room.messages.create!( user: current_user, content: data["message"] ) ChatChannel.broadcast_to(@room, { message: render_message(message), user: current_user.name }) end private def render_message(message) ApplicationController.renderer.render( partial: "messages/message", locals: { message: message } ) end end # JavaScript client (app/javascript/channels/chat_channel.js) import consumer from "./consumer" const chatChannel = consumer.subscriptions.create( { channel: "ChatChannel", room_id: roomId }, { received(data) { const messagesContainer = document.getElementById("messages") messagesContainer.insertAdjacentHTML("beforeend", data.message) }, speak(message) { this.perform("speak", { message: message }) } } ) // Send a message document.getElementById("message-form").addEventListener("submit", (e) => { e.preventDefault() const input = document.getElementById("message-input") chatChannel.speak(input.value) input.value = "" }) ``` --- ## Active Storage - File Attachments Active Storage facilitates uploading files to cloud storage services (Amazon S3, Google Cloud Storage, Azure) and attaching them to Active Record models. ```ruby # app/models/user.rb class User < ApplicationRecord has_one_attached :avatar has_many_attached :documents end # app/models/product.rb class Product < ApplicationRecord has_many_attached :images def thumbnail images.first&.variant(resize_to_limit: [150, 150]) end end # Controller usage class UsersController < ApplicationController def update if current_user.update(user_params) redirect_to current_user, notice: "Profile updated!" else render :edit end end private def user_params params.expect(user: [:name, :email, :avatar, documents: []]) end end # Attaching files programmatically user.avatar.attach(io: File.open("/path/to/photo.jpg"), filename: "photo.jpg", content_type: "image/jpeg") user.avatar.attach(params[:avatar]) # Checking attachments user.avatar.attached? # => true user.documents.count # => 3 # Generating URLs url_for(user.avatar) rails_blob_path(user.avatar, disposition: "attachment") # Image variants (requires image processing gem) <%= image_tag user.avatar.variant(resize_to_limit: [100, 100]) %> <%= image_tag product.images.first.variant(resize_to_fill: [300, 300]) %> # Direct uploads in forms <%= form.file_field :avatar, direct_upload: true %> <%= form.file_field :images, multiple: true, direct_upload: true %> # Configuration (config/storage.yml) amazon: service: S3 access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> region: us-east-1 bucket: myapp-production # Set active storage service (config/environments/production.rb) config.active_storage.service = :amazon ``` --- ## Action Text - Rich Text Content Action Text brings rich text content and editing to Rails using the Trix editor, with automatic handling of embedded images and attachments. ```ruby # Install Action Text # $ bin/rails action_text:install # app/models/article.rb class Article < ApplicationRecord has_rich_text :content has_rich_text :excerpt end # Controller class ArticlesController < ApplicationController def create @article = Article.new(article_params) # Rich text content is automatically handled if @article.save redirect_to @article else render :new end end private def article_params params.expect(article: [:title, :content, :excerpt]) end end # Form with rich text editor <%= form_with model: @article do |form| %> <div class="field"> <%= form.label :title %> <%= form.text_field :title %> </div> <div class="field"> <%= form.label :content %> <%= form.rich_text_area :content %> </div> <%= form.submit %> <% end %> # Displaying rich text content <%= @article.content %> # Querying by rich text content Article.joins(:content_rich_text).where("action_text_rich_texts.body LIKE ?", "%keyword%") ``` --- ## Active Support - Core Extensions Active Support provides utility classes and Ruby core extensions used throughout Rails, available for use in any Ruby project. ```ruby # Time and Date extensions 2.days.ago 3.weeks.from_now Time.current.beginning_of_day Time.current.end_of_month 1.year.ago.to_date Date.current.next_week(:monday) # String extensions "hello_world".camelize # => "HelloWorld" "HelloWorld".underscore # => "hello_world" "person".pluralize # => "people" "people".singularize # => "person" "hello".titleize # => "Hello" " hello ".squish # => "hello" "hello".truncate(3) # => "hel..." # Array extensions [1, 2, 3, 4, 5].in_groups_of(2) # => [[1, 2], [3, 4], [5, nil]] [1, 2, 3].to_sentence # => "1, 2, and 3" [{a: 1}, {b: 2}].extract_options! # Hash extensions { a: 1, b: 2 }.slice(:a) # => { a: 1 } { a: 1, b: 2 }.except(:a) # => { b: 2 } { a: 1 }.reverse_merge(b: 2, a: 0) # => { b: 2, a: 1 } { a: { b: 1 } }.deep_merge(a: { c: 2 }) # => { a: { b: 1, c: 2 } } params.to_query # => "a=1&b=2" # Number extensions 1234567.89.to_fs(:currency) # => "$1,234,567.89" 1234567890.to_fs(:human_size) # => "1.15 GB" 0.456.to_fs(:percentage) # => "45.600%" # Object extensions nil.blank? # => true "".blank? # => true "hello".present? # => true nil.presence # => nil "hello".presence # => "hello" object.try(:method_name) object.try!(:method_name) # Raises if object is not nil but method missing # Memoization def expensive_calculation @expensive_calculation ||= perform_calculation end # Callbacks class Payment include ActiveSupport::Callbacks define_callbacks :process set_callback :process, :before, :validate_amount set_callback :process, :after, :send_receipt def execute run_callbacks :process do # Process payment end end end ``` --- ## Testing in Rails Rails provides built-in testing support with Minitest, including fixtures, test helpers, and integration testing capabilities. ```ruby # test/models/product_test.rb class ProductTest < ActiveSupport::TestCase test "should not save product without name" do product = Product.new(price: 10.00) assert_not product.save, "Saved the product without a name" end test "should save valid product" do product = Product.new(name: "Widget", price: 10.00, sku: "WGT-001") assert product.save end test "price must be positive" do product = products(:one) product.price = -5 assert_not product.valid? assert_includes product.errors[:price], "must be greater than 0" end end # test/controllers/products_controller_test.rb class ProductsControllerTest < ActionDispatch::IntegrationTest setup do @product = products(:one) end test "should get index" do get products_url assert_response :success assert_select "h1", "Products" end test "should create product" do assert_difference("Product.count") do post products_url, params: { product: { name: "New Product", price: 19.99, sku: "NEW-001" } } end assert_redirected_to product_url(Product.last) end test "should update product" do patch product_url(@product), params: { product: { name: "Updated Name" } } assert_redirected_to product_url(@product) @product.reload assert_equal "Updated Name", @product.name end test "should destroy product" do assert_difference("Product.count", -1) do delete product_url(@product) end assert_redirected_to products_url end end # test/system/products_test.rb (System tests with Capybara) class ProductsTest < ApplicationSystemTestCase test "visiting the index" do visit products_url assert_selector "h1", text: "Products" end test "creating a product" do visit new_product_url fill_in "Name", with: "Test Product" fill_in "Price", with: "29.99" click_on "Create Product" assert_text "Product was successfully created" end end # Run tests # $ bin/rails test # All tests # $ bin/rails test:models # Model tests only # $ bin/rails test:controllers # Controller tests only # $ bin/rails test:system # System tests # $ bin/rails test test/models/product_test.rb # Specific file ``` --- ## Summary Ruby on Rails is designed for building complete web applications quickly by following conventions and providing integrated solutions for common requirements. The framework excels at rapid prototyping, CRUD applications, content management systems, e-commerce platforms, and API backends. Rails' "convention over configuration" philosophy means developers can focus on business logic rather than boilerplate setup, while the extensive ecosystem of gems extends functionality for authentication, authorization, payment processing, search, and more. The modular architecture allows components like Active Record, Active Job, and Action Cable to be used independently in non-Rails Ruby applications. Integration patterns typically involve defining models with Active Record, creating RESTful controllers with Action Controller, building views with ERB templates and view helpers, processing background work with Active Job, handling real-time features with Action Cable, and managing file uploads with Active Storage. The framework's emphasis on testing, database migrations, and deployment tooling (including Kamal for container deployment) provides a complete development-to-production workflow for modern web applications.