<commit_before>require 'volt/models/model_wrapper'
require 'volt/models/array_model'
require 'volt/models/model_helpers'
require 'volt/models/model_hash_behaviour'
require 'volt/models/validations'
require 'volt/models/model_state'
require 'volt/models/buffer'
require 'volt/models/field_helpers'
require 'volt/reactive/reactive_hash'
require 'volt/models/validators/user_validation'
require 'volt/models/dirty'

module Volt
  class NilMethodCall < NoMethodError
  end

  class Model
    include ModelWrapper
    include ModelHelpers
    include ModelHashBehaviour
    include Validations
    include ModelState
    include Buffer
    include FieldHelpers
    include UserValidatorHelpers
    include Dirty

    attr_reader :attributes
    attr_reader :parent, :path, :persistor, :options

    def initialize(attributes = {}, options = {}, initial_state = nil)
      @deps        = HashDependency.new
      @size_dep    = Dependency.new
      self.options = options

      send(:attributes=, attributes, true)

      # Models start in a loaded state since they are normally setup from an
      # ArrayModel, which will have the data when they get added.
      @state = :loaded

      @persistor.loaded(initial_state) if @persistor
    end

    # the id is stored in a field named _id, so we setup _id to proxy to this
    def _id
      @attributes && @attributes[:_id]
    end

    def _id=(val)
      self.__id = val
    end

    # Update the options
    def options=(options)
      @options     = options
      @parent      = options[:parent]
      @path        = options[:path] || []
      @class_paths = options[:class_paths]
      @persistor   = setup_persistor(options[:persistor])
    end

    # Assign multiple attributes as a hash, directly.
    def attributes=(attrs, initial_setup = false)
      @attributes = {}

      attrs = wrap_values(attrs)

      if attrs
        # Assign id first
        id       = attrs.delete(:_id)

        # When doing a mass-assign, we don't save until the end.
        Model.nosave do
          self._id = id if id

          # Assign each attribute using setters
          attrs.each_pair do |key, value|
            if self.respond_to?(:"#{key}=")
              # If a method without an underscore is defined, call that.
              send(:"#{key}=", value)
            else
              # Otherwise, use the _ version
              send(:"_#{key}=", value)
            end
          end
        end
      else
        @attributes = attrs
      end

      # Trigger and change all
      @deps.changed_all!
      @deps = HashDependency.new

      unless initial_setup

        # Let the persistor know something changed
        if @persistor
          # the changed method on a persistor should return a promise that will
          # be resolved when the save is complete, or fail with a hash of errors.
          return @persistor.changed
        end
      end
    end

    alias_method :assign_attributes, :attributes=

    # Pass the comparison through
    def ==(val)
      if val.is_a?(Model)
        # Use normal comparison for a model
        super
      else
        # Compare to attributes otherwise
        attributes == val
      end
    end

    # Pass through needed
    def !
      !attributes
    end

    def method_missing(method_name, *args, &block)
      if method_name[0] == '_'
        # Remove underscore
        method_name = method_name[1..-1]
        if method_name[-1] == '='
          # Assigning an attribute without the =
          assign_attribute(method_name[0..-2], args[0], &block)
        else
          read_attribute(method_name)
        end
      else
        # Call on parent
        super
      end
    end

    # Do the assignment to a model and trigger a changed event
    def assign_attribute(method_name, value, &block)
      self.expand!
      # Assign, without the =
      attribute_name = method_name.to_sym
<commit_msg>cleanup<commit_after>require 'volt/models/model_wrapper'
require 'volt/models/array_model'
require 'volt/models/model_helpers'
require 'volt/models/model_hash_behaviour'
require 'volt/models/validations'
require 'volt/models/model_state'
require 'volt/models/buffer'
require 'volt/models/field_helpers'
require 'volt/reactive/reactive_hash'
require 'volt/models/validators/user_validation'
require 'volt/models/dirty'

module Volt
  class NilMethodCall < NoMethodError
  end

  class Model
    include ModelWrapper
    include ModelHelpers
    include ModelHashBehaviour
    include Validations
    include ModelState
    include Buffer
    include FieldHelpers
    include UserValidatorHelpers
    include Dirty

    attr_reader :attributes
    attr_reader :parent, :path, :persistor, :options

    def initialize(attributes = {}, options = {}, initial_state = nil)
      @deps        = HashDependency.new
      @size_dep    = Dependency.new
      self.options = options

      send(:attributes=, attributes, true)

      # Models start in a loaded state since they are normally setup from an
      # ArrayModel, which will have the data when they get added.
      @state = :loaded

      @persistor.loaded(initial_state) if @persistor
    end

    # the id is stored in a field named _id, so we setup _id to proxy to this
    def _id
      @attributes && @attributes[:_id]
    end

    def _id=(val)
      self.__id = val
    end

    # Update the options
    def options=(options)
      @options     = options
      @parent      = options[:parent]
      @path        = options[:path] || []
      @class_paths = options[:class_paths]
      @persistor   = setup_persistor(options[:persistor])
    end

    # Assign multiple attributes as a hash, directly.
    def attributes=(attrs, initial_setup = false)
      @attributes = {}

      attrs = wrap_values(attrs)

      if attrs
        # Assign id first
        id       = attrs.delete(:_id)

        # When doing a mass-assign, we don't save until the end.
        Model.nosave do
          self._id = id if id

          # Assign each attribute using setters
          attrs.each_pair do |key, value|
            if self.respond_to?(:"#{key}=")
              # If a method without an underscore is defined, call that.
              send(:"#{key}=", value)
            else
              # Otherwise, use the _ version
              send(:"_#{key}=", value)
            end
          end
        end
      else
        @attributes = attrs
      end

      # Trigger and change all
      @deps.changed_all!
      @deps = HashDependency.new

      unless initial_setup

        # Let the persistor know something changed
        if @persistor
          # the changed method on a persistor should return a promise that will
          # be resolved when the save is complete, or fail with a hash of errors.
          return @persistor.changed
        end
      end
    end

    alias_method :assign_attributes, :attributes=

    # Pass the comparison through
    def ==(val)
      if val.is_a?(Model)
        # Use normal comparison for a model
        super
      else
        # Compare to attributes otherwise
        attributes == val
      end
    end

    # Pass through needed
    def !
      !attributes
    end

    def method_missing(method_name, *args, &block)
      if method_name[0] == '_'
        # Remove underscore
        method_name = method_name[1..-1]
        if method_name[-1] == '='
          # Assigning an attribute without the =
          assign_attribute(method_name[0..-2], args[0], &block)
        else
          read_attribute(method_name)
        end
      else
        # Call on parent
        super
      end
    end

    # Do the assignment to a model and trigger a changed event
    def assign_attribute(attribute_name, value, &block)
      self.expand!
      # Assign, without the =
      attribute_name = attribute_name.to_sym

{'fraction_non_alphanumeric': 0.07770961145194274, 'fraction_numerical': 0.0017893660531697342, 'mean_word_length': 2.192574459404325, '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': '5361843', 'n_tokens_mistral': 2203, 'n_tokens_neox': 2150, 'n_words': 694}