class FmRest::Spyke::SpykeFormatter
Response Faraday middleware for converting FM API's response JSON into Spyke's expected format
Constants
- CONTAINER_RE
- FIND_RECORDS_RE
- MULTIPLE_RECORDS_RE
- SCRIPT_REQUEST_RE
- SINGLE_RECORD_RE
- VALIDATION_ERROR_RANGE
Public Class Methods
@param app [#call] @param model [Class<FmRest::Spyke::Base>]
# File lib/fmrest/spyke/spyke_formatter.rb, line 32 def initialize(app, model) super(app) @model = model end
Public Instance Methods
@param env [Faraday::Env]
# File lib/fmrest/spyke/spyke_formatter.rb, line 38 def on_complete(env) return unless env.body.is_a?(Hash) json = env.body case when single_record_request?(env) env.body = prepare_single_record(json) when multiple_records_request?(env), find_request?(env) env.body = prepare_collection(json) when create_request?(env), update_request?(env), delete_request?(env), container_upload_request?(env) env.body = prepare_save_response(json) when execute_script_request?(env) env.body = build_base_hash(json) else # Attempt to parse unknown requests too env.body = build_base_hash(json) end end
Private Instance Methods
@param json [Hash] @param include_errors [Boolean] @return [FmRest::Spyke::Metadata] the skeleton structure for a
Spyke-formatted response
# File lib/fmrest/spyke/spyke_formatter.rb, line 95 def build_base_hash(json, include_errors = false) { metadata: Metadata.new( prepare_messages(json), prepare_script_results(json), prepare_data_info(json) ).freeze, errors: include_errors ? prepare_errors(json) : {} } end
(see single_record_request?
)
# File lib/fmrest/spyke/spyke_formatter.rb, line 260 def container_upload_request?(env) env.method == :post && env.url.path.match(CONTAINER_RE) end
(see single_record_request?
)
# File lib/fmrest/spyke/spyke_formatter.rb, line 255 def create_request?(env) env.method == :post && env.url.path.match(MULTIPLE_RECORDS_RE) end
(see single_record_request?
)
# File lib/fmrest/spyke/spyke_formatter.rb, line 265 def delete_request?(env) env.method == :delete && env.url.path.match(SINGLE_RECORD_RE) end
# File lib/fmrest/spyke/spyke_formatter.rb, line 269 def execute_script_request?(env) env.method == :get && env.url.path.match(SCRIPT_REQUEST_RE) end
(see single_record_request?
)
# File lib/fmrest/spyke/spyke_formatter.rb, line 245 def find_request?(env) env.method == :post && env.url.path.match(FIND_RECORDS_RE) end
(see single_record_request?
)
# File lib/fmrest/spyke/spyke_formatter.rb, line 240 def multiple_records_request?(env) env.method == :get && env.url.path.match(MULTIPLE_RECORDS_RE) end
(see prepare_save_response
)
# File lib/fmrest/spyke/spyke_formatter.rb, line 83 def prepare_collection(json) data = json[:response][:data] && json[:response][:data].map { |record_data| prepare_record_data(record_data) } build_base_hash(json).merge!(data: data) end
@param json [Hash] @return [OpenStruct] the script(s) execution results for
Spyke metadata format
# File lib/fmrest/spyke/spyke_formatter.rb, line 142 def prepare_data_info(json) data_info = json[:response] && json[:response][:dataInfo] return nil unless data_info.present? DataInfo.new(data_info).freeze end
@param json [Hash] @return [Hash] the errors hash in Spyke
format
# File lib/fmrest/spyke/spyke_formatter.rb, line 152 def prepare_errors(json) # Code 0 means "No Error" # https://fmhelp.filemaker.com/help/17/fmp/en/index.html#page/FMP_Help/error-codes.html return {} if json[:messages][0][:code].to_i == 0 json[:messages].each_with_object(base: []) do |message, hash| # Only include validation errors next unless VALIDATION_ERROR_RANGE.include?(message[:code].to_i) hash[:base] << "#{message[:message]} (#{message[:code]})" end end
@param json [Hash] @return [Array<OpenStruct>] the skeleton structure for a
Spyke-formatted response
# File lib/fmrest/spyke/spyke_formatter.rb, line 109 def prepare_messages(json) return [] unless json[:messages] json[:messages].map { |m| OpenStruct.new(m).freeze }.freeze end
Extracts `recordId` and strips the `“PortalName::”` field prefix for each portal
Sample `json_portal_data`:
"portalData": { "Orders":[ { "Orders::DeliveryDate": "3/7/2017", "recordId": "23" } ] }
@param json_portal_data [Hash] @return [Hash] the portal data in Spyke
format
# File lib/fmrest/spyke/spyke_formatter.rb, line 211 def prepare_portal_data(json_portal_data) json_portal_data.each_with_object({}) do |(portal_name, portal_records), out| portal_options = @model.portal_options[portal_name.to_s] || {} out[portal_name] = portal_records.map do |portal_fields| attributes = { __record_id: portal_fields[:recordId] } attributes[:__mod_id] = portal_fields[:modId] if portal_fields[:modId] prefix = portal_options[:attribute_prefix] || portal_name prefix_matcher = /\A#{prefix}::/ portal_fields.each do |k, v| next if :recordId == k || :modId == k attributes[k.to_s.gsub(prefix_matcher, "").to_sym] = v end attributes end end end
`json_data` is expected in this format:
{ "fieldData": { "fieldName1" : "fieldValue1", "fieldName2" : "fieldValue2", ... }, "portalData": { "portal1" : [ { <portalRecord1> }, { <portalRecord2> }, ... ], "portal2" : [ { <portalRecord1> }, { <portalRecord2> }, ... ] }, "modId": <Id_for_last_modification>, "recordId": <Unique_internal_ID_for_this_record> }
@param json_data [Hash] @return [Hash] the record data in Spyke
format
# File lib/fmrest/spyke/spyke_formatter.rb, line 191 def prepare_record_data(json_data) out = { __record_id: json_data[:recordId], __mod_id: json_data[:modId] } out.merge!(json_data[:fieldData]) out.merge!(prepare_portal_data(json_data[:portalData])) if json_data[:portalData] out end
@param json [Hash] @return [Hash] the response in Spyke
format
# File lib/fmrest/spyke/spyke_formatter.rb, line 62 def prepare_save_response(json) response = json[:response] data = {} data[:__mod_id] = response[:modId] if response[:modId] data[:__record_id] = response[:recordId] if response[:recordId] data[:__new_portal_record_info] = response[:newPortalRecordInfo] if response[:newPortalRecordInfo] build_base_hash(json, true).merge!(data: data) end
@param json [Hash] @return [OpenStruct] the script(s) execution results for Spyke
metadata
format
# File lib/fmrest/spyke/spyke_formatter.rb, line 117 def prepare_script_results(json) results = {} [:prerequest, :presort].each do |s| if json[:response][:"scriptError.#{s}"] results[s] = OpenStruct.new( result: json[:response][:"scriptResult.#{s}"], error: json[:response][:"scriptError.#{s}"] ).freeze end end if json[:response][:scriptError] results[:after] = OpenStruct.new( result: json[:response][:scriptResult], error: json[:response][:scriptError] ).freeze end results.present? ? OpenStruct.new(results).freeze : nil end
(see prepare_save_response
)
# File lib/fmrest/spyke/spyke_formatter.rb, line 74 def prepare_single_record(json) data = json[:response][:data] && prepare_record_data(json[:response][:data].first) build_base_hash(json).merge!(data: data) end
@param env [Faraday::Env] @return [Boolean]
# File lib/fmrest/spyke/spyke_formatter.rb, line 235 def single_record_request?(env) env.method == :get && env.url.path.match(SINGLE_RECORD_RE) end
(see single_record_request?
)
# File lib/fmrest/spyke/spyke_formatter.rb, line 250 def update_request?(env) env.method == :patch && env.url.path.match(SINGLE_RECORD_RE) end