rabl-rails 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - jruby-19mode
5
+ - rbx-19mode
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.3.0
4
+ * Travis integration
5
+ * Add test for keywords used as variable names
6
+ * Add PList renderer
7
+ * Remove location header from post responses in responder
8
+ * Fix bug with incomplete template prefixing
9
+
3
10
  ## 0.2.2
4
11
  * Add condition blocks
5
12
 
data/Gemfile CHANGED
@@ -2,8 +2,16 @@ source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'oj'
6
- gem 'libxml-ruby'
5
+ gem 'plist'
6
+
7
+ platforms :ruby do
8
+ gem 'oj'
9
+ gem 'libxml-ruby'
10
+ end
11
+
12
+ platforms :jruby do
13
+ gem 'nokogiri'
14
+ end
7
15
 
8
16
  group :test do
9
17
  gem 'rspec-mocks'
data/README.md CHANGED
@@ -4,7 +4,7 @@ RABL (Ruby API Builder Language) is a ruby templating system for rendering resou
4
4
 
5
5
  rabl-rails is **faster** and uses **less memory** than the standard rabl gem while letting you access the same features. There are some slight changes to do on your templates to get this gem to work but it should't take you more than 5 minutes.
6
6
 
7
- rabl-rails only target **Rails 3+ application**.
7
+ rabl-rails only targets **Rails 3+ application** and is compatible with mri 1.9.3, jRuby and rubinius.
8
8
 
9
9
  ## Installation
10
10
 
