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

Empty JSON response when using cache and collection contains only one element #468

Open
ryreitsma opened this issue Jun 21, 2013 · 0 comments

Comments

@ryreitsma
Copy link

If caching is on and the collection which is rendered contains only one element, I get an empty JSON repsonse in some cases. I have these three templates in my Rails 3.2 application:

message.rabl
object @message
cache @message

attribute :id, :url, :created_at

node :file_shares do |message|
  partial "drive/file_shares/file_shares", object: message.file_shares
end
file_shares.rabl
collection @file_shares, object_root: false
cache @file_shares

extends "drive/file_shares/file_share"
file_share.rabl
object @file_share
cache @file_share

attribute :url, :file_name, :file_type

The message.rabl template is always rendered first. This works fine, I get the json reponse including a node containing one file_share. However, if the file_shares.rabl is rendered in the next request, I get an empty json response.
When the file_shares.rabl is rendered, the extends method gets a cache hit on:

rabl/drive/file_shares/1012-20130620132506//hash

However, the result of that cache hit is an array containing a hash of the file_share. But an array is not what the extends method expects:

lib/rabl/builder.rb:118:

# Extends an existing rabl template with additional attributes in the block
# extends("users/show") { attribute :full_name }
def extends(file, options={}, &block)
  options = @options.slice(:child_root).merge(:object => @_object).merge(options)
  result = self.partial(file, options, &block)
  @_result.merge!(result) if result.is_a?(Hash)
end

The result from self.partial is not a hash, which results in an empty response. However, I think the cause of this bug is in the construction of the cache key in the Rabl engine:

lib/rabl/engine.rb:277

result_cache_key = Array(cache_key) + [@_options[:root_name], @_options[:format]]

The cache_key variable contains either an object or a collection of objects. However, by using Array(cache_key) the result_cache_key for one object is equal to the result_cache_key for the same object used as the sole object in an array.

file_share = FileShare.create
result_cache_key_1 = Array(file_share) + [@_options[:root_name], @_options[:format]]

result_cache_key_2 = Array([file_share]) + [@_options[:root_name], @_options[:format]]

result_cache_key_1 == result_cache_key_2

A possible solution could be to add information about whether the cache key is for an object or for a collection into the result_cache_key:

result_cache_key = [cache_key, cache_key.class, @_options[:root_name], @_options[:format]]

I don't know how to create a failing test case for this in the Rabl test suite. If anyone can, I'd love to help solve this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant