<commit_before>module Surus
  module JSON
    class Query
      attr_reader :original_scope
      attr_reader :options

      def initialize(original_scope, options={})
        @original_scope = original_scope
        @options = options
      end

      def to_sql
        selected_columns = if options.key? :columns
          options[:columns].clone
        else
          table_columns.map(&:name)
        end

        included_associations_name_and_options.each do |association_name, association_options|
          association = klass.reflect_on_association association_name
          subquery = case association.source_macro
          when :belongs_to
            association_scope = association
              .klass
              .where("#{connection.quote_column_name association.active_record_primary_key}=#{connection.quote_column_name association.foreign_key}")
            Query.new(association_scope, association_options).to_sql
          when :has_many
            association
              .klass
              .select("array_to_json(array_agg(row_to_json(#{association.quoted_table_name})))")
              .where("#{quoted_table_name}.#{connection.quote_column_name association.active_record_primary_key}=#{connection.quote_column_name association.foreign_key}")
              .to_sql
          end
          selected_columns << "(#{subquery}) #{association_name}"
        end

        subquery = select(selected_columns.map(&:to_s).join(', ')).to_sql
        "select row_to_json(t) from (#{subquery}) t"
      end

      private
      def klass
        original_scope.klass
      end

      def table_columns
        klass.columns
      end

      def included_associations_name_and_options
        _include = options[:include]
        if _include.nil?
          {}
        elsif _include.kind_of?(::Hash)<commit_msg>Refactor: Extract selected_columns and associated_columns<commit_after>module Surus
  module JSON
    class Query
      attr_reader :original_scope
      attr_reader :options

      def initialize(original_scope, options={})
        @original_scope = original_scope
        @options = options
      end

      def to_sql
        columns = selected_columns + association_columns
        subquery = select(columns.map(&:to_s).join(', ')).to_sql
        "select row_to_json(t) from (#{subquery}) t"
      end

      private
      def klass
        original_scope.klass
      end

      def table_columns
        klass.columns
      end

      def selected_columns
        if options.key? :columns
          options[:columns]
        else
          table_columns.map(&:name)
        end
      end

      def association_columns
        included_associations_name_and_options.map do |association_name, association_options|
          association = klass.reflect_on_association association_name
          subquery = case association.source_macro
          when :belongs_to
            association_scope = association
              .klass
              .where("#{connection.quote_column_name association.active_record_primary_key}=#{connection.quote_column_name association.foreign_key}")
            Query.new(association_scope, association_options).to_sql
          when :has_many
            association
              .klass
              .select("array_to_json(array_agg(row_to_json(#{association.quoted_table_name})))")
              .where("#{quoted_table_name}.#{connection.quote_column_name association.active_record_primary_key}=#{connection.quote_column_name association.foreign_key}")
              .to_sql
          end
          "(#{subquery}) #{association_name}"
        end
      end

      def included_associations_name_and_options
        _include = options[:include]
        if _include.nil?
          {}
        elsif _include.kind_of?(::Hash)
{'fraction_non_alphanumeric': 0.07891264185801003, 'fraction_numerical': 0.0, 'mean_word_length': 2.4052111410601977, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, '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': '4367321', 'n_tokens_mistral': 1016, 'n_tokens_neox': 1025, 'n_words': 186}