Ruby on Rails - Controllers
Ruby on Rails - Controllers
Section titled “Ruby on Rails - Controllers”The Controller is the ‘C’ in MVC for a Rails application. It acts as an intermediary between the user (via routes and views) and the application’s data (models). Controllers handle incoming web requests, retrieve or modify data using models, and then render a response, usually by selecting a view template.
Key responsibilities of a controller:
- Receiving HTTP requests from the router.
- Interacting with models to fetch, create, update, or delete data.
- Managing session information and cookies.
- Handling user authentication and authorization (often with helper gems).
- Making data available to views via instance variables (e.g.,
@books). - Choosing which view template to render or which URL to redirect to.
Creating a Controller
Section titled “Creating a Controller”You can generate a controller using the Rails generator. For our library application, let’s create a BooksController:
$ bin/rails generate controller Books index show new edit create update destroyConventionally, controller names are plural and CamelCased (e.g., BooksController). This command creates:
app/controllers/books_controller.rb- View template files for the specified actions (e.g.,
app/views/books/index.html.erb) - Test files, helper files, and potentially asset files.
- It also adds resourceful routes for
bookstoconfig/routes.rbif they don’t exist.
The generated app/controllers/books_controller.rb will look something like this:
class BooksController < ApplicationController def index end
def show end
# ... other generated actions ...endController classes inherit from ApplicationController (defined in app/controllers/application_controller.rb), which is a good place for application-wide controller logic like authentication or layout settings.
Implementing Controller Actions (CRUD Example)
Section titled “Implementing Controller Actions (CRUD Example)”Let’s implement common CRUD (Create, Read, Update, Delete) actions for our BooksController.
index Action (List Books)
Section titled “index Action (List Books)”The index action typically displays a list of resources.
def index @books = Book.all.order(title: :asc) # Fetch all books, order by title # Rails will automatically render app/views/books/index.html.erbendshow Action (Display One Book)
Section titled “show Action (Display One Book)”The show action displays details for a single resource, identified by params[:id].
before_action :set_book, only: [:show, :edit, :update, :destroy]# ...def show # @book is set by the set_book before_action # Renders app/views/books/show.html.erbend# ...private
def set_book @book = Book.find(params[:id])rescue ActiveRecord::RecordNotFound flash[:alert] = "The book you were looking for could not be found." redirect_to books_pathendbefore_action :set_book calls the set_book method before the specified actions. This DRYs up code for finding a book. Error handling for RecordNotFound is good practice.
new Action (Form for New Book)
Section titled “new Action (Form for New Book)”The new action prepares an empty @book object for the new book form.
def new @book = Book.new @subjects = Subject.all.order(:name) # For the subject dropdown in the form # Renders app/views/books/new.html.erbendcreate Action (Save New Book)
Section titled “create Action (Save New Book)”The create action handles the submission from the new form and attempts to save the new book.
def create @book = Book.new(book_params) if @book.save redirect_to @book, notice: 'Book was successfully created.' # Redirect to the show page else @subjects = Subject.all.order(:name) # Reload subjects for the form if re-rendering render :new, status: :unprocessable_entity # Re-render the new form with errors endendbook_params is a private method using Strong Parameters to permit only allowed attributes, preventing mass assignment vulnerabilities.
Strong Parameters
Section titled “Strong Parameters”private
def book_params params.require(:book).permit(:title, :price, :subject_id, :description, :published_at)endedit Action (Form to Edit Book)
Section titled “edit Action (Form to Edit Book)”The edit action fetches an existing book (using set_book) for the edit form.
def edit # @book is set by set_book @subjects = Subject.all.order(:name) # Renders app/views/books/edit.html.erbendupdate Action (Save Changes to Book)
Section titled “update Action (Save Changes to Book)”The update action handles submission from the edit form.
def update # @book is set by set_book if @book.update(book_params) redirect_to @book, notice: 'Book was successfully updated.' else @subjects = Subject.all.order(:name) render :edit, status: :unprocessable_entity endenddestroy Action (Delete Book)
Section titled “destroy Action (Delete Book)”The destroy action deletes a book.
def destroy # @book is set by set_book @book.destroy redirect_to books_url, notice: 'Book was successfully destroyed.', status: :see_otherendThe status: :see_other (HTTP 303) is recommended for redirects after non-GET requests that change state, especially with Turbo.
Complete BooksController Example:
Section titled “Complete BooksController Example:”class BooksController < ApplicationController before_action :set_book, only: [:show, :edit, :update, :destroy] before_action :load_subjects, only: [:new, :edit, :create, :update] # Load subjects for forms
def index @books = Book.includes(:subject).all.order(title: :asc) end
def show end
def new @book = Book.new end
def edit end
def create @book = Book.new(book_params) if @book.save redirect_to @book, notice: 'Book was successfully created.' else render :new, status: :unprocessable_entity end end
def update if @book.update(book_params) redirect_to @book, notice: 'Book was successfully updated.' else render :edit, status: :unprocessable_entity end end
def destroy @book.destroy redirect_to books_url, notice: 'Book was successfully destroyed.', status: :see_other end
# Example custom action for listing books by subject (if needed here) # def books_by_subject # @subject = Subject.find(params[:subject_id]) # @books = @subject.books.order(title: :asc) # render :index # Or a custom view like 'books_by_subject.html.erb' # end
private
def set_book @book = Book.find(params[:id]) rescue ActiveRecord::RecordNotFound flash[:alert] = "The book you were looking for could not be found." redirect_to books_path end
def load_subjects @subjects = Subject.all.order(:name) end
def book_params params.require(:book).permit(:title, :price, :subject_id, :description, :published_at) endendThis controller now handles the full lifecycle of book resources.
What is Next?
Section titled “What is Next?”With your controller actions defined, you need to define routes that map URLs to these actions. Then, you’ll create view templates to display the information and forms for user interaction.