rabl-rails 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,8 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.3.3
4
+ * Add response caching
5
+
3
6
  ## 0.3.2
4
7
  * Using child with a nil value will be correctly formatted as nil
5
8
  * Allow controller's assigns to have symbol keys
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # RABL for Rails #
1
+ # RABL for Rails [![Build Status](https://travis-ci.org/ccocchi/rabl-rails.png?branch=master)](https://travis-ci.org/ccocchi/rabl-rails)
2
2
 
3
3
  RABL (Ruby API Builder Language) is a ruby templating system for rendering resources in different format (JSON, XML, BSON, ...). You can find documentation [here](http://github.com/nesquena/rabl).
4
4
 
@@ -94,7 +94,7 @@ RablRails.configure do |config|
94
94
  # config.json_engine = :oj
95
95
  # config.xml_engine = 'LibXML'
96
96
  # config.use_custom_responder = false
97
- # config.default_responder_template = 'show'
97
+ # config.default_responder_template = 'show'
98
98
  # config.enable_jsonp_callbacks = false
99
99
  end
100
100
  ```
@@ -285,7 +285,10 @@ You can find more informations about how to use this method in the [wiki](http:/
285
285
 
286
286
  ### Other features
287
287
 
288
- You can find more informations about other features (caching, custom_responder, ...) in the [WIKI](https://github.com/ccocchi/rabl-rails/wiki)
288
+ * [Caching](https://github.com/ccocchi/rabl-rails/wiki/Caching)
289
+ * [Custom responder](https://github.com/ccocchi/rabl-rails/wiki/Using-custom-responder)
290
+
291
+ And more in the [WIKI](https://github.com/ccocchi/rabl-rails/wiki)
289
292
 
290
293
  ## Performance
291
294
 
@@ -65,11 +65,12 @@ module RablRails
65
65
  def child(name_or_data, options = {})
66
66
  data, name = extract_data_and_name(name_or_data)
67
67
  name = options[:root] if options.has_key? :root
68
- if options[:partial]
68
+
69
+ @template[name] = if options[:partial]
69
70
  template = Library.instance.compile_template_from_path(options[:partial])
70
- @template[name] = template.merge!(:_data => data)
71
+ template.merge!(:_data => data)
71
72
  elsif block_given?
72
- @template[name] = sub_compile(data) { yield }
73
+ sub_compile(data) { yield }
73
74
  end
74
75
  end
75
76
 
@@ -140,6 +141,10 @@ module RablRails
140
141
  @template[sequence('if')] = Condition.new(proc, sub_compile(nil) { yield })
141
142
  end
142
143
 
144
+ def cache(&block)
145
+ @template.cache_key = block_given? ? block : nil
146
+ end
147
+
143
148
  protected
144
149
 
145
150
  #
@@ -27,10 +27,13 @@ module RablRails
27
27
  end
28
28
  end
29
29
  collection_or_resource ||= @_resource
30
- output_hash = collection_or_resource.respond_to?(:each) ? render_collection(collection_or_resource, template.source) :
31
- render_resource(collection_or_resource, template.source)
32
- _options[:root_name] = template.root_name
33
- format_output(output_hash)
30
+
31
+ render_with_cache(template.cache_key, collection_or_resource) do
32
+ output_hash = collection_or_resource.respond_to?(:each) ? render_collection(collection_or_resource, template.source)
33
+ : render_resource(collection_or_resource, template.source)
34
+ _options[:root_name] = template.root_name
35
+ format_output(output_hash)
36
+ end
34
37
  end
35
38
 
36
39
  #
@@ -43,6 +46,16 @@ module RablRails
43
46
 
44
47
  protected
45
48
 
49
+ def render_with_cache(key, collection_or_resource, &block)
50
+ if !key.is_a?(FalseClass) && ActionController::Base.perform_caching
51
+ Rails.cache.fetch(resolve_cache_key(key, collection_or_resource)) do
52
+ yield
53
+ end
54
+ else
55
+ yield
56
+ end
57
+ end
58
+
46
59
  #
47
60
  # Render a single resource as a hash, according to the compiled
48
61
  # template source passed.
@@ -68,14 +81,7 @@ module RablRails
68
81
  instance_exec data, &(value.last)
69
82
  when Hash
70
83
  current_value = value.dup
71
- data_symbol = current_value.delete(:_data)
72
- object = if data_symbol == nil
73
- data
74
- else
75
- data_symbol.to_s.start_with?('@') ? instance_variable_get(data_symbol)
76
- : data.respond_to?(data_symbol) ? data.send(data_symbol)
77
- : send(data_symbol)
78
- end
84
+ object = object_from_data(data, current_value.delete(:_data))
79
85
 
80
86
  if key.to_s.start_with?('_') # glue
81
87
  output.merge!(render_resource(object, current_value))
@@ -133,6 +139,23 @@ module RablRails
133
139
  @_context.respond_to?(name) ? @_context.send(name, *args, &block) : super
134
140
  end
135
141
 
142
+ def resolve_cache_key(key, data)
143
+ return data.cache_key unless key
144
+ key.is_a?(Proc) ? instance_exec(data, &key) : key
145
+ end
146
+
147
+ private
148
+
149
+ def object_from_data(data, symbol)
150
+ return data if symbol == nil
151
+
152
+ if symbol.to_s.start_with?('@')
153
+ instance_variable_get(symbol)
154
+ else
155
+ data.respond_to?(symbol) ? data.send(symbol) : send(symbol)
156
+ end
157
+ end
158
+
136
159
  #
137
160
  # Copy assigns from controller's context into this
138
161
  # renderer context to include instances variables when
@@ -7,6 +7,10 @@ module RablRails
7
7
 
8
8
  RablRails.enable_jsonp_callbacks && params.has_key?(:callback) ? "#{params[:callback]}(#{json})" : json
9
9
  end
10
+
11
+ def resolve_cache_key(key, data)
12
+ "#{super}.json"
13
+ end
10
14
  end
11
15
  end
12
16
  end
@@ -6,6 +6,10 @@ module RablRails
6
6
  hash = { _options[:root_name] => hash } if _options[:root_name] && RablRails.include_plist_root
7
7
  RablRails.plist_engine.dump(hash)
8
8
  end
9
+
10
+ def resolve_cache_key(key, data)
11
+ "#{super}.plist"
12
+ end
9
13
  end
10
14
  end
11
15
  end
@@ -9,6 +9,10 @@ module RablRails
9
9
  xml_options = { root: _options[:root_name] }.merge!(DEFAULT_OPTIONS)
10
10
  hash.to_xml(xml_options)
11
11
  end
12
+
13
+ def resolve_cache_key(key, data)
14
+ "#{super}.xml"
15
+ end
12
16
  end
13
17
  end
14
18
  end
@@ -1,11 +1,12 @@
1
1
  module RablRails
2
2
  class CompiledTemplate
3
- attr_accessor :source, :data, :root_name
3
+ attr_accessor :source, :data, :root_name, :cache_key
4
4
 
5
5
  delegate :[], :[]=, :merge!, :to => :source
6
6
 
7
7
  def initialize
8
8
  @source = {}
9
+ @cache_key = false
9
10
  end
10
11
 
11
12
  def initialize_dup(other)
@@ -1,3 +1,3 @@
1
1
  module RablRails
2
- VERSION = '0.3.2'
2
+ VERSION = '0.3.3'
3
3
  end
@@ -15,7 +15,11 @@ class TestBaseRenderer < ActiveSupport::TestCase
15
15
  @context.assigns['data'] = @data
16
16
 
17
17
  @template = RablRails::CompiledTemplate.new
18
+ @template.source = {}
18
19
  @template.data = :@data
20
+
21
+ @cache = mock
22
+ Rails.stub(:cache).and_return(@cache)
19
23
  end
20
24
 
21
25
  def render_hash
@@ -29,7 +33,35 @@ class TestBaseRenderer < ActiveSupport::TestCase
29
33
 
30
34
  test "properly handle assigns with symbol keys" do
31
35
  @context.assigns[:foo] = 'bar'
32
- @template.source = {}
33
36
  assert_nothing_raised { render_hash }
34
37
  end
38
+
39
+ test "cache should be applied if no cache key is given" do
40
+ @cache.should_not_receive(:fetch)
41
+ render_hash
42
+ end
43
+
44
+ test "cache should not be used if disabled in Rails configuration" do
45
+ ActionController::Base.stub(:perform_caching).and_return(false)
46
+ @cache.should_not_receive(:fetch)
47
+ @template.cache_key = 'something'
48
+ render_hash
49
+ end
50
+
51
+ test "cache shoud use #cache_key as default" do
52
+ ActionController::Base.stub(:perform_caching).and_return(true)
53
+ @data.stub(:cache_key).and_return('data_cache_key')
54
+ @cache.should_receive(:fetch).with('data_cache_key').and_return({ some: 'hash' })
55
+ @template.cache_key = nil
56
+
57
+ assert_equal({ some: 'hash' }, render_hash)
58
+ end
59
+
60
+ test "cache should use the proc if given" do
61
+ ActionController::Base.stub(:perform_caching).and_return(true)
62
+ @template.cache_key = ->(u) { 'proc_cache_key' }
63
+ @cache.should_receive(:fetch).with('proc_cache_key').and_return({ some: 'hash' })
64
+
65
+ assert_equal({ some: 'hash' }, render_hash)
66
+ end
35
67
  end
@@ -58,6 +58,21 @@ class CompilerTest < ActiveSupport::TestCase
58
58
  assert_equal false, t.root_name
59
59
  end
60
60
 
61
+ test "template should not have a cache key if cache is not enable" do
62
+ t = @compiler.compile_source('')
63
+ assert_equal false, t.cache_key
64
+ end
65
+
66
+ test "cache can take no argument" do
67
+ t = @compiler.compile_source(%{ cache })
68
+ assert_nil t.cache_key
69
+ end
70
+
71
+ test "cache can take a block" do
72
+ t = @compiler.compile_source(%( cache { 'foo' }))
73
+ assert_instance_of Proc, t.cache_key
74
+ end
75
+
61
76
  # Compilation
62
77
 
63
78
  test "simple attributes are compiled to hash" do
@@ -152,6 +167,23 @@ class CompilerTest < ActiveSupport::TestCase
152
167
  assert_equal({ :id => :id }, t.source)
153
168
  end
154
169
 
170
+ test "extends should not overwrite nodes previously defined" do
171
+ skip('Bug reported by @abrisse')
172
+
173
+ template = mock('file_template', :source => %(condition(-> { true }) { 'foo' }))
174
+ lookup_context = mock
175
+ lookup_context.stub(:find_template).with('users/xtnd', [], false).and_return(template)
176
+ RablRails::Library.reset_instance
177
+ RablRails::Library.instance.instance_variable_set(:@lookup_context, lookup_context)
178
+
179
+ t = @compiler.compile_source(%{
180
+ condition(-> { false }) { 'bar' }
181
+ extends('users/xtnd')
182
+ })
183
+
184
+ assert_equal 2, t.source.keys.size
185
+ end
186
+
155
187
  test "node are compiled without evaluating the block" do
156
188
  t = @compiler.compile_source(%{ node(:foo) { bar } })
157
189
  assert_not_nil t.source[:foo]
@@ -174,4 +174,16 @@ class TestJsonRenderer < ActiveSupport::TestCase
174
174
  @template.source = { :name => :name }
175
175
  assert_equal %q[some_callback({"name":"foobar"})], render_json_output
176
176
  end
177
+
178
+ test "cache key should be different from Base to avoid name collisions" do
179
+ ActionController::Base.stub(:perform_caching).and_return(true)
180
+ @data.stub(:cache_key).and_return('data_cache_key')
181
+ @template.cache_key = nil
182
+
183
+ @cache = mock
184
+ @cache.should_receive(:fetch).with('data_cache_key.json').and_return(%("some":"json"))
185
+ Rails.stub(:cache).and_return(@cache)
186
+
187
+ assert_equal %("some":"json"), render_json_output
188
+ end
177
189
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabl-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-28 00:00:00.000000000 Z
12
+ date: 2013-06-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport