Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace Preneeds Virtus Models with POROs #18494

Merged
merged 23 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
beadb87
use new Parent Class
stevenjcumming Sep 17, 2024
a264aa0
proof of concept for replacing Virtus models
stevenjcumming Sep 18, 2024
e1caeb7
fix formatting
stevenjcumming Sep 18, 2024
b7ac0e6
use a class instance variable instead of class variable
stevenjcumming Sep 18, 2024
e2f01e8
linting
stevenjcumming Sep 18, 2024
4fddc3d
revert back to class variable for attributes
stevenjcumming Sep 18, 2024
76818e3
clean up and add comments
stevenjcumming Sep 18, 2024
923e223
Merge branch 'master' into sjc-preneeds-virtus-models
stevenjcumming Sep 18, 2024
74fe420
fix merge error
stevenjcumming Sep 18, 2024
fbd796b
move rubocop disable to base class
stevenjcumming Sep 18, 2024
b5cedbe
update the rest of the preneeds models
stevenjcumming Sep 18, 2024
41f653d
fix methods as default issue
stevenjcumming Sep 19, 2024
c7501c2
linting
stevenjcumming Sep 19, 2024
258d772
cast strings to boolean
stevenjcumming Sep 19, 2024
ae745a3
switch back to class instance methods
stevenjcumming Sep 19, 2024
8faf831
linting
stevenjcumming Sep 19, 2024
b9cbc6a
move boolean to core_extensions
stevenjcumming Sep 23, 2024
bce565a
fix spacing of comments
stevenjcumming Sep 23, 2024
bd8a0c5
linting
stevenjcumming Sep 23, 2024
587c138
add core_extensions initializer
stevenjcumming Sep 23, 2024
a3615aa
linting
stevenjcumming Sep 23, 2024
08f2aa6
Merge branch 'master' into sjc-preneeds-virtus-models
stevenjcumming Sep 23, 2024
7203641
remove core extension until common base is updated
stevenjcumming Sep 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,7 @@ config/initializers/clamav.rb @department-of-veterans-affairs/va-api-engineers @
config/initializers/combine_pdf_log_patch.rb @department-of-veterans-affairs/backend-review-group
config/initializers/config.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
config/initializers/cookie_rotation.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
config/initializers/core_extensions.rb @department-of-veterans-affairs/backend-review-group
config/initializers/covid_vaccine_facilities.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group @department-of-veterans-affairs/long-covid
config/initializers/datadog.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
config/initializers/date_formats.rb @department-of-veterans-affairs/octo-identity
Expand Down Expand Up @@ -864,6 +865,7 @@ lib/common/pdf_helpers.rb @department-of-veterans-affairs/benefits-decision-revi
lib/common/models @department-of-veterans-affairs/backend-review-group
lib/common/virus_scan.rb @department-of-veterans-affairs/backend-review-group
lib/common @department-of-veterans-affairs/backend-review-group
lib/core_extensions @department-of-veterans-affairs/backend-review-group
lib/debt_management_center @department-of-veterans-affairs/vsa-debt-resolution @department-of-veterans-affairs/backend-review-group
lib/decision_review @department-of-veterans-affairs/benefits-decision-reviews-be @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
lib/decision_review_v1 @department-of-veterans-affairs/benefits-decision-reviews-be @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
Expand Down
2 changes: 1 addition & 1 deletion app/models/preneeds/address.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Preneeds
# @!attribute postal_code
# @return [String] address postal code
#
class Address < Preneeds::VirtusBase
class Address < Preneeds::Base
attribute :street, String
attribute :street2, String
attribute :city, String
Expand Down
2 changes: 1 addition & 1 deletion app/models/preneeds/applicant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module Preneeds
# @!attribute name
# @return [Preneeds::FullName] applicant's name
#
class Applicant < Preneeds::VirtusBase
class Applicant < Preneeds::Base
attribute :applicant_email, String
attribute :applicant_phone_number, String
attribute :applicant_relationship_to_claimant, String
Expand Down
136 changes: 136 additions & 0 deletions app/models/preneeds/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# frozen_string_literal: true

# This will be moved after virtus is removed
module Boolean; end
class TrueClass; include Boolean; end
class FalseClass; include Boolean; end

# Parent class for other Preneeds Burial form related models
# Should not be initialized directly
#
module Preneeds
class Base
extend ActiveModel::Naming
include ActiveModel::Model
include ActiveModel::Serializers::JSON

