<commit_before>class Reading < ApplicationRecord
  belongs_to :sensor

  include Elasticsearch::Model
  include Elasticsearch::Model::Callbacks

  delegate :location, to: :sensor
  attr_accessor :force_alert

  after_create :create_notification, unless: Proc.new { self.humidity > 100 || Notification.for_sensor(self.sensor).exists? } # Check for excess humidity to ignore error readings

  def as_indexed_json(options={})
    room = sensor.room
    location = room.location
    floor = room.floor
    organization = location.organization

    self.as_json.merge(
      sensor_name: sensor.name,
      room_name: room.name,
      location_name: location.name,
      organization_name: organization.name,
      floor: floor.name)
  end

  def create_notification
    return Notification.create(
      sensor: self.sensor,
      reading: self,
      notification_trigger: NotificationTrigger.manual_trigger_for_location(self.location)
    ) if self.force_alert.present?

    NotificationTrigger.not_manual
      .for_location(self.location)
      .select { |t| t.triggered_for_reading?(self) }
      .each do |t|
      Notification.create(
        sensor: self.sensor,
        reading: self,
        notification_trigger: t
      )
    end
  end
end
<commit_msg>Validate reading before saving<commit_after>class Reading < ApplicationRecord
  belongs_to :sensor

  include Elasticsearch::Model
  include Elasticsearch::Model::Callbacks

  delegate :location, to: :sensor
  attr_accessor :force_alert

  after_create :create_notification, unless: Proc.new { Notification.for_sensor(self.sensor).exists? }

  validates :humidity, numericality: { :less_than_or_equal_to => 100 }

  def as_indexed_json(options={})
    room = sensor.room
    location = room.location
    floor = room.floor
    organization = location.organization

    self.as_json.merge(
      sensor_name: sensor.name,
      room_name: room.name,
      location_name: location.name,
      organization_name: organization.name,
      floor: floor.name)
  end

  def create_notification
    return Notification.create(
      sensor: self.sensor,
      reading: self,
      notification_trigger: NotificationTrigger.manual_trigger_for_location(self.location)
    ) if self.force_alert.present?

    NotificationTrigger.not_manual
      .for_location(self.location)
      .select { |t| t.triggered_for_reading?(self) }
      .each do |t|
      Notification.create(
        sensor: self.sensor,
        reading: self,
        notification_trigger: t
      )
    end
  end
end

{'fraction_non_alphanumeric': 0.08487958941966048, 'fraction_numerical': 0.002368732727990525, 'mean_word_length': 3.346483704974271, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, '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': '472610', 'n_tokens_mistral': 756, 'n_tokens_neox': 721, 'n_words': 162}