<commit_before>class Family < ActiveRecord::Base

  include Authority::Abilities
  self.authorizer_name = 'FamilyAuthorizer'

  MAX_TO_BATCH_AT_A_TIME = 50

  has_many :people, -> { order(:sequence) }, dependent: :destroy
  has_many :updates, -> { order(:created_at) }
  accepts_nested_attributes_for :people
  belongs_to :site

  scope_by_site_id

  has_attached_file :photo, PAPERCLIP_PHOTO_OPTIONS

  scope :undeleted, -> { where(deleted: false) }
  scope :deleted, -> { where(deleted: true) }
  scope :has_printable_people, -> { where('(select count(*) from people where family_id = families.id and visible_on_printed_directory = ?) > 0', true) }

  validates_presence_of :name, :last_name
  validates_uniqueness_of :barcode_id, allow_nil: true, scope: [:site_id, :deleted], unless: Proc.new { |f| f.deleted? }
  validates_uniqueness_of :alternate_barcode_id, allow_nil: true, scope: [:site_id, :deleted], unless: Proc.new { |f| f.deleted? }
  validates_length_of :barcode_id, :alternate_barcode_id, in: 5..50, allow_nil: true
  validates_format_of :barcode_id, :alternate_barcode_id, with: /\A\d+\z/, allow_nil: true
  validates_attachment_size :photo, less_than: PAPERCLIP_PHOTO_MAX_SIZE
  validates_attachment_content_type :photo, content_type: PAPERCLIP_PHOTO_CONTENT_TYPES

  validates_each [:barcode_id, :alternate_barcode_id] do |record, attribute, value|
    if attribute.to_s == 'barcode_id' and record.barcode_id
      if record.barcode_id == record.alternate_barcode_id
        record.errors.add(attribute, :taken)
      elsif Family.where(alternate_barcode_id: record.barcode_id).count > 0
        record.errors.add(attribute, :taken)
      end
    elsif attribute.to_s == 'alternate_barcode_id' and record.alternate_barcode_id
      if Family.where(barcode_id: record.alternate_barcode_id).count > 0
        record.errors.add(attribute, :taken)
      end
    end
  end

  geocoded_by :location
  after_validation :geocode

  def barcode_id=(b)
    write_attribute(:barcode_id, b.to_s.strip.any? ? b : nil)
    write_attribute(:barcode_assigned_at, Time.now.utc)
  end

  def alternate_barcode_id=(b)
    write_attribute(:alternate_barcode_id, b.to_s.strip.any? ? b : nil)
    write_attribute(:barcode_assigned_at, Time.now.utc)
  end

  def address
    address1.to_s + (address2.present? ? "\n#{address2}" : '')
  end

  def mapable?
    latitude != 0.0 and longitude != 0.0
  end

  def location
    pretty_address if [address1, city, state].all?(&:present?)
  end

  # not HTML-escaped!
  def pretty_address
    a = ''
    a << address1.to_s   if address1.present?
    a << ", #{address2}" if address2.present?
    if city.present? and state.present?
      a << "\n#{city}, #{state}"
      a << "  #{zip}" if zip.present?
    end
  end

  def short_zip
    zip.to_s.split('-').first
  end

  self.digits_only_for_attributes = [:home_phone]

  def children_without_consent
    people.undeleted.reject(&:adult_or_consent?)
  end

  def visible_people
    people.undeleted.select do |person|
      !person.deleted? and (<commit_msg>Fix blank map showing for nil lat/lon.<commit_after>class Family < ActiveRecord::Base

  include Authority::Abilities
  self.authorizer_name = 'FamilyAuthorizer'

  MAX_TO_BATCH_AT_A_TIME = 50

  has_many :people, -> { order(:sequence) }, dependent: :destroy
  has_many :updates, -> { order(:created_at) }
  accepts_nested_attributes_for :people
  belongs_to :site

  scope_by_site_id

  has_attached_file :photo, PAPERCLIP_PHOTO_OPTIONS

  scope :undeleted, -> { where(deleted: false) }
  scope :deleted, -> { where(deleted: true) }
  scope :has_printable_people, -> { where('(select count(*) from people where family_id = families.id and visible_on_printed_directory = ?) > 0', true) }

  validates_presence_of :name, :last_name
  validates_uniqueness_of :barcode_id, allow_nil: true, scope: [:site_id, :deleted], unless: Proc.new { |f| f.deleted? }
  validates_uniqueness_of :alternate_barcode_id, allow_nil: true, scope: [:site_id, :deleted], unless: Proc.new { |f| f.deleted? }
  validates_length_of :barcode_id, :alternate_barcode_id, in: 5..50, allow_nil: true
  validates_format_of :barcode_id, :alternate_barcode_id, with: /\A\d+\z/, allow_nil: true
  validates_attachment_size :photo, less_than: PAPERCLIP_PHOTO_MAX_SIZE
  validates_attachment_content_type :photo, content_type: PAPERCLIP_PHOTO_CONTENT_TYPES

  validates_each [:barcode_id, :alternate_barcode_id] do |record, attribute, value|
    if attribute.to_s == 'barcode_id' and record.barcode_id
      if record.barcode_id == record.alternate_barcode_id
        record.errors.add(attribute, :taken)
      elsif Family.where(alternate_barcode_id: record.barcode_id).count > 0
        record.errors.add(attribute, :taken)
      end
    elsif attribute.to_s == 'alternate_barcode_id' and record.alternate_barcode_id
      if Family.where(barcode_id: record.alternate_barcode_id).count > 0
        record.errors.add(attribute, :taken)
      end
    end
  end

  geocoded_by :location
  after_validation :geocode

  def barcode_id=(b)
    write_attribute(:barcode_id, b.to_s.strip.any? ? b : nil)
    write_attribute(:barcode_assigned_at, Time.now.utc)
  end

  def alternate_barcode_id=(b)
    write_attribute(:alternate_barcode_id, b.to_s.strip.any? ? b : nil)
    write_attribute(:barcode_assigned_at, Time.now.utc)
  end

  def address
    address1.to_s + (address2.present? ? "\n#{address2}" : '')
  end

  def mapable?
    latitude.to_i != 0.0 and longitude.to_i != 0.0
  end

  def location
    pretty_address if [address1, city, state].all?(&:present?)
  end

  # not HTML-escaped!
  def pretty_address
    a = ''
    a << address1.to_s   if address1.present?
    a << ", #{address2}" if address2.present?
    if city.present? and state.present?
      a << "\n#{city}, #{state}"
      a << "  #{zip}" if zip.present?
    end
  end

  def short_zip
    zip.to_s.split('-').first
  end

  self.digits_only_for_attributes = [:home_phone]

  def children_without_consent
    people.undeleted.reject(&:adult_or_consent?)
  end

  def visible_people
    people.undeleted.select do |person|
      !person.deleted? and (
{'fraction_non_alphanumeric': 0.11515250366987441, 'fraction_numerical': 0.0065242211710977, 'mean_word_length': 4.157275021026073, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 19, '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': '2055669', 'n_tokens_mistral': 2253, 'n_tokens_neox': 2197, 'n_words': 442}