Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

cache support

* added within the engine
* Rails 3 tests updated for posts only, left users to run without cache
* Rails 2 tests do not run for me locally, DID NOT TEST
* README updated
  • Loading branch information...
commit 99d0c5a7cb53072dc4ef6e1b6c932274970e83da 1 parent 982ea98
@databyte databyte authored committed
View
38 README.md
@@ -455,6 +455,44 @@ end
This will display the quiz object with nested questions and answers as you would expect with a quiz node, and embedded questions and answers.
Note that RABL can be nested arbitrarily deep within child nodes to allow for these representations to be defined.
+### Caching ###
+
+Caching works by saving the entire template output to the Rails cache_store.
+
+Requires Rails, action_controller.perform_caching set to true in your environment, and `cache` to be set to a key (object that has cache_key defined, array or string).
+
+```ruby
+# app/views/users/show.json.rabl
+object @quiz
+cache @quiz # key = rabl/quiz/[cache_key]
+attribute :title
+```
+
+The `cache` keyword accepts the same parameters as fragment caching for Rails.
+
+```ruby
+cache @user # calls @user.cache_key
+cache ['keel', @user] # calls @user.cache_key and prefixes with kewl/
+cache 'lists' # explicit key of 'lists'
+cache 'lists', expires_in: 1.hour
+```
+
+The cache keyword is used from within the base template. It will ignore any cache keys specified in an extended template or within partials.
+
+```ruby
+# app/views/users/index.json.rabl
+collection @users
+cache @users # key = rabl/users/[cache_key]/users/[cache_key]/...
+extends "users/show"
+```
+
+```ruby
+# app/views/users/show.json.rabl
+object @user
+cache @user # ignored
+
+attributes :name, :email
+```
### Content Type Assignment ###
Currently in RABL, the content-type of your response is not set automatically. This is because RABL is intended
View
1  fixtures/ashared/views/posts/index.json.rabl
@@ -1,4 +1,5 @@
collection @posts => :articles
+cache ['kittens!', @posts]
extends "posts/show"
View
1  fixtures/ashared/views/posts/show.json.rabl
@@ -1,4 +1,5 @@
object @post
+cache @post
attributes :title, :body
attributes :created_at => :posted_at
View
25 fixtures/rails3/test/functional/posts_controller_test.rb
@@ -78,7 +78,7 @@
json_output['post']
end
- # Attributes (regular)
+ # Attributes (regular)
asserts("contains post title") { topic['title'] }.equals { @post1.title }
asserts("contains post body") { topic['body'] }.equals { @post1.body }
@@ -105,4 +105,27 @@
asserts("contains date partial with full") { topic['full'] }.equals { @post1.created_at.iso8601 }
end # date node
end # show action
+
+ context "for index action with caching" do
+ setup do
+ mock(ActionController::Base).perform_caching.any_number_of_times { true }
+ get "/posts"
+ end
+
+ asserts("contains post titles") do
+ json_output['articles'].map { |o| o["article"]["title"] }
+ end.equals { @posts.map(&:title) }
+ end
+
+ context "for show action with caching" do
+ setup do
+ mock(ActionController::Base).perform_caching.any_number_of_times { true }
+ get "/posts/#{@post1.id}"
+ json_output['post']
+ end
+
+ asserts("contains post title") { topic['title'] }.equals { @post1.title }
+ asserts("contains post body") { topic['body'] }.equals { @post1.body }
+ end
+
end
View
26 lib/rabl/engine.rb
@@ -17,7 +17,6 @@ def render(scope, locals, &block)
self.copy_instance_variables_from(@_scope, [:@assigns, :@helpers])
@_options[:scope] = @_scope
@_options[:format] ||= self.request_format
- @_options[:cache] = @_cache if defined? @_cache
@_data = locals[:object] || self.default_object
if @_options[:source_location]
instance_eval(@_source, @_options[:source_location]) if @_source.present?
@@ -35,10 +34,15 @@ def to_hash(options={})
data = data_object(@_data)
builder = Rabl::Builder.new(options)
options[:root_name] = determine_object_root(@_data, options[:root])
- if is_object?(data) || !data # object @user
- builder.build(data, options)
- elsif is_collection?(data) # collection @users
- data.map { |object| builder.build(object, options) }
+
+ _cache = @_cache if defined?(@_cache)
+ cache_key, cache_options = *_cache || nil
+ cache_results(cache_key, cache_options) do
+ if is_object?(data) || !data # object @user
+ builder.build(data, options)
+ elsif is_collection?(data) # collection @users
+ data.map { |object| builder.build(object, options) }
+ end
end
end
@@ -232,5 +236,17 @@ def reset_options!
@_options[:extends] = []
@_options[:root_name] = nil
end
+
+ def cache_configured?
+ defined?(Rails) && ActionController::Base.perform_caching
+ end
+
+ def cache_results(key, options = {}, &block)
+ if cache_configured? && key
+ Rails.cache.fetch(ActiveSupport::Cache.expand_cache_key(key, :rabl), options, &block)
+ else
+ yield
+ end
+ end
end
end
View
1  test/integration/test_init.rb
@@ -1,5 +1,6 @@
require 'rack/test'
require 'riot'
+require 'riot/rr'
Riot.pretty_dots
Please sign in to comment.
Something went wrong with that request. Please try again.