<commit_before>module Globalize
  module ActiveRecord
    class Adapter
      # The cache caches attributes that already were looked up for read access.
      # The stash keeps track of new or changed values that need to be saved.
      attr_accessor :record, :stash, :translations
      private :record=, :stash=

      delegate :translation_class, :to => :'record.class'

      def initialize(record)
        @record = record
        @stash = Attributes.new
      end

      def fetch_stash(locale, name)
        stash.read(locale, name)
      end

      delegate :contains?, :to => :stash, :prefix => :stash
      delegate :write, :to => :stash

      def fetch(locale, name)
        record.globalize_fallbacks(locale).each do |fallback|
          value = stash.contains?(fallback, name) ? fetch_stash(fallback, name) : fetch_attribute(fallback, name)

          unless fallbacks_for?(value)
            set_metadata(value, :locale => fallback, :requested_locale => locale)
            return value
          end
        end

        return nil
      end

      def save_translations!
        existing_translations_by_locale = Hash[record.translations.map { |t| [ t.locale, t ] }]

        stash.each do |locale, attrs|
          if attrs.any?
            translation = existing_translations_by_locale[locale] || record.translations.build(locale: locale.to_s)
            attrs.each { |name, value| translation[name] = value }
            translation.save!
          end
        end

        reset
      end

      def reset
        stash.clear
      end

    protected

      def type_cast(name, value)
        return value.presence unless column = column_for_attribute(name)

        column.type_cast value
      end

      def column_for_attribute(name)
        translation_class.columns_hash[name.to_s]
      end

      def unserializable_attribute?(name, column)
        column.text? && translation_class.serialized_attributes[name.to_s]
      end

      def fetch_attribute(locale, name)<commit_msg>Ensure that a foreign key is always set.<commit_after>module Globalize
  module ActiveRecord
    class Adapter
      # The cache caches attributes that already were looked up for read access.
      # The stash keeps track of new or changed values that need to be saved.
      attr_accessor :record, :stash, :translations
      private :record=, :stash=

      delegate :translation_class, :to => :'record.class'

      def initialize(record)
        @record = record
        @stash = Attributes.new
      end

      def fetch_stash(locale, name)
        stash.read(locale, name)
      end

      delegate :contains?, :to => :stash, :prefix => :stash
      delegate :write, :to => :stash

      def fetch(locale, name)
        record.globalize_fallbacks(locale).each do |fallback|
          value = stash.contains?(fallback, name) ? fetch_stash(fallback, name) : fetch_attribute(fallback, name)

          unless fallbacks_for?(value)
            set_metadata(value, :locale => fallback, :requested_locale => locale)
            return value
          end
        end

        return nil
      end

      def save_translations!
        existing_translations_by_locale = Hash[record.translations.map { |t| [ t.locale, t ] }]

        stash.reject {|locale, attrs| attrs.empty?}.each do |locale, attrs|
          translation = existing_translations_by_locale[locale] ||
                          record.translations.build(locale: locale.to_s)
          attrs.each { |name, value| translation[name] = value }
          ensure_foreign_key_for(translation)
          translation.save!
        end

        reset
      end

      def reset
        stash.clear
      end

      protected

      def ensure_foreign_key_for(translation)
        # Sometimes the translation is initialised before a foreign key can be set.
        translation[translation.reflections[:globalized_model].foreign_key] = record.id
      end

      def type_cast(name, value)
        return value.presence unless column = column_for_attribute(name)

        column.type_cast value
      end

      def column_for_attribute(name)
        translation_class.columns_hash[name.to_s]
      end

      def unserializable_attribute?(name, column)
        column.text? && translation_class.serialized_attributes[name.to_s]
      end

      def fetch_attribute(locale, name)
{'fraction_non_alphanumeric': 0.0815668202764977, 'fraction_numerical': 0.0, 'mean_word_length': 2.4047058823529412, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, 'https://': 0, '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': '4808564', 'n_tokens_mistral': 1231, 'n_tokens_neox': 1203, 'n_words': 322}