Module: Foobara::RemoteImports::ImportBase

Included in:
ImportCommand, ImportDomain, ImportError, ImportOrganization, ImportType
Defined in:
foobara-remote-imports-1.2.0/src/foobara/remote_imports/import_base.rb

Defined Under Namespace

Classes: BadManifestInputsError, NotFoundError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#manifest_dataObject

Returns the value of attribute manifest_data.



57
58
59
# File 'src/foobara/remote_imports/import_base.rb', line 57

def manifest_data
  @manifest_data
end

#manifest_to_importObject

Returns the value of attribute manifest_to_import.



57
58
59
# File 'src/foobara/remote_imports/import_base.rb', line 57

def manifest_to_import
  @manifest_to_import
end

#manifests_to_importObject

Returns the value of attribute manifests_to_import.



57
58
59
# File 'src/foobara/remote_imports/import_base.rb', line 57

def manifests_to_import
  @manifests_to_import
end

Class Method Details

.included(klass) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'src/foobara/remote_imports/import_base.rb', line 28

def included(klass)
  klass.possible_input_error :to_import, NotFoundError
  klass.possible_error BadManifestInputsError

  klass.inputs(
    manifest_url: :string,
    raw_manifest: :associative_array,
    cache: { type: :boolean, default: true },
    cache_path: { type: :string, default: "tmp/cache/foobara-remote-imports" },
    to_import: :duck,
    already_imported: { type: :duck, allow_nil: true },
    deanonymize_models: { type: :boolean, default: true }
  )

  klass.result :duck
end

Instance Method Details

#already_exists?Boolean

Returns:

  • (Boolean)


74
75
76
77
78
79
80
81
82
# File 'src/foobara/remote_imports/import_base.rb', line 74

def already_exists?
  method = "foobara_lookup_#{manifest_to_import.scoped_category}"

  Foobara.foobara_root_namespace.send(
    method,
    manifest_to_import.reference,
    mode: Namespace::LookupMode::ABSOLUTE
  )
end

#already_importedObject



84
85
86
# File 'src/foobara/remote_imports/import_base.rb', line 84

def already_imported
  inputs[:already_imported] || AlreadyImported.new
end

#cache_file_pathObject



189
190
191
# File 'src/foobara/remote_imports/import_base.rb', line 189

def cache_file_path
  @cache_file_path ||= "#{cache_path}/#{cache_key}.json"
end

#cache_keyObject



180
181
182
183
184
185
186
187
# File 'src/foobara/remote_imports/import_base.rb', line 180

def cache_key
  @cache_key ||= begin
    hash = Digest::MD5.hexdigest(manifest_url)
    escaped_url = manifest_url.gsub(/[^\w]/, "_")

    "#{hash}_#{escaped_url}"
  end
end

#cache_manifestObject



163
164
165
166
# File 'src/foobara/remote_imports/import_base.rb', line 163

def cache_manifest
  FileUtils.mkdir_p(cache_path)
  File.write(cache_file_path, manifest_data.to_json)
end

#cached?Boolean

Returns:

  • (Boolean)


172
173
174
# File 'src/foobara/remote_imports/import_base.rb', line 172

def cached?
  File.exist?(cache_file_path)
end

#determine_manifests_to_importObject



193
194
195
# File 'src/foobara/remote_imports/import_base.rb', line 193

def determine_manifests_to_import
  self.manifests_to_import = find_manifests_to_import
end

#executeObject



46
47
48
49
50
51
52
53
54
55
# File 'src/foobara/remote_imports/import_base.rb', line 46

def execute
  load_manifest

  cache_manifest if should_cache?
  determine_manifests_to_import
  filter_manifests_to_import
  import_objects_from_manifests

  imported_objects
end

#filter_manifests_to_importObject

TODO: feels like a command smell to pass manifests here… reconsider algorithm



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'src/foobara/remote_imports/import_base.rb', line 125

