Class: HasHelpers::ResourceImporter
- Inherits:
-
Object
- Object
- HasHelpers::ResourceImporter
- Defined in:
- lib/has_helpers/resource_importer.rb
Constant Summary collapse
- AuditError =
Class.new(::StandardError)
- AUDIT_MISSING_RESOURCES =
"Application: %{application_name}, Resources: %{resources} were flagged during an audit. The resources may need to be migrated to match a new name or removed as the case may require."- AUDIT_MISSING_NESTED_RESOURCES =
"Application: %{application_name}, Resource: %{resource_name}, Nested_resources: %{nested_resources} were flagged during an audit. The nested resources may need to be migrated to match a new name or removed as the case may require."
Instance Attribute Summary collapse
-
#mem_resources ⇒ Object
Memoize already read resources.
Class Method Summary collapse
- .create_importable_resources_for(resource, application) ⇒ Object
- .import_resources(*applications, audit: true) ⇒ Object
Instance Method Summary collapse
- #add_field_resources(resource) ⇒ Object
- #add_nested_resources(resource) ⇒ Object
- #audit_nested_resources(resource) ⇒ Object
- #audit_resources(application) ⇒ Object
-
#create_branch_resource(resource) ⇒ Object
check if the branch already has the resource and if not save it This is to avoid infinite recursion with resources in case of a circular reference such as A -> B -> C -> A e.g., Hierarchy contains a Hierarchy and that a Hierarchy and so on...
- #create_importable_resources_for(resource, application) ⇒ Object
- #import_nested_resources!(audit: true) ⇒ Object
- #import_resource_nested_resources(resource, audit: true) ⇒ Object
- #import_resources(audit: true) ⇒ Object
- #import_resources!(audit: true) ⇒ Object
-
#initialize(*applications) ⇒ ResourceImporter
constructor
A new instance of ResourceImporter.
- #lacks_of_nested_resources(resource) ⇒ Object
Constructor Details
#initialize(*applications) ⇒ ResourceImporter
Returns a new instance of ResourceImporter.
19 20 21 22 23 24 |
# File 'lib/has_helpers/resource_importer.rb', line 19 def initialize(*applications) @applications = applications.presence @mem_resources ||= [] @ancestors ||= {} @descendants ||= {} end |
Instance Attribute Details
#mem_resources ⇒ Object
Memoize already read resources. Hash containing the resource, its ancestors, and descendants
5 6 7 |
# File 'lib/has_helpers/resource_importer.rb', line 5 def mem_resources @mem_resources end |
Class Method Details
.create_importable_resources_for(resource, application) ⇒ Object
15 16 17 |
# File 'lib/has_helpers/resource_importer.rb', line 15 def self.create_importable_resources_for(resource, application) new(application).create_importable_resources_for(resource, application) end |
.import_resources(*applications, audit: true) ⇒ Object
11 12 13 |
# File 'lib/has_helpers/resource_importer.rb', line 11 def self.import_resources(*applications, audit: true) self.new(*applications).import_resources(audit: audit) end |
Instance Method Details
#add_field_resources(resource) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/has_helpers/resource_importer.rb', line 71 def add_field_resources(resource) # Create fields resources for the resource with BelongsToReflection associations if resource.klass(safe: true) && resource.klass.respond_to?(:table_exists?) && resource.klass.table_exists? = (resource.klass) associations = .associations.select { |_, value| value[:assoc_type] == "BelongsToReflection" } resource.klass.columns.each do |column| resource_type = column.null ? ::HasHelpers::ResourceType::FIELD : ::HasHelpers::ResourceType::REQUIRED_FIELD association_class = associations[column.name] ? associations[column.name][:class_name] : nil field_resource_id = nil if association_class && association_class.safe_constantize field_resource_id = HasHelpers::Resource.find_by(name: association_class, parent_id: nil, application: resource.application)&.id if association_class.constantize < ::Option field_resource_id = ::HasHelpers::Resource.find_by(name: "Option", parent_id: nil, application: resource.application)&.id end end HasHelpers::Resource.find_or_create_by( resource_type: resource_type, application: resource.application, parent_id: resource.id, name: column.name, field_resource_id: field_resource_id, alias_name: column.name, field_class_name: association_class ) end end end |
#add_nested_resources(resource) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/has_helpers/resource_importer.rb', line 150 def add_nested_resources(resource) return unless resource.klass(safe: true) && resource.klass.respond_to?(:table_exists?) && resource.klass.table_exists? if [HasHelpers::ResourceType::BASE, HasHelpers::ResourceType::NESTED, HasHelpers::ResourceType::TYPE, HasHelpers::ResourceType::SUB].include?(resource.resource_type) = (resource.klass) # Create nested resources # recursive for each nested resource created .nested_resources.each do |nested_resource_name| nested_resource = ::HasHelpers::Resource.find_or_initialize_by(parent_id: resource.id, name: nested_resource_name, application_id: resource.application.id, resource_type: ::HasHelpers::ResourceType::NESTED) if create_branch_resource(nested_resource) || lacks_of_nested_resources(nested_resource) add_nested_resources(nested_resource) # recursive call add next nested resource in branch elsif nested_resource.new_record? # already exists no need to create it nested_resource.destroy end end # Create split resources .split_resources.each do |split_resource_name| ::HasHelpers::Resource.find_or_create_by(parent_id: resource.id, name: split_resource_name, application_id: resource.application.id, resource_type: ::HasHelpers::ResourceType::SPLIT) end # Create fields resources add_field_resources(resource) end end |
#audit_nested_resources(resource) ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/has_helpers/resource_importer.rb', line 185 def audit_nested_resources(resource) return if resource.klass(safe: true).blank? = (resource.klass) existing_nested_resources = resource.nested_resources.map(&:name) new_nested_resources = .nested_resources + .split_resources + .fields_resources missing_nested_resources = existing_nested_resources - new_nested_resources if missing_nested_resources.present? raise AuditError, AUDIT_MISSING_NESTED_RESOURCES % { application_name: resource.application.name, resource_name: resource.name, nested_resources: missing_nested_resources } end end |
#audit_resources(application) ⇒ Object
175 176 177 178 179 180 181 182 183 |
# File 'lib/has_helpers/resource_importer.rb', line 175 def audit_resources(application) existing_resources = application.resources.where.not(resource_type: [::HasHelpers::ResourceType::SPLIT, ::HasHelpers::ResourceType::FIELD, ::HasHelpers::ResourceType::REQUIRED_FIELD]).map(&:name) new_resources = active_record_models.map(&:name).to_a missing_resources = existing_resources - new_resources if missing_resources.present? raise AuditError, AUDIT_MISSING_RESOURCES % { application_name: application.name, resources: missing_resources } end end |
#create_branch_resource(resource) ⇒ Object
check if the branch already has the resource and if not save it This is to avoid infinite recursion with resources in case of a circular reference such as A -> B -> C -> A e.g., Hierarchy contains a Hierarchy and that a Hierarchy and so on...
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/has_helpers/resource_importer.rb', line 103 def create_branch_resource(resource) # Find the base resource (the one without a parent) mem_record = @mem_resources.find { |mem_res| mem_res[:resource] == resource } base_resource = mem_record[:ancestors].find { |r| r.parent_id == nil } if mem_record base_resource = ancestor_resources(resource).find { |r| r.parent_id == nil } unless base_resource return false unless base_resource base_resource_mem_record = @mem_resources.find { |mem_res| mem_res[:resource].name == base_resource.name && mem_res[:resource].application_id == base_resource.application.id && mem_res[:resource].resource_type_id == base_resource.resource_type.id } if !base_resource_mem_record base_resource_mem_record = { resource: base_resource, ancestors: ancestor_resources(base_resource), descendants: descendants_resources(base_resource) } @mem_resources << base_resource_mem_record end # Check if the resource exists in the branch all_descendants = base_resource_mem_record[:descendants] exists = all_descendants.select { |r| r.name == resource.name && r.application_id == resource.application.id && r.resource_type_id == resource.resource_type.id } # we only want to save if the resource does not exist in the branch, if it is a valid active record model, and if the table exists if resource.klass(safe: true) && active_record_models.include?(resource.klass) && resource.klass.respond_to?(:table_exists?) && resource.klass.table_exists? if exists.empty? resource.save! @mem_resources << { resource: resource, ancestors: ancestor_resources(resource), descendants: descendants_resources(resource) } base_resource_mem_record[:descendants] << resource if base_resource_mem_record return true else # check if the resource path though its parent is the same. If not then save the resource. # e.g. A -> B -> C && A -> F -> C then C after F should be saved as a new resource exists.each do |exist_resource| exist_resource_ancestors = ancestor_resources(exist_resource) resource_ancestors = ancestor_resources(resource) if exist_resource_ancestors.map(&:name).to_set != resource_ancestors.map(&:name).reject { |name| name == exist_resource.name }.to_set && resource_ancestors.map(&:name).reject { |name| name == exist_resource.name }.to_set.present? resource.save! @mem_resources << { resource: resource, ancestors: ancestor_resources(resource), descendants: descendants_resources(resource) } base_resource_mem_record[:descendants] << resource if base_resource_mem_record return true end end end end false end |
#create_importable_resources_for(resource, application) ⇒ Object
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/has_helpers/resource_importer.rb', line 197 def create_importable_resources_for(resource, application) model = resource&.name&.safe_constantize return if model.blank? return unless model.respond_to?(:importable_accessors) model.importable_accessors.each do |accessor_name| accessor_name = accessor_name.to_s ::HasHelpers::Resource.find_or_create_by!( parent_id: resource.id, name: accessor_name, application: application, resource_type: ::HasHelpers::ResourceType::ACCESSOR_FIELD, alias_name: accessor_name.humanize.titleize ) end end |
#import_nested_resources!(audit: true) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/has_helpers/resource_importer.rb', line 58 def import_nested_resources!(audit: true) [].tap do |errors| applications.each do |application| application.resources.where(parent_id: nil).find_each do |resource| add_nested_resources(resource) run_audit(audit) { audit_nested_resources(resource) } rescue AuditError => e errors << e. end end end end |
#import_resource_nested_resources(resource, audit: true) ⇒ Object
26 27 28 29 30 31 |
# File 'lib/has_helpers/resource_importer.rb', line 26 def import_resource_nested_resources(resource, audit: true) add_nested_resources(resource) run_audit(audit) { audit_nested_resources(resource) } rescue AuditError => e e. end |
#import_resources(audit: true) ⇒ Object
33 34 35 36 37 38 |
# File 'lib/has_helpers/resource_importer.rb', line 33 def import_resources(audit: true) [].tap do |errors| errors.concat(import_resources!(audit: audit)) errors.concat(import_nested_resources!(audit: audit)) if errors.empty? end end |
#import_resources!(audit: true) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/has_helpers/resource_importer.rb', line 40 def import_resources!(audit: true) [].tap do |errors| applications.each do |application| run_audit(audit) { audit_resources(application) } active_record_models.each do |model_klass| next if model_klass.name == "primary::SchemaMigration" = (model_klass) if model_klass.respond_to?(:table_exists?) && model_klass.table_exists? resource = ::HasHelpers::Resource.find_or_create_by(name: model_klass.name, application: application, resource_type: .resource_type, alias_name: .alias_name) @mem_resources << { resource: resource, ancestors: ancestor_resources(resource), descendants: descendants_resources(resource) } end end rescue AuditError => e errors << e. end end end |
#lacks_of_nested_resources(resource) ⇒ Object
142 143 144 145 146 147 148 |
# File 'lib/has_helpers/resource_importer.rb', line 142 def lacks_of_nested_resources(resource) if resource.persisted? = (resource.klass) return .nested_resources.present? && .nested_resources.to_set != resource.nested_resources.not_fields.map(&:name).to_set end false end |