<commit_before>require 'active_remote/rpc'

module ActiveRemote
  module Persistence
    extend ActiveSupport::Concern

    included do
      include RPC

      # Allow users to create callbacks around a `save` call.
      #
      define_model_callbacks :save, :create, :update

      # Before a save occurs, ensure that we
      # clear out the errors list.
      #
      set_callback :save, :before do |remote|
        remote.errors.clear
      end
    end

    module ClassMethods

      # Creates a remote record through the service.
      #
      # The service will run any validations and if any of them fail, will return
      # the record error messages indicating what went wrong.
      #
      # The newly created record is returned if it was successfully saved or not.
      #
      def create(attributes)
        remote = self.new(attributes)
        remote.save
        remote
      end

      # Creates a remote record through the service and if successful, returns
      # the newly created record.
      #
      # The service will run any validations and if any of them fail, will raise
      # an ActiveRemote::RemoteRecordNotSaved exception.
      #
      def create!(attributes)
        remote = self.new(attributes)
        remote.save!
        remote
      end

      # Instantiate a record with the given remote attributes. Generally used
      # when retrieving records that already exist, so @new_record is set to false.
      #
      def instantiate(attributes, options = {})
        new_object = self.new.instantiate(attributes)
        new_object.readonly! if options[:readonly]

        new_object
      end

      # Mark the class as readonly. Overrides instance-level readonly, making
      # any instance of this class readonly.
      def readonly!
        @readonly = true
      end

      # Returns true if the class is marked as readonly; otherwise, returns false.
      def readonly?
        @readonly
      end
    end

    # Deletes the record from the service (the service determines if the
    # record is hard or soft deleted) and freezes this instance to indicate
    # that no changes should be made (since they can't be persisted). If the
    # record was not deleted, it will have error messages indicating what went
    # wrong. Returns the frozen instance.
    #
    def delete
      raise ReadOnlyRemoteRecord if readonly?
      response = rpc.execute(:delete, scope_key_hash)

      add_errors(response.errors) if response.respond_to?(:errors)

      return success? ? freeze : false
    end

    # Deletes the record from the service (the service determines if the
    # record is hard or soft deleted) and freezes this instance to indicate
    # that no changes should be made (since they can't be persisted). If the
    # record was not deleted, an exception will be raised. Returns the frozen
    # instance.
    #
    def delete!
      delete
      raise ActiveRemoteError.new(errors.to_s) if has_errors?
    end

    # Destroys (hard deletes) the record from the service and freezes this
    # instance to indicate that no changes should be made (since they can't
    # be persisted). If the record was not deleted, it will have error
    # messages indicating what went wrong. Returns the frozen instance.
    #
    def destroy
      raise ReadOnlyRemoteRecord if readonly?
      response = rpc.execute(:destroy, scope_key_hash)

      add_errors(response.errors) if response.respond_to?(:errors)

      return success? ? freeze : false
    end

    # Destroys (hard deletes) the record from the service and freezes this
    # instance to indicate that no changes should be made (since they can't
    # be persisted). If the record was not deleted, an exception will be
    # raised. Returns the frozen instance.
    #
    def destroy!
      destroy
      raise ActiveRemoteError.new(errors.to_s) if has_errors?
    end

    # Returns true if the record has errors; otherwise, returns false.
    #
    def has_errors?
      return respond_to?(:errors) && errors.present?
    end

    # Instantiate a record with the given remote attributes. Generally used
    # when retrieving records that already exist, so @new_record is set to false.
    #
    def instantiate(record)
      skip_dirty_tracking do
        assign_attributes(record)
      end

      # TODO: figure out how to safely run after_find/search callbacks here
      # currently, several functions use this code path, so an alternate path
      # may need to be added

      run_callbacks :initialize

      @new_record = false
      self
    end

    # Returns true if the remote record hasn't been saved yet; otherwise,
    # returns false.
    #
    def new_record?
      @new_record
    end

    # Returns true if the remote record has been saved; otherwise, returns false.
    #<commit_msg>instantiate needs to be responsible for setting up @attributes hash<commit_after>require 'active_remote/rpc'

module ActiveRemote
  module Persistence
    extend ActiveSupport::Concern

    included do
      include RPC

      # Allow users to create callbacks around a `save` call.
      #
      define_model_callbacks :save, :create, :update

      # Before a save occurs, ensure that we
      # clear out the errors list.
      #
      set_callback :save, :before do |remote|
        remote.errors.clear
      end
    end

    module ClassMethods

      # Creates a remote record through the service.
      #
      # The service will run any validations and if any of them fail, will return
      # the record error messages indicating what went wrong.
      #
      # The newly created record is returned if it was successfully saved or not.
      #
      def create(attributes)
        remote = self.new(attributes)
        remote.save
        remote
      end

      # Creates a remote record through the service and if successful, returns
      # the newly created record.
      #
      # The service will run any validations and if any of them fail, will raise
      # an ActiveRemote::RemoteRecordNotSaved exception.
      #
      def create!(attributes)
        remote = self.new(attributes)
        remote.save!
        remote
      end

      # Instantiate a record with the given remote attributes. Generally used
      # when retrieving records that already exist, so @new_record is set to false.
      #
      def instantiate(attributes, options = {})
        new_object = self.new.instantiate(attributes)
        new_object.readonly! if options[:readonly]

        new_object
      end

      # Mark the class as readonly. Overrides instance-level readonly, making
      # any instance of this class readonly.
      def readonly!
        @readonly = true
      end

      # Returns true if the class is marked as readonly; otherwise, returns false.
      def readonly?
        @readonly
      end
    end

    # Deletes the record from the service (the service determines if the
    # record is hard or soft deleted) and freezes this instance to indicate
    # that no changes should be made (since they can't be persisted). If the
    # record was not deleted, it will have error messages indicating what went
    # wrong. Returns the frozen instance.
    #
    def delete
      raise ReadOnlyRemoteRecord if readonly?
      response = rpc.execute(:delete, scope_key_hash)

      add_errors(response.errors) if response.respond_to?(:errors)

      return success? ? freeze : false
    end

    # Deletes the record from the service (the service determines if the
    # record is hard or soft deleted) and freezes this instance to indicate
    # that no changes should be made (since they can't be persisted). If the
    # record was not deleted, an exception will be raised. Returns the frozen
    # instance.
    #
    def delete!
      delete
      raise ActiveRemoteError.new(errors.to_s) if has_errors?
    end

    # Destroys (hard deletes) the record from the service and freezes this
    # instance to indicate that no changes should be made (since they can't
    # be persisted). If the record was not deleted, it will have error
    # messages indicating what went wrong. Returns the frozen instance.
    #
    def destroy
      raise ReadOnlyRemoteRecord if readonly?
      response = rpc.execute(:destroy, scope_key_hash)

      add_errors(response.errors) if response.respond_to?(:errors)

      return success? ? freeze : false
    end

    # Destroys (hard deletes) the record from the service and freezes this
    # instance to indicate that no changes should be made (since they can't
    # be persisted). If the record was not deleted, an exception will be
    # raised. Returns the frozen instance.
    #
    def destroy!
      destroy
      raise ActiveRemoteError.new(errors.to_s) if has_errors?
    end

    # Returns true if the record has errors; otherwise, returns false.
    #
    def has_errors?
      return respond_to?(:errors) && errors.present?
    end

    # Instantiate a record with the given remote attributes. Generally used
    # when retrieving records that already exist, so @new_record is set to false.
    #
    def instantiate(record)
      @attributes ||= begin
        attribute_names = self.class.attribute_names
        Hash[attribute_names.map { |key| [key, nil] }]
      end

      skip_dirty_tracking do
        assign_attributes(record)
      end

      # TODO: figure out how to safely run after_find/search callbacks here
      # currently, several functions use this code path, so an alternate path
      # may need to be added

      run_callbacks :initialize

      @new_record = false
      self
    end

    # Returns true if the remote record hasn't been saved yet; otherwise,
    # returns false.
    #
    def new_record?
      @new_record
    end

    # Returns true if the remote record has been saved; otherwise, returns false.
    #
{'fraction_non_alphanumeric': 0.05517662628524891, 'fraction_numerical': 0.0, 'mean_word_length': 2.527468581687612, 'pattern_counts': {'":': 0, '<': 3, '<?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': '2208980', 'n_tokens_mistral': 2559, 'n_tokens_neox': 2458, 'n_words': 1108}