def filter_manifests_to_import
  return if to_import.nil? || to_import.empty?

  references = manifests_to_import.map(&:reference)

  filter = Util.array(to_import)

  filter.map! do |name|
    if references.include?(name)
      name
    else
      suffix = "::#{name}"

      partial_matches = references.select { |reference| reference.end_with?(suffix) }

      if partial_matches.size == 1
        partial_matches.first
      else
        name
      end
    end
  end

  not_found = filter - references

  if not_found.any?
    add_input_error :to_import, :not_found, "Could not find #{not_found}", not_found:
  end

  self.manifests_to_import = manifests_to_import.select do |manifest|
    filter.include?(manifest.reference)
  end
end

#find_manifests_to_importObject



197
198
199
200
201
# File 'src/foobara/remote_imports/import_base.rb', line 197

def find_manifests_to_import
  # :nocov:
  raise "subclass responsibility"
  # :nocov:
end

#import_object_from_manifestObject



216
217
218
219
220
# File 'src/foobara/remote_imports/import_base.rb', line 216

def import_object_from_manifest
  # :nocov:
  raise "subclass responsibility"
  # :nocov:
end

#import_objects_from_manifestsObject



203
204
205
206
207
208
209
210
211
212
213
214
# File 'src/foobara/remote_imports/import_base.rb', line 203

def import_objects_from_manifests
  manifests_to_import.each do |manifest|
    unless already_imported.already_imported?(manifest)
      self.manifest_to_import = manifest

      next if already_exists?

      imported_objects << import_object_from_manifest
      already_imported << manifest
    end
  end
end

#imported_objectsObject



222
223
224
# File 'src/foobara/remote_imports/import_base.rb', line 222

def imported_objects
  @imported_objects ||= []
end

#load_cached_manifestObject



176
177
178
# File 'src/foobara/remote_imports/import_base.rb', line 176

def load_cached_manifest
  JSON.parse(File.read(cache_file_path))
end

#load_manifestObject



88
89
90
91
92
93
94
95
96
# File 'src/foobara/remote_imports/import_base.rb', line 88

def load_manifest
  self.manifest_data = if raw_manifest
                         raw_manifest
                       elsif cache && cached?
                         load_cached_manifest
                       else
                         load_manifest_from_url
                       end
end

#load_manifest_from_urlObject



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'src/foobara/remote_imports/import_base.rb', line 98

def load_manifest_from_url
  uri = URI.parse(manifest_url)

  net_http = Net::HTTP.new(uri.host, uri.port).tap do |http|
    http.use_ssl = uri.scheme == "https"
    http.read_timeout = ENV["FOOBARA_HTTP_MANIFEST_TIMEOUT"]&.to_i || 30
  end

  request = Net::HTTP::Get.new(uri.request_uri, load_manifest_headers)
  response = net_http.request(request)

  unless response.is_a?(Net::HTTPSuccess)
    # :nocov:
    raise "Could not get manifest from #{manifest_url}: " \
          "#{response.code} #{response.message}"
    # :nocov:
  end
  manifest_json = response.body

  JSON.parse(manifest_json)
end

#load_manifest_headersObject



120
121
122
# File 'src/foobara/remote_imports/import_base.rb', line 120

def load_manifest_headers
  { "Content-Type" => "application/json" }
end

#root_manifestObject



159
160
161
# File 'src/foobara/remote_imports/import_base.rb', line 159

def root_manifest
  @root_manifest ||= Manifest::RootManifest.new(manifest_data)
end

#should_cache?Boolean

Returns:

  • (Boolean)


168
169
170
# File 'src/foobara/remote_imports/import_base.rb', line 168

def should_cache?
  cache && manifest_url && !cached?
end

#validateObject



59
60
61
62
# File 'src/foobara/remote_imports/import_base.rb', line 59

def validate
  super
  validate_manifest
end

#validate_manifestObject



64
65
66
67
68
69
70
71
72
# File 'src/foobara/remote_imports/import_base.rb', line 64

def validate_manifest
  if manifest_url
    if raw_manifest
      add_runtime_error :bad_manifest_inputs, "Cannot provide both manifest_url and raw_manifest"
    end
  elsif !raw_manifest
    add_runtime_error :bad_manifest_inputs, "Must provide either manifest_url or raw_manifest"
  end
end