Rails Console Code Snippets - department-of-veterans-affairs/caseflow GitHub Wiki

Rails Console Code Snippets

In support of handling Bat Team support tickets, onboarding new teammates to Caseflow products, and general data investigation, this page provides a collection of code snippets that you can run in the Rails console to get a quick view of records and their associations (similar to structure_render and treee but on a wider range of record types).

See FinderConsoleMethods and ProductionConsoleMethods for helper methods.

To use these snippets, paste the method definitions into your console or add them to your .pryrc and call the methods as needed (my_repl.rb is an example and offers different options).

  • Methods like user or appeal provide easier ways to retrieve the desired records.
  • The p_ prefix for many of the methods means "print" to the console.
  • In the future, these snippets could be incorporated into the codebase (as monkey-patches) and enabled with a special incantation, but for now you'll have to copy and paste.

These methods can always be improved, so please contribute your knowledge of useful methods that can be called for each model.

General helper methods

# Prints history of commands in the irb REPL
def hist
  puts *(Readline::HISTORY.to_a)
end

def uuid?(uuid)
  uuid_regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
  uuid_regex.match?(uuid.to_s.downcase)
end

# Suppress SQL queries to reduce console clutter
def quietly
  saved_logger_level = ActiveRecord::Base.logger.level
  ActiveRecord::Base.logger.level = :warn
  ret_value = yield
  ActiveRecord::Base.logger.level = saved_logger_level
  ret_value
end

def could_be_ssn?(ssn)
  ssn =~ /^[0-8]\d{8}$/
end

Person

def p_vet(id)
  vet=Veteran.find_by_file_number_or_ssn(id)
  
  crs=ClaimReview.find_all_visible_by_file_number(vet.file_number)
  crs.each{|cr| p_claim_review(cr)}
  
  appeals=AppealFinder.find_appeals_with_file_numbers(vet.file_number)
  appeals.each{|a| p_appeal(a)}

  vet
end

# user 3
# user "BvaAAbshire"
# user 'ABS'
def user(id)
  user=User.find(id) if id.is_a? Numeric
  return user if user
  
  user=User.find_by(css_id: id.upcase) if id.is_a? String
  return user if user

  staff=VACOLS::Staff.find_by(slogid: id.upcase)
  return User.find_by(css_id: staff.sdomainid) if staff

  users = User.where("UPPER(full_name) LIKE ?", "%#{id.upcase}%")
  return users.first if users.count==1
  puts "Found #{users.count} users with full_name like %#{id.upcase}%: #{users.map{|u| [u.css_id, u.full_name]}}"
end
  
# p_user user "BvaAAbshire"
def p_user(obj)
  user = obj if obj.is_a?(User)
  user = user(obj) if user.nil?
  
  puts UserRepository.user_info_from_vacols(user.css_id)
  puts UserRepository.user_info_for_idt(user.css_id)
  
  puts VACOLS::Staff.find_by_sdomainid(user.css_id)&.attributes
  
  # Can also run this on the command line such as 
  # `CSS_ID=BVAAABSHIRE bundle exec rake users:footprint`
  pp UserReporter.new(user.css_id).report
  user
end

# authenticate user
def auth_user(user)
  RequestStore[:current_user]=user
  # https://github.com/department-of-veterans-affairs/caseflow/wiki/Debugging-Tips#authenticating-in-the-rails-console
  User.authentication_service.user_session = User.authentication_service.get_user_session(user.id)
end

Appeal

If desired, you can monkey-patch classes to add these methods to the class themselves like so:

class Appeal
  def p
    quietly do
      self.treee
      
      AttorneyCaseReview.find_by(task_id: self.tasks.pluck(:id)).tap {|acr| puts acr&.inspect }

      JudgeCaseReview.find_by(task_id: self.tasks.pluck(:id)).tap {|jcr| puts "  #{jcr&.inspect}"}
    end
  end
end

or simply use them as utility methods:

# appeal "1c11a1ae-43bd-449b-9416-7ccb9cb06c11"
# appeal 1234567
def appeal(obj)
  appeal = obj if obj.is_a?(Appeal) || obj.is_a?(LegacyAppeal)
  appeal = uuid?(obj) ? Appeal.find_by(uuid: obj) : LegacyAppeal.find_by(vacols_id: obj) if appeal.nil?
end

# p_appeal appeal "f3c20696-9c28-4213-bcc3-cba93b6e6184"
def p_appeal(appeal)
  quietly do
    appeal.treee

    if appeal.is_a? LegacyAppeal
      p_legacy_appeal(appeal)
    end
    
    AttorneyCaseReview.find_by(task_id: appeal.tasks.pluck(:id)).tap {|acr| puts acr&.inspect }
    
    JudgeCaseReview.find_by(task_id: appeal.tasks.pluck(:id)).tap {|jcr| puts "  #{jcr&.inspect}"}
    
    puts "---- #{appeal.hearings.count} Hearings"
    appeal.hearings.each{|hearing|
      p_hearing(hearing) 
    } if defined? p_hearing
    
    ris=appeal.issues[:request_issues]
    puts "---- #{ris.count} Request Issues"
    p_request_issues(ris) if defined? p_request_issues

    rius = RequestIssuesUpdate.where(review: appeal)
    puts "---- #{rius.count} Request Issues Update"
    rius.each_with_index{|riu,i|
      p_request_issue_update(riu,i)
    } if defined? p_request_issue_update

    appeal
  end
