Globals don't need to be just variables

  • Wrap global variables in Current class

    class Current < ActiveSurpport::CurrentAttributes
      attribute :account, :person
      attribute :request_id, :user_agent, :ip_address
    
      delegate :user, :integration, to: :person, allow_nil: true
      delegate :identity, to: :user, allow_nil: true
    
      resets { Time.zone = nil }
    
      def person=(person)
        super
    
        self.account = person.try(:account)
        Time.zone = person.try(:time_zone)
      end
    end
    
    • module SetCurrentRequestDetails

      module SetCurrentRequestDetails
        extend ActiveSupport::Concern
      
        included do
          before_action do
            Current.request_id = request.uuid
            Current.user_agent = request.user_agent
            Current.ip_address = request.ip
          end
        end
      end
      

-- from On Writing Software Well: Using globals when the price is right - YouTube

I was watching DHH's On Writing Software Well screencasts series1, where he explained the trade offs they've made in the Basecamp codebase.

And this idea of using a class Current to wrap all the global variables really hit me and made me realize that globals don't need to be just variables like redis_client or something like that.

Wrapping these variables in a cohesive class is really a great idea and I really like it. If you are also interested, you can check out the CurrentAttributes class2 which supports this style of programming in Rails.