<commit_before>class Answer < ActiveRecord::Base
  include Deletable

  STATE = %(incomplete complete migrated locked)

  has_many :answer_values, -> { where deleted: false }, dependent: :destroy
  belongs_to :question
  belongs_to :answer_option
  belongs_to :answer_session
  has_one :in_edge, class_name: "AnswerEdge", foreign_key: "child_answer_id", dependent: :destroy
  has_one :out_edge, class_name: "AnswerEdge", foreign_key: "parent_answer_id", dependent: :destroy
  belongs_to :user # When necessary

  # Scopes
  scope :incomplete, -> { where(state: 'incomplete')}
  scope :migrated, -> { where(state: 'migrated')}
  scope :complete, -> { where(state: ['complete', 'locked'])}
  scope :locked, -> { where(state: 'locked')}

  # Class Methods
  def self.first_answer(question, answer_session)
    Answer.current.where(question_id: question.id, answer_session_id: answer_session.id).first
  end

  def self.first_or_new(question, answer_session)
    self.first_answer(question, answer_session) || Answer.new(question_id: question.id, answer_session_id: answer_session.id)
  end

  # Instance Methods


  ## Value Methods
  ## Different options:
  # It gets complicated with many answer templates
  #   at most basic, one answer template with not allowed multiple ==> target field gets value
  #   then, one answer templates with allowed multiple ==> builds from array of values
  #
  #   we repeat this for all answer templates
  #
  #   the inputs can be single value, array of values, hash with answer templates as keys
  #   if multiple answer templates are present, then hash is NECESSARY

  # single value, raw value!
  # single value, answer option id (multiple_choice)
  # Multiple Values, answer option id (check_box)
  # (not supported now) multiple values,

  def value=(val)
    if locked?
      logger.warn "Attempting to change value of locked answer: survey: #{answer_session.survey.slug} | question: #{question.slug} | user: #{answer_session.user.email} | encounter: #{answer_session.encounter}"
      return nil
    end

    self[:preferred_not_to_answer] = (val.delete('preferred_not_to_answer') ? true : false)
<commit_msg>Fixed bug where empty checkbox questions were causing an error, closing #442<commit_after>class Answer < ActiveRecord::Base
  include Deletable

  STATE = %(incomplete complete migrated locked)

  has_many :answer_values, -> { where deleted: false }, dependent: :destroy
  belongs_to :question
  belongs_to :answer_option
  belongs_to :answer_session
  has_one :in_edge, class_name: "AnswerEdge", foreign_key: "child_answer_id", dependent: :destroy
  has_one :out_edge, class_name: "AnswerEdge", foreign_key: "parent_answer_id", dependent: :destroy
  belongs_to :user # When necessary

  # Scopes
  scope :incomplete, -> { where(state: 'incomplete')}
  scope :migrated, -> { where(state: 'migrated')}
  scope :complete, -> { where(state: ['complete', 'locked'])}
  scope :locked, -> { where(state: 'locked')}

  # Class Methods
  def self.first_answer(question, answer_session)
    Answer.current.where(question_id: question.id, answer_session_id: answer_session.id).first
  end

  def self.first_or_new(question, answer_session)
    self.first_answer(question, answer_session) || Answer.new(question_id: question.id, answer_session_id: answer_session.id)
  end

  # Instance Methods


  ## Value Methods
  ## Different options:
  # It gets complicated with many answer templates
  #   at most basic, one answer template with not allowed multiple ==> target field gets value
  #   then, one answer templates with allowed multiple ==> builds from array of values
  #
  #   we repeat this for all answer templates
  #
  #   the inputs can be single value, array of values, hash with answer templates as keys
  #   if multiple answer templates are present, then hash is NECESSARY

  # single value, raw value!
  # single value, answer option id (multiple_choice)
  # Multiple Values, answer option id (check_box)
  # (not supported now) multiple values,

  def value=(val)
    # Deal with nil values, generated by empty checkbox questions
    val = {} if val.nil?

    if locked?
      logger.warn "Attempting to change value of locked answer: survey: #{answer_session.survey.slug} | question: #{question.slug} | user: #{answer_session.user.email} | encounter: #{answer_session.encounter}"
      return nil
    end

    self[:preferred_not_to_answer] = (val.delete('preferred_not_to_answer') ? true : false)

{'fraction_non_alphanumeric': 0.09988776655443322, 'fraction_numerical': 0.0006734006734006734, 'mean_word_length': 4.494451294697904, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 17, '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': '4199577', 'n_tokens_mistral': 1324, 'n_tokens_neox': 1300, 'n_words': 423}