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.