<commit_before># frozen_string_literal: true

require 'multi_json'
require 'set'

module Grape
  # An Entity is a lightweight structure that allows you to easily
  # represent data from your application in a consistent and abstracted
  # way in your API. Entities can also provide documentation for the
  # fields exposed.
  #
  # @example Entity Definition
  #
  #   module API
  #     module Entities
  #       class User < Grape::Entity
  #         expose :first_name, :last_name, :screen_name, :location
  #         expose :field, documentation: { type: "string", desc: "describe the field" }
  #         expose :latest_status, using: API::Status, as: :status, unless: { collection: true }
  #         expose :email, if: { type: :full }
  #         expose :new_attribute, if: { version: 'v2' }
  #         expose(:name) { |model, options| [model.first_name, model.last_name].join(' ') }
  #       end
  #     end
  #   end
  #
  # Entities are not independent structures, rather, they create
  # **representations** of other Ruby objects using a number of methods
  # that are convenient for use in an API. Once you've defined an Entity,
  # you can use it in your API like this:
  #
  # @example Usage in the API Layer
  #
  #   module API
  #     class Users < Grape::API
  #       version 'v2'
  #
  #       desc 'User index', { params: API::Entities::User.documentation }
  #       get '/users' do
  #         @users = User.all
  #         type = current_user.admin? ? :full : :default
  #         present @users, with: API::Entities::User, type: type
  #       end
  #     end
  #   end
  class Entity
    attr_reader :object, :delegator, :options

    # The Entity DSL allows you to mix entity functionality into
    # your existing classes.
    module DSL
      def self.included(base)
        base.extend ClassMethods
        ancestor_entity_class = base.ancestors.detect { |a| a.entity_class if a.respond_to?(:entity_class) }
        base.const_set(:Entity, Class.new(ancestor_entity_class || Grape::Entity)) unless const_defined?(:Entity)
      end

      module ClassMethods
        # Returns the automatically-created entity class for this
        # Class.
        def entity_class(search_ancestors = true)
          klass = const_get(:Entity) if const_defined?(:Entity)
          klass ||= ancestors.detect { |a| a.entity_class(false) if a.respond_to?(:entity_class) } if search_ancestors
          klass
        end

        # Call this to make exposures to the entity for this Class.
        # Can be called with symbols for the attributes to expose,
        # a block that yields the full Entity DSL (See Grape::Entity),
        # or both.
        #
        # @example Symbols only.
        #
        #   class User
        #     include Grape::Entity::DSL
        #
        #     entity :name, :email
        #   end
        #
        # @example Mixed.
        #
        #   class User
        #     include Grape::Entity::DSL
        #
        #     entity :name, :email do
        #       expose :latest_status, using: Status::Entity, if: :include_status
        #       expose :new_attribute, if: { version: 'v2' }
        #     end
        #   end
        def entity(*exposures, &block)
          entity_class.expose(*exposures) if exposures.any?
          entity_class.class_eval(&block) if block_given?
          entity_class
        end
      end

      # Instantiates an entity version of this object.
      def entity(options = {})
        self.class.entity_class.new(self, options)
      end
    end

    class << self
      def root_exposure
        @root_exposure ||= Exposure.new(nil, nesting: true)
      end

      attr_writer :root_exposure, :formatters

      # Returns all formatters that are registered for this and it's ancestors
      # @return [Hash] of formatters
      def formatters
        @formatters ||= {}
      end

      def hash_access
        @hash_access ||= :to_sym
      end

      def hash_access=(value)
        @hash_access =
          case value
          when :to_s, :str, :string
            :to_s
          else
            :to_sym
          end
      end

      def delegation_opts
        @delegation_opts ||= { hash_access: hash_access }
      end
    end

    @formatters = {}

    def self.inherited(subclass)
      subclass.root_exposure = root_exposure.dup
      subclass.formatters = formatters.dup

      super
    end

    # This method is the primary means by which you will declare what attributes
    # should be exposed by the entity.
    #
    # @option options :expose_nil When set to false the associated exposure will not
    #   be rendered if its value is nil.
    #
    # @option options :as Declare an alias for the representation of this attribute.
    #   If a proc is presented it is evaluated in the context of the entity so object
    #   and the entity methods are available to it.
    #
    # @example as: a proc or lambda
    #
    #   object = OpenStruct(awesomness: 'awesome_key', awesome: 'not-my-key', other: 'other-key' )
    #
    #   class MyEntity < Grape::Entity
    #     expose :awesome, as: proc { object.awesomeness }
    #     expose :awesomeness, as: ->(object, opts) { object.other }
    #   end
    #
    #   => { 'awesome_key': 'not-my-key', 'other-key': 'awesome_key' }
    #
    # Note the parameters passed in via the lambda syntax.
    #
    # @option options :if When passed a Hash, the attribute will only be exposed if the
    #   runtime options match all the conditions passed in. When passed a lambda, the
    #   lambda will execute with two arguments: the object being represented and the
    #   options passed into the representation call. Return true if you want the attribute
    #   to be exposed.
    # @option options :unless When passed a Hash, the attribute will be exposed if the
    #   runtime options fail to match any of the conditions passed in. If passed a lambda,<commit_msg>Fix typo in comments in lib/grape_entity/entity.rb (#350)<commit_after># frozen_string_literal: true

require 'multi_json'
require 'set'

