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
| Feature | Session | Cookie |
|---|---|---|
| Storage location | Server or encrypted cookie | Browser |
| Size limit | 4KB (cookie-based session) | 4KB |
| Lifespan | Browser session or configurable | Set expiry or browser session |
| Security | Signed/encrypted by Rails | Plain (readable) unless signed |
| Best for | Login state, temporary data | User 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_sessionafter 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
Secureonly transmit over HTTPS - Set
HttpOnlyon 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.
