Skip to content

Latest commit

 

History

History
353 lines (267 loc) · 6.59 KB

File metadata and controls

353 lines (267 loc) · 6.59 KB

Rails Course

MVC Design Pattern

Model: provides the interface for stored data

Controller: bridge between model and views

Views: user interface (can be html, json, etc)

Request Lifecycle

alt text

Basic Rendering

def index
    message = "Hello, Rails!"
    render plain: message
end
def index
    message = "Hello, Rails!"
    render html: "<h1>#{message}</h1>".html_safe
  end

Accessing QueryString Parameters

def get_query_string
    render plain: "Query string parameters: #{params[:message]}"
end

Accessing controller variables from views

def pass_data_to_views
    @message="Hello, Rails"
end
<h1>Accessing Instance Variables in Views</h1>

<div>
  <p>Message: <%= @message %></p>
</div>

Conditional Rendering

def conditional_rendering
    @data={
      name: "John Doe",
      country: "USA",
      role: "admin",
      is_logged_in: true
    }
end
<h1>Conditional Rendering</h1>

<table class="table">
    <tr>
        <td>Name</td>
    </tr>
    <tr>
        <td><%= @data[:name] %></td>
        <td><%= @data[:country] %></td>
        <td><%= @data[:role] %></td>
    </tr>
</table>

<% if @data[:is_logged_in] %>
    <p>Welcome to the system</p>
<% else %>
    <p>Please login to view the data</p>
<% end %>

Looping in Views

  def looping_in_views
    @users = [
      {name: "John Doe", country: "USA", role: "admin"},
      {name: "Jane Doe", country: "UK", role: "user"},
      {name: "John Smith", country: "Australia", role: "user"}
    ]
  end
<h1>Looping in Views</h1>

<ul class="list-group">
    <% @users.each do |user| %>
    <li class="list-group-item">
        <%= user[:name] %> is from <%= user[:country] %>
    </li>
    <% end %>
</ul>

Debugging

ViewHelper Methods

<%= debug @users %>
<%= @users.inspect %>

Debug Gem

Execution will stop and dev server will show debug info. Use c to continue to the next breakpoint. Use break 71 to add a breakpoint on line 71.

debugger

Web Console Gem

Inspect directly on the browser. Use instance_variables or local_variables to list available variables.

console

Logging

Format and where to output can be configured on environments/<env>.rb

  def logging_demo
    Rails.logger.debug("The debug level is for detailed info that assists in development.")
    Rails.logger.info("The info level provides information for the normal application process.")
    Rails.logger.warn("The warning level indicates something unexpected that might not be an error.")
    Rails.logger.error("The error level indicates that something went wrong.")
    Rails.logger.fatal("The fatal level indicates that something went critically wrong.")
  end

Consuming APIs

  def index
    response = HTTParty.get(base_url)
    @users = response.parsed_response
  end

  def show
    response = HTTParty.get("#{base_url}/#{params[:id]}")
    @user = response.parsed_response
  end

  private
  def base_url
    "https://fakestoreapi.com/users"
  end

Respond To

  def render_404
    respond_to do |format|
      format.html { render file: "#{Rails.root}/public/404.html", layout: false, status: :not_found }
      format.any  { head :not_found }
    end
  end

ActiveRecord Operations

Retrieval

  • all – All records
  • find(id) – Find by ID, raises error if it does not exist.
  • find_by(attr: val) – Find first match or nil if it does not exist.
  • where(attr: val) – Filter records
  • order(:attr) – Sort results
  • limit(n) – Limit results
  • offset(n) – Skip n records
  • first / last – First/last record

Creation & Updates

  • new(attr) – New object (not saved)
  • create(attr) – New + save
  • create!(attr) – New + save (raises error if invalid)
  • save – Save record
  • update(attr) – Update record
  • find_or_create_by(attr) – Find or create

Deletion

  • destroy – Delete a record
  • destroy_all – Delete multiple

Aggregations

  • count – Number of records
  • pluck(:attr) – Get column values
  • group(:attr) – Group records˝
  • having(cond) – Filter grouped records

Associations & Queries

  • includes(:assoc) – Eager load (avoid N+1)
  • joins(:assoc) – SQL JOIN
  • select(:attr) – Select specific columns
  • exists?(cond) – Check existence

Model Level Validation

  • presence – Ensures a field is not empty.
  • uniqueness – Ensures a field is unique.
  • length – Limits character count.
  • format – Validates with a regex.
  • numericality – Ensures numerical value (e.g., integer, greater than).
  • inclusion – Restricts values to a set.
  • exclusion – Prevents certain values.
  • acceptance – Requires agreement (e.g., terms of service).
  • confirmation – Requires a matching field (e.g., password).
  • custom validation – Uses validate :method_name.

Devise Authentication

Enable Authentication in Controllers

before_action :authenticate_user!  

Routes & Views

Devise auto-generates routes:

devise_for :users

Generate customizable views:

rails g devise:views

Accessing current_user

In Controllers

class ArticlesController < ApplicationController
  before_action :authenticate_user!  # Ensure user is logged in

  def index
    @articles = current_user.articles  # Fetch only current user's articles
  end
end

In Views

<p>Welcome, <%= current_user.email %>!</p>

In Helpers

module ApplicationHelper
  def user_signed_in_message
    "Hello, #{current_user.username}" if user_signed_in?
  end
end

Checking if a User is Logged In

In Controllers

if user_signed_in?
  puts "User is logged in as #{current_user.email}"
end

In Views

<% if user_signed_in? %>
  <p>Welcome, <%= current_user.username %>!</p>
<% else %>
  <p>Please log in.</p>
<% end %>

Cancancan Authorization

Define Abilities (app/models/ability.rb)

class Ability  
  include CanCan::Ability  

  def initialize(user)  
    user ||= User.new  
    if user.admin?  
      can :manage, :all  
    else  
      can :read, Article  
      can :create, Article if user.persisted?  
      can :update, Article, user_id: user.id  
    end  
  end  
end

Authorize in Controllers

class ArticlesController < ApplicationController  
  load_and_authorize_resource  

  def index  
    @articles = Article.accessible_by(current_ability)  
  end  
end

Handle Unauthorized Access (ApplicationController)

rescue_from CanCan::AccessDenied do |exception|  
  redirect_to root_path, alert: "Access denied!"
end