end

# p_appeal appeal 3085659
def p_legacy_appeal(appeal)
  quietly do
    tasks=LegacyWorkQueue.tasks_by_appeal_id(appeal.vacols_id)
    puts "____________________"
    puts "---- Legacy Tasks"
    tasks.map do |t|
      puts "#{t.class.name}, assigned_by: #{t.assigned_by&.inspect} #{t.assigned_by&.sdomainid}, assigned_to: #{t.assigned_to&.inspect} #{t.assigned_to&.sdomainid}, at: #{t.assigned_at}\n"
    rescue
      puts "#{t.class.name}, assigned_by: #{t.assigned_by&.inspect}, assigned_to: #{t.assigned_to&.inspect}, at: #{t.assigned_at}\n"
    end

    puts "---- Prior Locations"
    puts "changed_at, change_to, changed_by, prior_loc"
    pp appeal.location_history.pluck(:locdout, :locstto, :locstrcv, :locstout)
    puts "^^^^^^^^^^^^^^^^^^^^"
    tasks
  end
end

Legacy appeal

def legacy_appeals_by_file_number(fn)
  LegacyAppeal.fetch_appeals_by_file_number(fn)
end

def legacies(fn)
  LegacyAppeal.fetch_appeals_by_file_number(fn).map{|l| {nod: l.nod_date, soc: l.soc_date, ssoc: l.ssoc_dates, vacols_id: l.vacols_id, disposition: l.disposition}}
end

# Find a specific legacy appeal
def legacy(vacols_id)
  LegacyAppeal.find_or_create_by_vacols_id(vacols_id)
end

# Get the data for a specific vacols issue, useful for validating results after making manual updates,
# because otherwise the issue will be memoized and may not show the current status
def vacols_issue(vacols_id, vacols_sequence_id)
  return unless vacols_id && vacols_sequence_id

  @vacols_issue ||= AppealRepository.issues(vacols_id).find do |issue|
    issue.vacols_sequence_id == vacols_sequence_id
  end
end

Hearing

def hearing(id)
  Hearing.find_hearing_by_uuid_or_vacols_id(id)
end

# p_appeal appeal "3ee973ab-467e-46c6-9b0b-7c83e11ecd6c"
# p_hearing hearing "cbdde413-1461-4a64-a82e-06e8df147c2c"
def p_hearing(hearing)
  quietly do
    puts hearing.inspect
    puts "    Day:#{[hearing.hearing_day.scheduled_for, hearing.hearing_day.request_type, hearing.hearing_day.regional_office]}, Judge:#{[hearing.judge.css_id, hearing.judge.full_name]}"

    p_legacy_hearing(hearing) if hearing.is_a? LegacyHearing
  end
end

def p_legacy_hearing(hearing)
  puts "TBD"
end

RequestIssue

def p_request_issues(ris)
  quietly do
    dis=ris.first.decision_review.decision_issues
    puts "---- #{ris.count} RequestIssues with #{dis.count} DecisionIssues"
    ris.order(:id).each_with_index{|ri,i| 
      p_request_issue(ri, i)
    }.map(&:to_s)
    dis
    puts "^^^^^^^^^^^^^^^^^^^^"
  end
end

def p_request_issue(r, i=0)
  puts "#{i+1}. Request #{r.id}: #{[r.closed_status, r.contested_rating_issue_diagnostic_code, r.benefit_type, r.contested_issue_description].to_s}"
  r.decision_issues.order(:id).each_with_index{|di,i2|
    p_decision_issue(di,i2)
  }
end

def p_decision_issue(di, i=0)
  puts "    * Decision #{di.id}: #{[di.disposition, di.diagnostic_code, di.caseflow_decision_date, di.description]}"
end

def p_request_issue_update(riu,i=0)
  puts "#{i+1}. RequestIssueUpdate #{riu.id}: #{[riu.review_id, riu.before_request_issue_ids, riu.after_request_issue_ids, riu.processed_at].to_s}"
end

ClaimReview

def claim_review(id)
  return [HigherLevelReview, SupplementalClaim].each{|clazz| 
    r=clazz.find_by(uuid: id)
    return r if r
  } if uuid?(id)
  
  # if id is a claim ID
  return [HigherLevelReview, SupplementalClaim].each{|clazz| 
    epe=EndProductEstablishment.find_by(reference_id: id, source_type: clazz.to_s)
    return epe.source if epe
  }
end

def p_claim_review(cr)
  puts cr.inspect
  puts cr.establishment_error
  puts "Intake completed at: " + cr.establishment_submitted_at
end

EndProductEstablishment

def p_epe(epe)
  output = ""
  output << "=== #{epe.id} ==="
  src = epe.source
  output << "    > #{src.class.name} #{src.id}"
  output << "    > empty decision issues? #{src.decision_issues.empty?} ?? true"
  output << "    > has #{src.end_product_establishments.count} epes"
  src.end_product_establishments.each do |e|
    output << "    >> epe #{e.id}, request_issues.count: #{e.request_issues.count}, synced_status: #{e.synced_status} ?? CLR, last_synced_at: #{e.last_synced_at}"
    e.request_issues.each do |ri|
      output << "    >>> ri.contention_disposition.nil? #{ri.contention_disposition.nil?} ?? true"
    end
  end
  puts output.join('\n')
end
⚠️ **GitHub.com Fallback** ⚠️