<commit_before>require "active_support/core_ext/module/attribute_accessors"
require "thread"

module ActiveRecord
  module SessionStore
    # The default Active Record class.
    class Session < ActiveRecord::Base
      extend ClassMethods
      SEMAPHORE = Mutex.new

      ##
      # :singleton-method:
      # Customizable data column name. Defaults to 'data'.
      cattr_accessor :data_column_name
      self.data_column_name = 'data'

      before_save :serialize_data!
      before_save :raise_on_session_data_overflow!

      class << self
        def data_column_size_limit
          @data_column_size_limit ||= columns_hash[data_column_name].limit
        end

        # Hook to set up sessid compatibility.
        def find_by_session_id(session_id)
          SEMAPHORE.synchronize { setup_sessid_compatibility! }
          find_by_session_id(session_id)
        end

        private
          def session_id_column
            'session_id'
          end

          # Compatibility with tables using sessid instead of session_id.
          def setup_sessid_compatibility!
            # Reset column info since it may be stale.
            reset_column_information
            if columns_hash['sessid']
              def self.find_by_session_id(session_id)
                find_by_sessid(session_id)
              end

              define_method(:session_id)  { sessid }
              define_method(:session_id=) { |session_id| self.sessid = session_id }
            else
              class << self; remove_possible_method :find_by_session_id; end

              def self.find_by_session_id(session_id)
                where(session_id: session_id).first
              end
            end
          end
      end

      def initialize(*)
        @data = nil
        super
      end

      # Lazy-deserialize session state.
      def data
        @data ||= self.class.deserialize(read_attribute(@@data_column_name)) || {}
      end

      attr_writer :data

      # Has the session been loaded yet?
      def loaded?
        @data
      end

      def secure!
        session_id_column = if self.class.columns_hash['sessid']
          :sessid
        else
          :session_id
        end
        raw_session_id = read_attribute(session_id_column)
        if ActionDispatch::Session::ActiveRecordStore.private_session_id?(raw_session_id)
          # is already private, nothing to do
        else
          session_id_object = Rack::Session::SessionId.new(raw_session_id)
          update_column(session_id_column, session_id_object.private_id)
        end
      end
<commit_msg>add documentation for a new method<commit_after>require "active_support/core_ext/module/attribute_accessors"
require "thread"

module ActiveRecord
  module SessionStore
    # The default Active Record class.
    class Session < ActiveRecord::Base
      extend ClassMethods
      SEMAPHORE = Mutex.new

      ##
      # :singleton-method:
      # Customizable data column name. Defaults to 'data'.
      cattr_accessor :data_column_name
      self.data_column_name = 'data'

      before_save :serialize_data!
      before_save :raise_on_session_data_overflow!

      class << self
        def data_column_size_limit
          @data_column_size_limit ||= columns_hash[data_column_name].limit
        end

        # Hook to set up sessid compatibility.
        def find_by_session_id(session_id)
          SEMAPHORE.synchronize { setup_sessid_compatibility! }
          find_by_session_id(session_id)
        end

        private
          def session_id_column
            'session_id'
          end

          # Compatibility with tables using sessid instead of session_id.
          def setup_sessid_compatibility!
            # Reset column info since it may be stale.
            reset_column_information
            if columns_hash['sessid']
              def self.find_by_session_id(session_id)
                find_by_sessid(session_id)
              end

              define_method(:session_id)  { sessid }
              define_method(:session_id=) { |session_id| self.sessid = session_id }
            else
              class << self; remove_possible_method :find_by_session_id; end

              def self.find_by_session_id(session_id)
                where(session_id: session_id).first
              end
            end
          end
      end

      def initialize(*)
        @data = nil
        super
      end

      # Lazy-deserialize session state.
      def data
        @data ||= self.class.deserialize(read_attribute(@@data_column_name)) || {}
      end

      attr_writer :data

      # Has the session been loaded yet?
      def loaded?
        @data
      end

      # This method was introduced when addressing CVE-2019-16782
      # (see https://github.com/rack/rack/security/advisories/GHSA-hrqr-hxpp-chr3).
      # Sessions created on version <= 1.1.3 were guessable via a timing attack.
      # To secure sessions created on those old versions, this method can be called
      # on all existing sessions in the database. Users will not lose their session
      # when this is done.
      def secure!
        session_id_column = if self.class.columns_hash['sessid']
          :sessid
        else
          :session_id
        end
        raw_session_id = read_attribute(session_id_column)
        if ActionDispatch::Session::ActiveRecordStore.private_session_id?(raw_session_id)
          # is already private, nothing to do
        else
          session_id_object = Rack::Session::SessionId.new(raw_session_id)
          update_column(session_id_column, session_id_object.private_id)
        end
      end

{'fraction_non_alphanumeric': 0.06342156688577012, 'fraction_numerical': 0.0023094688221709007, 'mean_word_length': 2.1347438752783963, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 3, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '121294', 'n_tokens_mistral': 1611, 'n_tokens_neox': 1566, 'n_words': 369}