RoR Session and Cookies

HTTP is stateless — each request the browser sends is independent. The server has no memory of who made the previous request. Sessions and cookies solve this by storing small pieces of information that travel back and forth between the browser and server, creating the illusion of a continuous user experience.

Cookies — Stored in the Browser

A cookie is a small piece of data the server sends to the browser. The browser stores it and sends it back with every subsequent request to that domain.

First Visit:
  Browser → GET /           → Server
  Server  → Sets cookie: user_pref=dark_mode → Browser
  Browser stores the cookie

Second Visit:
  Browser → GET /products + Cookie: user_pref=dark_mode → Server
  Server reads the cookie and knows the user prefers dark mode

Setting and Reading Cookies in Rails

Set a cookie:
cookies[:user_preference] = "dark_mode"
cookies[:language] = { value: "en", expires: 30.days.from_now }

Read a cookie:
cookies[:user_preference]     # => "dark_mode"
cookies[:language]            # => "en"

Delete a cookie:
cookies.delete(:user_preference)

Permanent and Signed Cookies

Permanent cookie (20 years expiry):
cookies.permanent[:newsletter] = "subscribed"

Signed cookie (tamper-proof):
cookies.signed[:user_id] = current_user.id

Encrypted cookie (tamper-proof + hidden):
cookies.encrypted[:cart_data] = { items: [1, 2, 3] }.to_json

Read signed/encrypted cookies the same way:
cookies.signed[:user_id]         # => 42
cookies.encrypted[:cart_data]    # => '{"items":[1,2,3]}'

Always use signed or encrypted cookies for sensitive data. Plain cookies can be read and modified by the user.

Sessions — Server-Side Memory

A session stores data on the server (or in an encrypted cookie) and identifies the user with a session ID cookie. Rails uses the session to remember who is logged in.

Session Flow:

1. User logs in
   Server creates a session: { user_id: 42 }
   Server sends session ID in a cookie: _session_id=abc123

2. User makes another request
   Browser sends: Cookie: _session_id=abc123
   Server looks up session data for abc123
   Finds: { user_id: 42 }
   Loads User.find(42) as current_user

3. User logs out
   Server clears the session data
   Session cookie becomes invalid

Using the Session in Rails

Set session data:
session[:user_id] = @user.id
session[:cart_count] = 3
session[:last_visited] = Time.now

Read session data:
session[:user_id]       # => 42
session[:cart_count]    # => 3

Delete a key:
session.delete(:cart_count)

Clear the entire session (logout):
reset_session

Session vs Cookie Comparison

FeatureSessionCookie
Storage locationServer or encrypted cookieBrowser
Size limit4KB (cookie-based session)4KB
LifespanBrowser session or configurableSet expiry or browser session
SecuritySigned/encrypted by RailsPlain (readable) unless signed
Best forLogin state, temporary dataUser preferences, tracking

Rails Session Storage Options

Default: CookieStore
  Session stored entirely in a signed, encrypted cookie
  Fast — no database query needed
  4KB size limit

Database-backed: ActiveRecord::SessionStore
  gem "activerecord-session_store"
  Stores session in database
  No size limit, sessions revocable server-side
  Slightly slower (requires a DB query)

Redis-backed: ActionDispatch::Session::RedisSessionStore
  Stores session in Redis
  Fast, no size limit, sessions revocable
  Requires a Redis server

The default CookieStore works well for most apps. Switch to database or Redis sessions if you need server-side session invalidation (force-logout all devices).

Building a Simple Shopping Cart with Session

Add item to cart:
def add_to_cart
  session[:cart] ||= []
  session[:cart] << params[:product_id]
  redirect_to cart_path, notice: "Item added to cart."
end

View cart:
def show
  @product_ids = session[:cart] || []
  @products = Product.where(id: @product_ids)
end

Clear cart:
def empty_cart
  session.delete(:cart)
  redirect_to root_path, notice: "Cart cleared."
end

Remember Me with Cookies

The "Remember me" feature keeps a user logged in across browser restarts using a long-lived cookie. Devise handles this automatically when you include the :rememberable module.

Devise rememberable in User model:
  devise :rememberable

In the login form:
  <%= f.check_box :remember_me %>
  <%= f.label :remember_me, "Keep me logged in" %>

When checked:
  Devise sets a remember_token cookie with 2-week expiry
  On next visit, Devise reads the cookie and re-authenticates the user

Security Considerations

  • Always call reset_session after login to prevent session fixation attacks
  • Never store passwords, credit card numbers, or full sensitive data in sessions or cookies
  • Use HTTPS in production — cookies marked with Secure only transmit over HTTPS
  • Set HttpOnly on cookies to prevent JavaScript from reading them
config/initializers/session_store.rb

Rails.application.config.session_store :cookie_store,
  key: "_myapp_session",
  secure: Rails.env.production?,      ← HTTPS only in production
  httponly: true,                     ← not readable by JavaScript
  same_site: :lax                     ← CSRF protection

Sessions and cookies are foundational to how web apps remember their users. Rails manages them securely by default, and understanding how they work helps you build features like shopping carts, login state, and user preferences correctly.

Leave a Comment

Your email address will not be published. Required fields are marked *