module Grape
  # An Entity is a lightweight structure that allows you to easily
  # represent data from your application in a consistent and abstracted
  # way in your API. Entities can also provide documentation for the
  # fields exposed.
  #
  # @example Entity Definition
  #
  #   module API
  #     module Entities
  #       class User < Grape::Entity
  #         expose :first_name, :last_name, :screen_name, :location
  #         expose :field, documentation: { type: "string", desc: "describe the field" }
  #         expose :latest_status, using: API::Status, as: :status, unless: { collection: true }
  #         expose :email, if: { type: :full }
  #         expose :new_attribute, if: { version: 'v2' }
  #         expose(:name) { |model, options| [model.first_name, model.last_name].join(' ') }
  #       end
  #     end
  #   end
  #
  # Entities are not independent structures, rather, they create
  # **representations** of other Ruby objects using a number of methods
  # that are convenient for use in an API. Once you've defined an Entity,
  # you can use it in your API like this:
  #
  # @example Usage in the API Layer
  #
  #   module API
  #     class Users < Grape::API
  #       version 'v2'
  #
  #       desc 'User index', { params: API::Entities::User.documentation }
  #       get '/users' do
  #         @users = User.all
  #         type = current_user.admin? ? :full : :default
  #         present @users, with: API::Entities::User, type: type
  #       end
  #     end
  #   end
  class Entity
    attr_reader :object, :delegator, :options

    # The Entity DSL allows you to mix entity functionality into
    # your existing classes.
    module DSL
      def self.included(base)
        base.extend ClassMethods
        ancestor_entity_class = base.ancestors.detect { |a| a.entity_class if a.respond_to?(:entity_class) }
        base.const_set(:Entity, Class.new(ancestor_entity_class || Grape::Entity)) unless const_defined?(:Entity)
      end

      module ClassMethods
        # Returns the automatically-created entity class for this
        # Class.
        def entity_class(search_ancestors = true)
          klass = const_get(:Entity) if const_defined?(:Entity)
          klass ||= ancestors.detect { |a| a.entity_class(false) if a.respond_to?(:entity_class) } if search_ancestors
          klass
        end

        # Call this to make exposures to the entity for this Class.
        # Can be called with symbols for the attributes to expose,
        # a block that yields the full Entity DSL (See Grape::Entity),
        # or both.
        #
        # @example Symbols only.
        #
        #   class User
        #     include Grape::Entity::DSL
        #
        #     entity :name, :email
        #   end
        #
        # @example Mixed.
        #
        #   class User
        #     include Grape::Entity::DSL
        #
        #     entity :name, :email do
        #       expose :latest_status, using: Status::Entity, if: :include_status
        #       expose :new_attribute, if: { version: 'v2' }
        #     end
        #   end
        def entity(*exposures, &block)
          entity_class.expose(*exposures) if exposures.any?
          entity_class.class_eval(&block) if block_given?
          entity_class
        end
      end

      # Instantiates an entity version of this object.
      def entity(options = {})
        self.class.entity_class.new(self, options)
      end
    end

    class << self
      def root_exposure
        @root_exposure ||= Exposure.new(nil, nesting: true)
      end

      attr_writer :root_exposure, :formatters

      # Returns all formatters that are registered for this and it's ancestors
      # @return [Hash] of formatters
      def formatters
        @formatters ||= {}
      end

      def hash_access
        @hash_access ||= :to_sym
      end

      def hash_access=(value)
        @hash_access =
          case value
          when :to_s, :str, :string
            :to_s
          else
            :to_sym
          end
      end

      def delegation_opts
        @delegation_opts ||= { hash_access: hash_access }
      end
    end

    @formatters = {}

    def self.inherited(subclass)
      subclass.root_exposure = root_exposure.dup
      subclass.formatters = formatters.dup

      super
    end

    # This method is the primary means by which you will declare what attributes
    # should be exposed by the entity.
    #
    # @option options :expose_nil When set to false the associated exposure will not
    #   be rendered if its value is nil.
    #
    # @option options :as Declare an alias for the representation of this attribute.
    #   If a proc is presented it is evaluated in the context of the entity so object
    #   and the entity methods are available to it.
    #
    # @example as: a proc or lambda
    #
    #   object = OpenStruct(awesomeness: 'awesome_key', awesome: 'not-my-key', other: 'other-key' )
    #
    #   class MyEntity < Grape::Entity
    #     expose :awesome, as: proc { object.awesomeness }
    #     expose :awesomeness, as: ->(object, opts) { object.other }
    #   end
    #
    #   => { 'awesome_key': 'not-my-key', 'other-key': 'awesome_key' }
    #
    # Note the parameters passed in via the lambda syntax.
    #
    # @option options :if When passed a Hash, the attribute will only be exposed if the
    #   runtime options match all the conditions passed in. When passed a lambda, the
    #   lambda will execute with two arguments: the object being represented and the
    #   options passed into the representation call. Return true if you want the attribute
    #   to be exposed.
    # @option options :unless When passed a Hash, the attribute will be exposed if the
    #   runtime options fail to match any of the conditions passed in. If passed a lambda,
{'fraction_non_alphanumeric': 0.08571188010440346, 'fraction_numerical': 0.0007577671129072998, 'mean_word_length': 2.2365122615803816, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 7, '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': '7190148', 'n_tokens_mistral': 3464, 'n_tokens_neox': 3389, 'n_words': 1189}