<commit_before>require 'type_casters'

# The Setting class is an AR model that encapsulates a Settler setting. The key if the setting is the only required attribute.\
class Setting < ActiveRecord::Base  
  attr_readonly   :key
  attr_protected  :editable, :deletable, :deleted  
  
  before_update :ensure_editable
  
  validates_presence_of :key  
  validate :setting_validations
  
  serialize :value
  
  default_scope :conditions => ['deleted = ? or deleted IS NULL', false]
  named_scope :editable, :conditions => { :editable => true }
  named_scope :deletable, :conditions => { :deletable => true }  
  
  # Returns the value, typecasted if a typecaster is available.
  def value
    typecast.present? ? typecasted_value : super
  end
  
  # Reads the raw, untypecasted value.
  def untypecasted_value
    read_attribute(:value)
  end

  # Returns the typecasted value or the raw value if a typecaster could not be found.
  def typecasted_value
    typecaster.present? ? typecaster.typecast(untypecasted_value) : untypecasted_value
  end
  
  # Finds the typecast for this key in the settler configuration.
  def typecast
    @typecast ||= Settler.typecast_for(key)
  end
  
  # Returns all valid values for this setting, which is based on the presence of an inclusion validator.
  # Will return nil if no valid values could be determined.
  def valid_values
    if validators['inclusion']
      return case
        when validators['inclusion'].is_a?(Array) then validators['inclusion']
        when validators['inclusion'].is_a?(String) then validators['inclusion'].to_s.split(',').map{|v| v.to_s.strip }
        else nil
      end
    end
    nil
  end
  
  # Performs a soft delete of the setting if this setting is deletable. This ensures this setting is not recreated from the configuraiton file.
  # Returns false if the setting could not be destroyed.
  def destroy    
    if deletable?       
      self.deleted = true if Setting.update_all({ :deleted => true }, { :id => self })
      deleted?
    else 
      false
    end
  end
  
  # Can be used to get *all* settings, including deleted settings.
  def self.without_default_scope &block
    Setting.with_exclusive_scope(&block)
  end
  
  # Deleted scope is specified as a method as it needs to be an exclusive scope
  def self.deleted
    Setting.without_default_scope{ Setting.all :conditions => { :deleted => true } }
  end
  
protected

  # Performs instance validations as defined in the settler configuration.
  def setting_validations
    errors.add(:value, I18n.t(:blank, :scope => 'activerecord.errors.messages')) if validators['presence'] && ['1','true',true].include?(validators['presence']) && self.value.nil?
    errors.add(:value, I18n.t(:inclusion, :scope => 'activerecord.errors.messages')) if valid_values && !valid_values.include?(self.value)
    errors.add(:value, I18n.t(:format, :scope => 'activerecord.errors.messages')) if validators['format'] && !(Regexp.new(validators['format']) =~ self.value)
  end
  
  # Retrieves all validators defined for this setting.
  def validators
    @validators ||= Settler.validations_for(self.key)
  end
  
  # Retrieves the typecaster instance that will typecast the value of this setting.
  def typecaster
    @typecaster ||= Typecaster.typecaster_for(typecast)    
  end
  
  # Before_update filter to ensure uneditable settings cannot be updated.
  def ensure_editable; return false unless editable? end  
    
end<commit_msg>use 'invalid' AR error message for invalid format<commit_after>require 'type_casters'

# The Setting class is an AR model that encapsulates a Settler setting. The key if the setting is the only required attribute.\
class Setting < ActiveRecord::Base  
  attr_readonly   :key
  attr_protected  :editable, :deletable, :deleted  
  
  before_update :ensure_editable
  
  validates_presence_of :key  
  validate :setting_validations
  
  serialize :value
  
  default_scope :conditions => ['deleted = ? or deleted IS NULL', false]
  named_scope :editable, :conditions => { :editable => true }
  named_scope :deletable, :conditions => { :deletable => true }  
  
  # Returns the value, typecasted if a typecaster is available.
  def value
    typecast.present? ? typecasted_value : super
  end
  
  # Reads the raw, untypecasted value.
  def untypecasted_value
    read_attribute(:value)
  end

  # Returns the typecasted value or the raw value if a typecaster could not be found.
  def typecasted_value
    typecaster.present? ? typecaster.typecast(untypecasted_value) : untypecasted_value
  end
  
  # Finds the typecast for this key in the settler configuration.
  def typecast
    @typecast ||= Settler.typecast_for(key)
  end
  
  # Returns all valid values for this setting, which is based on the presence of an inclusion validator.
  # Will return nil if no valid values could be determined.
  def valid_values
    if validators['inclusion']
      return case
        when validators['inclusion'].is_a?(Array) then validators['inclusion']
        when validators['inclusion'].is_a?(String) then validators['inclusion'].to_s.split(',').map{|v| v.to_s.strip }
        else nil
      end
    end
    nil
  end
  
  # Performs a soft delete of the setting if this setting is deletable. This ensures this setting is not recreated from the configuraiton file.
  # Returns false if the setting could not be destroyed.
  def destroy    
    if deletable?       
      self.deleted = true if Setting.update_all({ :deleted => true }, { :id => self })
      deleted?
    else 
      false
    end
  end
  
  # Can be used to get *all* settings, including deleted settings.
  def self.without_default_scope &block
    Setting.with_exclusive_scope(&block)
  end
  
  # Deleted scope is specified as a method as it needs to be an exclusive scope
  def self.deleted
    Setting.without_default_scope{ Setting.all :conditions => { :deleted => true } }
  end
  
protected

  # Performs instance validations as defined in the settler configuration.
  def setting_validations
    errors.add(:value, I18n.t(:blank, :scope => 'activerecord.errors.messages')) if validators['presence'] && ['1','true',true].include?(validators['presence']) && self.value.nil?
    errors.add(:value, I18n.t(:inclusion, :scope => 'activerecord.errors.messages')) if valid_values && !valid_values.include?(self.value)
    errors.add(:value, I18n.t(:invalid, :scope => 'activerecord.errors.messages')) if validators['format'] && !(Regexp.new(validators['format']) =~ self.value)
  end
  
  # Retrieves all validators defined for this setting.
  def validators
    @validators ||= Settler.validations_for(self.key)
  end
  
  # Retrieves the typecaster instance that will typecast the value of this setting.
  def typecaster
    @typecaster ||= Typecaster.typecaster_for(typecast)    
  end
  
  # Before_update filter to ensure uneditable settings cannot be updated.
  def ensure_editable; return false unless editable? end  
    
end
{'fraction_non_alphanumeric': 0.08893365951935531, 'fraction_numerical': 0.0020146783709886315, 'mean_word_length': 3.658176943699732, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 27, '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': '5646320', 'n_tokens_mistral': 2100, 'n_tokens_neox': 2067, 'n_words': 680}