Search code examples
ruby-on-railsrubydevisehttp-caching

Rails: Why is etag not available in before_action?


I am trying to add a use etag to add a ETag with the current users ID:

UsersController:Class < ApplicationController 
  etag { current_user.id } if user_signed_in?
end

However this fails since the Devise helpers are not available when the controller class is defined: undefined method `user_signed_in?'

If I attempt to use etag in a before_action it is not defined:

before_action do
 etag { current_user.try(:id) } if user_signed_in? # undefined method `etag'
end

I have also tried:

before_action do
  self.etag { current_user.id } if user_signed_in? 
end

Which does not seem to add an extra etagger.


Solution

  • In you first example self is the class itself, so while the etag method is defined, user_signed_in isn't. Rails ignores any etag block that returns nil you could instead do

    etag { current_user.id if user_signed_in? }
    

    or simply

    etag { current_user.try :id}
    

    Your second and third examples don't work because rails uses instance_exec to evaluate the block, so self is an instance of the class on which you cannot call class methods.

    Lastly, I can't tell from what you've posted whether you're already aware of this, but the etaggers added with etag are only used if you call fresh_when.