@attributes = {}.freeze

class << self
# class variable attributes won't work so this is
# the only way for it to work. Thread safety shouldn't
# matter because @attributes is the same across all thread
# they are set by the class.
# rubocop:disable ThreadSafety/InstanceVariableInClassMethod
def attributes
@attributes ||= {}
end
# rubocop:enable ThreadSafety/InstanceVariableInClassMethod

# Class method to define a setter & getter for attribute
# this will also coerce a hash to the require class
# doesn't currently coerce scalar classes such as string to int
# In the future this could become it's own class e.g., Vets::Model::Attribute
#
# @param name [Symbol] the name of the attribute
# @param klass [Class] the class of the attribute
# @param default [String|Integer] the default value of the attribute
#
def attribute(name, klass, **options)
default = options[:default]
array = options[:array] || false

attributes[name] = { type: klass, default:, array: }

define_getter(name, default)
define_setter(name, klass, array)
end

def attribute_set
attributes.keys
end

private

def define_getter(name, default)
define_method(name) do
instance_variable_get("@#{name}") || begin
return nil unless defined?(default)

if default.is_a?(Symbol) && respond_to?(default)
send(default)
else
default
end
end
end
end

def define_setter(name, klass, array)
define_method("#{name}=") do |value|
if array
raise TypeError, "#{name} must be an Array" unless value.is_a?(Array)

value = value.map do |item|
item.is_a?(Hash) ? klass.new(item) : item
end

unless value.all? { |item| item.is_a?(klass) }
raise TypeError, "All elements of #{name} must be of type #{klass}"
end
end

value = ActiveModel::Type::Boolean.new.cast(value) if klass == Boolean

value = klass.new(value) if value.is_a?(Hash)

if (array && value.is_a?(Array)) || value.is_a?(klass) || value.nil?
instance_variable_set("@#{name}", value)
else
raise TypeError, "#{name} must be a #{klass}"
end
end
end
end

def initialize(params = {})
super
# Ensure all attributes have a defined value (default to nil)
self.class.attribute_set.each do |attr_name|
instance_variable_set("@#{attr_name}", nil) unless instance_variable_defined?("@#{attr_name}")
end
end

# Acts as ActiveRecord::Base#attributes which is needed for serialization
def attributes
nested_attributes(instance_values)
end

# Override `as_json`
#
# @param options [Hash]
#
# @see ActiveModel::Serializers::JSON
#
def as_json(options = {})
super(options).deep_transform_keys { |key| key.camelize(:lower) }
end

private

# Collect values from attribute and nested objects
#
# @param values [Hash]
#
# @return [Hash] nested attributes
def nested_attributes(values)
values.transform_values do |value|
if value.respond_to?(:instance_values)
nested_attributes(value.instance_values)
else
value
end
end
end
end
end
6 changes: 3 additions & 3 deletions app/models/preneeds/burial_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ module Preneeds
# @!attribute veteran
# @return [Preneeds::Veteran] Veteran object. Veteran is the person who is the owner of the benefit.
#
class BurialForm < Preneeds::VirtusBase
class BurialForm < Preneeds::Base
# Preneeds Burial Form official form id
#
FORM = '40-10007'

attribute :application_status, String, default: ''
attribute :preneed_attachments, Array[PreneedAttachmentHash]
attribute :preneed_attachments, PreneedAttachmentHash, array: true
attribute :has_currently_buried, String
attribute :sending_application, String, default: 'vets.gov'
attribute :sending_code, String, default: ''
attribute :sent_time, Common::UTCTime, default: :current_time
attribute :tracking_number, String, default: :generate_tracking_number
attribute :applicant, Preneeds::Applicant
attribute :claimant, Preneeds::Claimant
attribute :currently_buried_persons, Array[Preneeds::CurrentlyBuriedPerson]
attribute :currently_buried_persons, Preneeds::CurrentlyBuriedPerson, array: true
attribute :veteran, Preneeds::Veteran

# keeping this name because it matches the previous attribute
Expand Down
2 changes: 1 addition & 1 deletion app/models/preneeds/claimant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module Preneeds
# @!attribute address
# @return [Preneeds::Address] claimant's address
#
class Claimant < Preneeds::VirtusBase
class Claimant < Preneeds::Base
attribute :date_of_birth, String
attribute :desired_cemetery, String
attribute :email, String
Expand Down
2 changes: 1 addition & 1 deletion app/models/preneeds/currently_buried_person.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module Preneeds
# @!attribute name
# @return [Preneeds::FullName] currently buried person's full name
#
class CurrentlyBuriedPerson < Preneeds::VirtusBase
class CurrentlyBuriedPerson < Preneeds::Base
attribute :cemetery_number, String
attribute :name, Preneeds::FullName

Expand Down
2 changes: 1 addition & 1 deletion app/models/preneeds/date_range.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module Preneeds
# @!attribute to
# @return [String] 'to' date
#
class DateRange < Preneeds::VirtusBase
class DateRange < Preneeds::Base
attribute :from, String
attribute :to, String

Expand Down
2 changes: 1 addition & 1 deletion app/models/preneeds/full_name.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Preneeds
# @!attribute suffix
# @return [String] name suffix
#
class FullName < Preneeds::VirtusBase
class FullName < Preneeds::Base
attribute :first, String
attribute :last, String
attribute :maiden, String
Expand Down
2 changes: 1 addition & 1 deletion app/models/preneeds/preneed_attachment_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module Preneeds
# @!attribute name
# @return [String] attachment file name
#
class PreneedAttachmentHash < Preneeds::VirtusBase
class PreneedAttachmentHash < Preneeds::Base
attribute :confirmation_code, String
attribute :attachment_id, String
attribute :name, String
Expand Down
4 changes: 2 additions & 2 deletions app/models/preneeds/race.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Preneeds
class Race < Preneeds::VirtusBase
class Race < Preneeds::Base
ATTRIBUTE_MAPPING = {
'I' => :is_american_indian_or_alaskan_native,
'A' => :is_asian,
Expand All @@ -13,7 +13,7 @@ class Race < Preneeds::VirtusBase
}.freeze

ATTRIBUTE_MAPPING.each_value do |attr|
attribute(attr, Boolean)
attribute(attr, Boolean, default: false)
end

def as_eoas
Expand Down
6 changes: 3 additions & 3 deletions app/models/preneeds/service_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Preneeds
# @!attribute date_range
# @return [Preneeds::DateRange] service date range
#
class ServiceRecord < Preneeds::VirtusBase
class ServiceRecord < Preneeds::Base
attribute :service_branch, String
attribute :discharge_type, String
attribute :highest_rank, String
Expand All @@ -29,8 +29,8 @@ class ServiceRecord < Preneeds::VirtusBase
def as_eoas
hash = {
branchOfService: service_branch, dischargeType: discharge_type,
enteredOnDutyDate: date_range.try(:[], :from), highestRank: highest_rank,
nationalGuardState: national_guard_state, releaseFromDutyDate: date_range.try(:[], :to)
enteredOnDutyDate: date_range.try(:from), highestRank: highest_rank,
nationalGuardState: national_guard_state, releaseFromDutyDate: date_range.try(:to)
}

%i[
Expand Down
4 changes: 2 additions & 2 deletions app/models/preneeds/veteran.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ module Preneeds
# @!attribute service_records
# @return [Array<Preneeds::ServiceRecord>] veteran's service records
#
class Veteran < Preneeds::VirtusBase
class Veteran < Preneeds::Base
attribute :date_of_birth, String
attribute :date_of_death, String
attribute :gender, String
Expand All @@ -50,7 +50,7 @@ class Veteran < Preneeds::VirtusBase
attribute :address, Preneeds::Address
attribute :current_name, Preneeds::FullName
attribute :service_name, Preneeds::FullName
attribute :service_records, Array[Preneeds::ServiceRecord]
attribute :service_records, Preneeds::ServiceRecord, array: true

# (see Preneeds::BurialForm#as_eoas)
#
Expand Down
20 changes: 0 additions & 20 deletions app/models/preneeds/virtus_base.rb

This file was deleted.

2 changes: 1 addition & 1 deletion spec/requests/v0/preneeds/burial_forms_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

let(:submission_record) { OpenStruct.new(application_uuid: 'UUID') }
let(:form) do
Preneeds::BurialForm.new(params).tap do |f|
Preneeds::BurialForm.new(params[:application]).tap do |f|
f.claimant = Preneeds::Claimant.new(
email: 'foo@foo.com',
name: Preneeds::FullName.new(
Expand Down
Loading