Description
When I start implementing caching in my app, I noticed CachedResourcesProcessor#process_resources returns an array of strings, but SimpleResourcesProcessor#process_resources returns an array of hashes.
I assume the api should expect to return an array of hashes, so that when Rails' controllers calls render
in jsonapi-rails, it converts that data hash into json correctly, but if it's a string, it will to_json
again on string which I don't think we want that behaviour.
Option 1
Change CachedResourcesProcessor#process_resources
to return array of hash:
def process_resources
[@primary, @included].each do |resources|
cache_hash = cache_key_map(resources)
processed_resources = @cache.fetch_multi(*cache_hash.keys) do |key|
res, include, fields = cache_hash[key]
json = res.as_jsonapi(include: include, fields: fields).to_json
JSONString.new(json)
end
values = processed_resources.values.map { |json| JSON.parse(json) }
resources.replace(values)
end
end
Pros: Consistency API.
Cons: It's a bit slow if we do with big data because it has to convert json data back and forth.
Option 2
Change jsonapi-rails
to not calling to_json
again if it's already in string.
::ActionController::Renderers.add(name) do |resources, options|
# Renderer proc is evaluated in the controller context.
self.content_type ||= Mime[:jsonapi]
ActiveSupport::Notifications.instrument('render.jsonapi-rails',
resources: resources,
options: options) do
data = renderer.render(resources, options, self)
data.is_a?(String) ? data : data.to_json
end
end
Pros: It's fast because we don't need to do double works on converting json data.
Cons: Inconsistency API between CachedResourcesProcessor#process_resources
vs SimpleResourcesProcessor#process_resources
.
Edit: Option 2 is not working because renderer.render(resources, options, self)
return jsonapi respone data hash not just data
attribute.