We've moved discussions to Discord

Should static pages have access to cookies?

Darren Smyth •
Hi all

I'm finding that my static pages defined in the routes.rb file don't seem to have access to cookies? Is that correct? I'm trying to read the value of a cookie but the pages below seem to return a null object. 

scope controller: :static do
  get :about
  get :terms
  get :privacy
  get :cookies
  get :returns
  get :delivery
end

At the start of the Static controller I have a before_action to find an order if it exists in the DB or Cookie.

def find_order
  @order = if current_user
             Order.where(
               user: current_user,
               basket: true
             ).first
           else
             if cookies
               if cookies[:ordernum]
                 Order.where(
                   ordernum: cookies[:ordernum],
                   basket: true
                 ).first
               end
             end
           end
end
helper_method :find_order

Without the check for if cookies and then if cookies[:ordernum] it fails on the static pages.

Thanks for any help!

PS. If anyone feels the code could be better ... please let me know! There must be a nicer way to achieve this. It feels a little clunky.
Chris Oliver •
Every controller in Rails has the cookies method since it comes from ApplicationController. 

You'll have to share some more information on the actual failure.
Darren Smyth •
Sorry Chris Oliver   ... I wasn't sure how much to add ... Here is much more information:

I'm finding that my static pages defined in the routes.rb file don't seem to have access to cookies? Is that correct? I'm trying to read the value of a cookie but the pages below seem to return a null object.

My routes.rb contains the following:

scope controller: :static do
  get :about
  get :terms
  get :privacy
  get :cookies
  get :returns
  get :delivery
end


For completeness here is the Static Controller:

# frozen_string_literal: true

class StaticController < ApplicationController
  before_action :find_order

  def index; end

  def about; end

  def pricing
    redirect_to root_path, alert: t('.no_plans') unless Plan.without_free.exists?
  end

  def terms; end

  def privacy; end

  def cookies; end

  def returns; end

  def delivery; end
end


And this is how the cookie is set:

class OrdersController < ApplicationController
before_action :find_order

def add_hamper
    @order ||= Order.create!(
      ordernum: find_next_order_number,
      user: current_user,
      basket: true
    )
    @order.hampers << Hamper.friendly.find(params[:id])
    update_order_total(@order)
    if current_user&.custaddress
      @order.update(custaddress: current_user.custaddress)
    else
      cookies[:ordernum] = @order.ordernum
    end

    redirect_to order_path(@order.ordernum)
    # Update basket in Navbar
    # Save the information as a cookie reference if they are not signed in
  end


At the start of each controller I have a before_action to find an order if it exists in the DB or Cookie. For all other controllers, the find_order method is working. For the StaticController, there seems to be no access to the cookies.

Here is my find_order as defined in ApplicationController:

def find_order
  @order = if current_user
             Order.where(
               user: current_user,
               basket: true
             ).first
           else
             if cookies[:ordernum]
               Order.where(
                 ordernum: cookies[:ordernum],
                 basket: true
               ).first
             end
           end
end
helper_method :find_order

This is what I have from the console when the find_order method is being called from the returns.html static page (only a problem when a user is not signed in):

NoMethodError (undefined method `[]' for nil:NilClass):  app/controllers/application_controller.rb:27:in `find_order'

Line 27 is the line of code stating: if cookies[:ordernum]

I have checked and the cookie is very must present.

Thanks for any help with this.
Chris Oliver •
The full stracktrace is important here. Did it call that from the controller or from the view?
Darren Smyth •
Chris Oliver ... here is the stack track. find_order is being called from the controller with the method being defined in ApplicationController.rb

19:34:57 web.1     | Started GET "/welcome" for ::1 at 2020-11-05 
19:34:57 +110019:34:57 web.1     | Processing by WelcomeController#index as HTML
19:34:57 web.1     | Completed 500 Internal Server Error in 47ms (ActiveRecord: 0.0ms | Allocations: 52843
19:34:57 web.1     | 
19:34:57 web.1     | 
19:34:57 web.1     |  
19:34:57 web.1     | NoMethodError (undefined method `dig' for #<ActionDispatch::Cookies::CookieJar:0x00007ffa5497b660>):
19:34:57 web.1     |  
19:34:57 web.1     | app/controllers/application_controller.rb:29:in `find_order'

The WelcomeController has the following:

class WelcomeController < ApplicationController
  invisible_captcha only: [:add_to_mailing], honeypot: :nickname
  before_action :find_order

  def index
    @categories = Category.all.order(id: :asc)
    @popular = Hamper.where(popular: true, available: true).order(id: :asc)
  end
end

When called from something in the StaticController this is the stack trace:

19:47:57 web.1     | Started GET "/terms" for ::1 at 2020-11-05 19:47:57 +1100
19:47:57 web.1     | Processing by StaticController#terms as HTML
19:47:57 web.1     | Completed 500 Internal Server Error in 2ms (ActiveRecord: 0.0ms | Allocations: 2541)
19:47:57 web.1     | 
19:47:57 web.1     | 
19:47:57 web.1     |  
19:47:57 web.1     | NoMethodError (undefined method `dig' for nil:NilClass):
19:47:57 web.1     |  
19:47:57 web.1     | app/controllers/application_controller.rb:29:in `find_order'
Notifications
You’re not receiving notifications from this thread.