@@ -269,9 +269,9 @@ You can find more informations about other features (caching, custom_responder,
269
269
 
270
270
  ## Performance
271
271
 
272
- Benchmarks have been made using this [application](http://github.com/ccocchi/rabl-benchmark), with rabl 0.6.14 and rabl-rails 0.1.0
272
+ Benchmarks have been made using this [application](http://github.com/ccocchi/rabl-benchmark), with rabl 0.7.6 and rabl-rails 0.3.0
273
273
 
274
- Overall, Rabl-rails is **20% faster and use 10% less memory**, even **twice faster** when rendering collections with extends.
274
+ Overall, Rabl-rails is **20% faster and use 10% less memory**, even **twice faster** when using extends.
275
275
 
276
276
  You can see full tests on test application repository.
277
277
 
@@ -280,11 +280,12 @@ You can see full tests on test application repository.
280
280
  * [Christopher Cocchi-Perrier](http://github.com/ccocchi) - Creator of the project
281
281
 
282
282
  Want to add another format to Rabl-rails ? Checkout [JSON renderer](http://github.com/ccocchi/rabl-rails/blob/master/lib/rabl-rails/renderers/json.rb) for reference
283
- Want to make another change ? Just fork and contribute, any help is very much appreciated
283
+ Want to make another change ? Just fork and contribute, any help is very much appreciated. If you found a bug, you can report it via the Github issues.
284
284
 
285
285
  ## Original idea
286
286
 
287
- * [RABL](http://github.com/nesquena/rabl) Standart RABL gem. I used it a lot before deciding I wanted faster views
287
+ * [RABL](http://github.com/nesquena/rabl) Standart RABL gem. I used it a lot but I needed to improve my API response time, and
288
+ since most of the time was spent in view rendering, I decided to implement a faster rabl gem.
288
289
 
289
290
  ## Copyright
290
291
 
@@ -21,7 +21,6 @@ module RablRails
21
21
  def compile_template_from_source(source, path = nil)
22
22
  if path && RablRails.cache_templates?
23
23
  @cached_templates[path] ||= Compiler.new.compile_source(source)
24
- @cached_templates[path].dup
25
24
  else
26
25
  Compiler.new.compile_source(source)
27
26
  end
@@ -1,6 +1,7 @@
1
1
  require 'rabl-rails/renderers/base'
2
2
  require 'rabl-rails/renderers/json'
3
3
  require 'rabl-rails/renderers/xml'
4
+ require 'rabl-rails/renderers/plist'
4
5
 
5
6
  module RablRails
6
7
  module Renderer
@@ -48,8 +48,7 @@ module RablRails
48
48
  # template source passed.
49
49
  #
50
50
  def render_resource(data, source)
51
- source.inject({}) { |output, current|
52
- key, value = current
51
+ source.inject({}) { |output, (key, value)|
53
52
 
54
53
  out = case value
55
54
  when Symbol
@@ -0,0 +1,11 @@
1
+ module RablRails
2
+ module Renderers
3
+ class PLIST < Base
4
+
5
+ def format_output(hash)
6
+ hash = { _options[:root_name] => hash } if _options[:root_name] && RablRails.include_plist_root
7
+ RablRails.plist_engine.dump(hash)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -28,14 +28,15 @@ module RablRails
28
28
 
29
29
  def api_behavior(error)
30
30
  if post?
31
- template = if @controller.respond_to?(:responder_default_template, true)
31
+ template = if controller.respond_to?(:responder_default_template, true)
32
32
  controller.send(:responder_default_template)
33
33
  else
34
34
  RablRails.responder_default_template
35
35
  end
36
- options[:template] ||= "#{@controller.controller_name}/#{template}"
36
+ options[:prefixes] = controller._prefixes
37
+ options[:template] ||= template
37
38
 
38
- controller.default_render options.merge(status: :created, location: api_location)
39
+ controller.default_render options.merge(status: :created)
39
40
  else
40
41
  head :no_content
41
42
  end
@@ -1,3 +1,3 @@
1
1
  module RablRails
2
- VERSION = '0.2.2'
2
+ VERSION = '0.3.0'
3
3
  end
data/lib/rabl-rails.rb CHANGED
@@ -33,6 +33,12 @@ module RablRails
33
33
  mattr_accessor :responder_default_template
34
34
  @@responder_default_template = 'show'
35
35
 
36
+ mattr_reader :plist_engine
37
+ @@plist_engine = nil
38
+
39
+ mattr_accessor :include_plist_root
40
+ @@include_plist_root = nil
41
+
36
42
  def self.configure
37
43
  yield self
38
44
 
@@ -59,12 +65,23 @@ module RablRails
59
65
  ActiveSupport::XmlMini.backend
60
66
  end
61
67
 
68
+ def self.plist_engine=(name)
69
+ raise "Your plist engine does not respond to #dump" unless name.respond_to?(:dump)
70
+ @@plist_engine = name
71
+ end
72
+
62
73
  def self.cache_templates?
63
74
  ActionController::Base.perform_caching && @@cache_templates
64
75
  end
65
76
 
66
77
  def self.load_default_engines!
67
- self.json_engine = MultiJson.default_engine
68
- self.xml_engine = 'LibXML' if defined?(LibXML)
78
+ self.json_engine = MultiJson.default_engine
79
+ self.plist_engine = Plist::Emit if defined?(Plist)
80
+
81
+ if defined?(LibXML)
82
+ self.xml_engine = 'LibXML'
83
+ elsif defined?(Nokogiri)
84
+ self.xml_engine = 'Nokogiri'
85
+ end
69
86
  end
70
87
  end
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ class KeywordTest < ActiveSupport::TestCase
4
+ class Collection
5
+ attr_accessor :id, :name
6
+
7
+ def initialize(id, name)
8
+ @id = id
9
+ @name = name
10
+ end
11
+
12
+ def cover(size)
13
+ "foo_#{size}"
14
+ end
15
+ end
16
+
17
+ setup do
18
+ RablRails::Library.reset_instance
19
+ @context = Context.new
20
+ @user = User.new(1, 'Marty')
21
+ @collections = [Collection.new(1, 'first'), Collection.new(2, 'last')]
22
+ @context.assigns['user'] = @user
23
+ @context.assigns['collections'] = @collections
24
+ @context.virtual_path = 'user/show'
25
+ @context.stub(lookup_context: nil)
26
+ end
27
+
28
+ test "collections model should render correctly" do
29
+ source = %{
30
+ object :@user
31
+ child(:@collections => :collections) do
32
+ attributes :id, :name
33
+ node(:cover_url) { |c|
34
+ c.cover(:medium)
35
+ }
36
+ end
37
+ }
38
+
39
+ assert_equal(MultiJson.encode(
40
+ user: { collections: [{
41
+ id: 1, name: 'first', cover_url: "foo_medium"
42
+ }, {
43
+ id: 2, name: 'last', cover_url: "foo_medium"
44
+ }] }
45
+ ), RablRails::Library.instance.get_rendered_template(source, @context))
46
+ end
47
+ end
@@ -140,6 +140,7 @@ class TestJsonRenderer < ActiveSupport::TestCase
140
140
  end
141
141
 
142
142
  test "render object with root node" do
143
+ RablRails.include_json_root = true
143
144
  @template.root_name = :author
144
145
  @template.source = { :id => :id, :name => :name }
145
146
  assert_equal %q({"author":{"id":1,"name":"foobar"}}), render_json_output
@@ -0,0 +1,135 @@
1
+ require 'test_helper'
2
+
3
+ class TestPlistRenderer < ActiveSupport::TestCase
4
+ INDENT_REGEXP = /\n(\s)*/
5
+ HEADER_REGEXP = /<\?[^>]+><![^>]+>/
6
+
7
+ setup do
8
+ @data = User.new(1, 'foobar', 'male')
9
+
10
+ @context = Context.new
11
+ @context.assigns['data'] = @data
12
+
13
+ @template = RablRails::CompiledTemplate.new
14
+ @template.data = :@data
15
+ @template.root_name = :user
16
+ end
17
+
18
+ def render_plist_output
19
+ output = RablRails::Renderers::PLIST.new(@context).render(@template).to_s.gsub!(INDENT_REGEXP, '')
20
+ output.sub!(HEADER_REGEXP, '').gsub!(%r(</?plist[^>]*>), '').sub!(%r(<dict/?>), '').sub(%r(</dict>), '')
21
+ end
22
+
23
+ test "plist engine should responsd to #dump" do
24
+ assert_raises(RuntimeError) { RablRails.plist_engine = Object.new }
25
+ end
26
+
27
+ test "render object wth empty template" do
28
+ @template.source = {}
29
+ assert_equal %q(), render_plist_output
30
+ end
31
+
32
+ test "render collection with empty template" do
33
+ @context.assigns['data'] = [@data]
34
+ @template.source = {}
35
+ assert_equal %q(<array></array>), render_plist_output
36
+ end
37
+
38
+ test "render object with local methods (used by decent_exposure)" do
39
+ @context.stub(:user).and_return(@data)
40
+ @template.data = :user
41
+ @template.source = { :id => :id }
42
+ assert_equal %q(<key>id</key><integer>1</integer>), render_plist_output
43
+ end
44
+
45
+ test "render single object attributes" do
46
+ @template.source = { :id => :id, :name => :name }
47
+ assert_equal %q(<key>id</key><integer>1</integer><key>name</key><string>foobar</string>), render_plist_output
48
+ end
49
+
50
+ test "render child with object association" do
51
+ @data.stub(:address).and_return(mock(:city => 'Paris'))
52
+ @template.source = { :address => { :_data => :address, :city => :city } }
53
+ assert_equal %q(<key>address</key><dict><key>city</key><string>Paris</string></dict>), render_plist_output
54
+ end
55
+
56
+ test "render child with arbitrary data source" do
57
+ @template.source = { :author => { :_data => :@data, :name => :name } }
58
+ assert_equal %q(<key>author</key><dict><key>name</key><string>foobar</string></dict>), render_plist_output
59
+ end
60
+
61
+ test "render child with local methods (used by decent_exposure)" do
62
+ @context.stub(:user).and_return(@data)
63
+ @template.source = { :author => { :_data => :user, :name => :name } }
64
+ assert_equal %q(<key>author</key><dict><key>name</key><string>foobar</string></dict>), render_plist_output
65
+ end
66
+
67
+ test "render node property" do
68
+ proc = lambda { |object| object.name }
69
+ @template.source = { :name => proc }
70
+ assert_equal %q(<key>name</key><string>foobar</string>), render_plist_output
71
+ end
72
+
73
+ test "render node property with true condition" do
74
+ condition = lambda { |u| true }
75
+ proc = lambda { |object| object.name }
76
+ @template.source = { :name => [condition, proc] }
77
+ assert_equal %q(<key>name</key><string>foobar</string>), render_plist_output
78
+ end
79
+
80
+ test "render node property with false condition" do
81
+ condition = lambda { |u| false }
82
+ proc = lambda { |object| object.name }
83
+ @template.source = { :name => [condition, proc] }
84
+ assert_equal %q(), render_plist_output
85
+ end
86
+
87
+ test "node with context method call" do
88
+ @context.stub(:respond_to?).with(:@data).and_return(false)
89
+ @context.stub(:respond_to?).with(:context_method).and_return(true)
90
+ @context.stub(:context_method).and_return('marty')
91
+ proc = lambda { |object| context_method }
92
+ @template.source = { :name => proc }
93
+ assert_equal %q(<key>name</key><string>marty</string>), render_plist_output
94
+ end
95
+
96
+ test "partial with no values should raise an error" do
97
+ @template.data = false
98
+ @template.source = { :user => ->(s) { partial('users/base') } }
99
+
100
+ assert_raises(RablRails::Renderers::PartialError) { render_plist_output }
101
+ end
102
+
103
+ test "partial with empty values should not raise an error" do
104
+ @template.data = false
105
+ @template.source = { :users => ->(s) { partial('users/base', :object => []) } }
106
+
107
+ assert_equal %q(<key>users</key><array/>), render_plist_output
108
+ end
109
+
110
+ test "condition blocks are transparent if the condition passed" do
111
+ c = RablRails::Condition.new(->(u) { true }, { :name => :name })
112
+ @template.source = { :_if0 => c }
113
+ assert_equal %q(<key>name</key><string>foobar</string>), render_plist_output
114
+ end
115
+
116
+ test "condition blocks are ignored if the condition is not met" do
117
+ c = RablRails::Condition.new(->(u) { false }, { :name => :name })
118
+ @template.source = { :_if0 => c }
119
+ assert_equal %q(), render_plist_output
120
+ end
121
+
122
+ test "render object with root node" do
123
+ RablRails.include_plist_root = true
124
+ @template.root_name = :author
125
+ @template.source = { :id => :id, :name => :name }
126
+ assert_equal %q(<key>author</key><dict><key>id</key><integer>1</integer><key>name</key><string>foobar</string></dict>), render_plist_output
127
+ end
128
+
129
+ test "render object with root options set to false" do
130
+ RablRails.include_plist_root = false
131
+ @template.root_name = :author
132
+ @template.source = { :id => :id, :name => :name }
133
+ assert_equal %q(<key>id</key><integer>1</integer><key>name</key><string>foobar</string>), render_plist_output
134
+ end
135
+ end
data/test/test_helper.rb CHANGED
@@ -22,6 +22,15 @@ class <<Singleton
22
22
  end
23
23
 
24
24
  require 'rabl-rails'
25
+ require 'plist'
26
+
27
+ if RUBY_ENGINE == 'jruby'
28
+ require 'nokogiri'
29
+ else
30
+ require 'libxml'
31
+ end
32
+
33
+ RablRails.load_default_engines!
25
34
 
26
35
  module ActiveSupport
27
36
  class TestCase
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.2.2
4
+ version: 0.3.0
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: 2012-10-05 00:00:00.000000000 Z
12
+ date: 2012-11-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -67,6 +67,7 @@ extensions: []
67
67
  extra_rdoc_files: []
68
68
  files:
69
69
  - .gitignore
70
+ - .travis.yml
70
71
  - CHANGELOG.md
71
72
  - Gemfile
72
73
  - MIT-LICENSE
@@ -81,6 +82,7 @@ files:
81
82
  - lib/rabl-rails/renderer.rb
82
83
  - lib/rabl-rails/renderers/base.rb
83
84
  - lib/rabl-rails/renderers/json.rb
85
+ - lib/rabl-rails/renderers/plist.rb
84
86
  - lib/rabl-rails/renderers/xml.rb
85
87
  - lib/rabl-rails/responder.rb
86
88
  - lib/rabl-rails/template.rb
@@ -90,9 +92,11 @@ files:
90
92
  - test/cache_templates_test.rb
91
93
  - test/compiler_test.rb
92
94
  - test/deep_nesting_test.rb
95
+ - test/keyword_test.rb
93
96
  - test/non_restful_response_test.rb
94
97
  - test/render_test.rb
95
98
  - test/renderers/json_renderer_test.rb
99
+ - test/renderers/plist_renderer_test.rb
96
100
  - test/renderers/xml_renderer_test.rb
97
101
  - test/test_helper.rb
98
102
  homepage: https://github.com/ccocchi/rabl-rails
@@ -123,8 +127,10 @@ test_files:
123
127
  - test/cache_templates_test.rb
124
128
  - test/compiler_test.rb
125
129
  - test/deep_nesting_test.rb
130
+ - test/keyword_test.rb
126
131
  - test/non_restful_response_test.rb
127
132
  - test/render_test.rb
128
133
  - test/renderers/json_renderer_test.rb
134
+ - test/renderers/plist_renderer_test.rb
129
135
  - test/renderers/xml_renderer_test.rb
130
136
  - test/test_helper.rb