rabl-rails 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,7 +1,10 @@
1
- .bundle/
2
- log/*.log
3
- pkg/
4
- test/dummy/db/*.sqlite3
5
- test/dummy/log/*.log
6
- test/dummy/tmp/
7
- test/dummy/.sass-cache
1
+ ## General
2
+ log
3
+ doc
4
+ rdoc
5
+
6
+ ## Bundler
7
+ .bundle
8
+ pkg
9
+ Gemfile.lock
10
+
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.1.2
4
+ * Add RablRails#render method (see README or source code)
5
+ * Fix fail when JSON engine is not found. Now fallback to MultiJson.default_adapter
6
+ * Warning message printed on logger when JSON engine fail to load
7
+
3
8
  ## 0.1.1
4
9
 
5
10
  * Add CHANGELOG
data/README.md CHANGED
@@ -81,6 +81,20 @@ The same rule applies for view helpers such as `current_user`
81
81
 
82
82
  After the template is compiled into a hash, Rabl-rails will use a renderer to do the actual output. Actually, only JSON and XML formats are supported.
83
83
 
84
+ ## Configuration
85
+
86
+ RablRails works out of the box, with default options and fastest engine available (yajl, libxml). But depending on your needs, you might want to change that or how your output looks like. You can set global configuration in your application:
87
+
88
+ ```ruby
89
+ # config/initializers/rabl_rails.rb
90
+ RablRails.configure do |config|
91
+ # These are the default
92
+ # config.cache_templates = true
93
+ # config.include_json_root = true
94
+ # config.json_engine = :yajl
95
+ end
96
+ ```
97
+
84
98
  ## Usage
85
99
 
86
100
  ### Data declaration
@@ -218,6 +232,22 @@ child :posts do
218
232
  end
219
233
  ```
220
234
 
235
+ ### Caching
236
+
237
+ Caching is not a part of Rabl-rails. It is already in Rails itself, because caching all view output is the same as action caching (Rails caching is even better because it will also not run your queries).
238
+
239
+ Moreover caching each object in a collection can be really not effective with big collections or simple objects. This is also a nightmare with cache expiration.
240
+
241
+ ### Render object directly
242
+
243
+ There are cases when you want to render object outside Rails view context. For instance to render objects in the console or to create message queue payloads. For these situations, you can use `RablRails.render` as show below:
244
+
245
+ ```ruby
246
+ Rabl.render(object, template, :view_path => 'app/views', :format => :json) #=> "{...}"
247
+ ```
248
+
249
+ You can find more informations about how to use this method in the [wiki](http://github.com/ccocchi/rabl-rails/wiki/Render-object-directly)
250
+
221
251
  ## Performance
222
252
 
223
253
  Benchmarks have been made using this [application](http://github.com/ccocchi/rabl-benchmark), with rabl 0.6.14 and rabl-rails 0.1.0
@@ -226,12 +256,6 @@ Overall, Rabl-rails is **20% faster and use 10% less memory**.
226
256
 
227
257
  You can see full tests on test application repository.
228
258
 
229
- ## Caching
230
-
231
- Caching is not a part of Rabl-rails. It is already in Rails itself, because caching all view output is the same as action caching (Rails caching is even better because it will also not run your queries).
232
-
233
- And caching each object in a collection can be really not effective with big collections or simple objects. This is also a nightmare with cache expiration.
234
-
235
259
  ## Authors and contributors
236
260
 
237
261
  * [Christopher Cocchi-Perrier](http://github.com/ccocchi) - Creator of the project
data/lib/rabl-rails.rb CHANGED
@@ -16,26 +16,33 @@ require 'rabl-rails/railtie'
16
16
  require 'multi_json'
17
17
 
18
18
  module RablRails
19
+ extend Renderer
20
+
19
21
  mattr_accessor :cache_templates
20
22
  @@cache_templates = true
21
23
 
22
24
  mattr_accessor :include_json_root
23
25
  @@include_json_root = true
24
26
 
25
- mattr_accessor :json_engine
27
+ mattr_reader :json_engine
26
28
  @@json_engine = :yajl
27
29
 
28
30
  def self.configure
29
31
  yield self
30
- post_configure
31
32
  end
32
-
33
+
34
+ def self.json_engine=(name)
35
+ MultiJson.engine = name
36
+ @@json_engine = name
37
+ rescue LoadError
38
+ Rails.logger.warn %Q(WARNING: rabl-rails could not load "#{self.json_engine}" as JSON engine, fallback to default)
39
+ end
40
+
33
41
  def self.cache_templates?
34
42
  ActionController::Base.perform_caching && @@cache_templates
35
43
  end
36
-
37
- private
38
- def self.post_configure
39
- MultiJson.engine = self.json_engine
44
+
45
+ def self.load_default_engines!
46
+ self.json_engine = :yajl
40
47
  end
41
48
  end
@@ -1,6 +1,8 @@
1
1
  module RablRails
2
2
  class Railtie < Rails::Railtie
3
3
  initializer "rabl.initialize" do |app|
4
+ RablRails.load_default_engines!
5
+
4
6
  ActiveSupport.on_load(:action_view) do
5
7
  ActionView::Template.register_template_handler :rabl, RablRails::Handlers::Rabl
6
8
  end
@@ -1,2 +1,91 @@
1
1
  require 'rabl-rails/renderers/base'
2
- require 'rabl-rails/renderers/json'
2
+ require 'rabl-rails/renderers/json'
3
+
4
+ module RablRails
5
+ module Renderer
6
+ class TemplateNotFound < StandardError; end
7
+
8
+ mattr_reader :view_path
9
+ @@view_path = 'app/views'
10
+
11
+ class LookupContext
12
+ T = Struct.new(:source)
13
+
14
+ def initialize(view_path, format)
15
+ @view_path = view_path || RablRails::Renderer.view_path
16
+ @format = format
17
+ end
18
+
19
+ #
20
+ # Manually find given rabl template file with given format.
21
+ # View path can be set via options, otherwise default Rails
22
+ # path is used
23
+ #
24
+ def find_template(name, opt, partial = false)
25
+ path = File.join(@view_path, "#{name}.#{@format}.rabl")
26
+ File.exists?(path) ? T.new(File.read(path)) : nil
27
+ end
28
+ end
29
+
30
+ #
31
+ # Context class to emulate normal Rails view
32
+ # context
33
+ #
34
+ class Context
35
+ attr_reader :format
36
+ attr_accessor :target_object
37
+
38
+ def initialize(path, options)
39
+ @virtual_path = path
40
+ @format = options.delete(:format) || 'json'
41
+ @_assigns = {}
42
+ @options = options
43
+
44
+ options[:locals].each { |k, v| @_assigns[k.to_s] = v } if options[:locals]
45
+ end
46
+
47
+ def assigns
48
+ @_assigns
49
+ end
50
+
51
+ def params
52
+ { format: format }
53
+ end
54
+
55
+ def lookup_context
56
+ @lookup_context ||= LookupContext.new(@options[:view_path], format)
57
+ end
58
+ end
59
+
60
+ #
61
+ # Renders object with the given rabl template.
62
+ #
63
+ # Object can also be passed as an option :
64
+ # { locals: { object: obj_to_render } }
65
+ #
66
+ # Default render format is JSON, but can be changed via
67
+ # an option: { format: 'xml' }
68
+ #
69
+ # If template includes uses of instance variables (usually
70
+ # defined in the controller), you can passed them as locals
71
+ # options.
72
+ # For example, if you have this template:
73
+ # object :@user
74
+ # node(:read) { |u| u.has_read?(@post) }
75
+ #
76
+ # Your method call should look like this:
77
+ # RablRails.render(user, 'users/show', locals: { post: Post.new })
78
+ #
79
+ def render(object, template, options = {})
80
+ object = options[:locals].delete(:object) if !object && options[:locals]
81
+
82
+ c = Context.new(template, options)
83
+ c.target_object = object
84
+
85
+ t = c.lookup_context.find_template(template, [], false)
86
+ raise TemplateNotFound unless t
87
+
88
+ Library.instance.get_rendered_template(t.source, c)
89
+ end
90
+ end
91
+ end
@@ -19,6 +19,7 @@ module RablRails
19
19
  #
20
20
  def render(template)
21
21
  collection_or_resource = instance_variable_get(template.data) if template.data
22
+ collection_or_resource = @_context.target_object unless collection_or_resource || template.data == false || !@_context.respond_to?(:target_object)
22
23
  output_hash = collection_or_resource.respond_to?(:each) ? render_collection(collection_or_resource, template.source) :
23
24
  render_resource(collection_or_resource, template.source)
24
25
  _options[:root_name] = template.root_name
@@ -1,3 +1,3 @@
1
1
  module RablRails
2
- VERSION = '0.1.1'
2
+ VERSION = '0.1.2'
3
3
  end
@@ -0,0 +1,64 @@
1
+ require 'test_helper'
2
+ require 'pathname'
3
+ require 'tmpdir'
4
+
5
+ class RenderTest < ActiveSupport::TestCase
6
+
7
+ setup do
8
+ @user = User.new(1, 'Marty')
9
+ @user.stub(:respond_to?).with(:each).and_return(false)
10
+ @tmp_path = Pathname.new(Dir.mktmpdir)
11
+ end
12
+
13
+ test "allow object to be passed as an option" do
14
+ File.open(@tmp_path + "nil.json.rabl", "w") do |f|
15
+ f.puts %q{
16
+ object :@user
17
+ attributes :name
18
+ }
19
+ end
20
+ assert_equal %q({"user":{"name":"Marty"}}), RablRails.render(nil, 'nil', locals: { object: @user }, view_path: @tmp_path)
21
+ end
22
+
23
+ test "load source from file" do
24
+ File.open(@tmp_path + "show.json.rabl", "w") do |f|
25
+ f.puts %q{
26
+ object :@user
27
+ attributes :id, :name
28
+ }
29
+ end
30
+ assert_equal %q({"user":{"id":1,"name":"Marty"}}), RablRails.render(@user, 'show', view_path: @tmp_path)
31
+ end
32
+
33
+ test "raise error if template is not found" do
34
+ assert_raises(RablRails::Renderer::TemplateNotFound) { RablRails.render(@user, 'not_found') }
35
+ end
36
+
37
+ test "instance variables can be passed via options[:locals]" do
38
+ File.open(@tmp_path + "instance.json.rabl", "w") do |f|
39
+ f.puts %q{
40
+ object false
41
+ node(:username) { |_| @user.name }
42
+ }
43
+ end
44
+ assert_equal %q({"username":"Marty"}), RablRails.render(nil, 'instance', view_path: @tmp_path, locals: { user: @user })
45
+ end
46
+
47
+ test "handle path for extends" do
48
+ File.open(@tmp_path + "extend.json.rabl", "w") do |f|
49
+ f.puts %q{
50
+ object :@user
51
+ extends 'base'
52
+ }
53
+ end
54
+
55
+ File.open(@tmp_path + "base.json.rabl", "w") do |f|
56
+ f.puts %q{
57
+ attribute :name, as: :extended_name
58
+ }
59
+ end
60
+
61
+ assert_equal %q({"user":{"extended_name":"Marty"}}), RablRails.render(@user, 'extend', view_path: @tmp_path)
62
+ end
63
+
64
+ 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.1.1
4
+ version: 0.1.2
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-07-25 00:00:00.000000000 Z
12
+ date: 2012-08-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -69,7 +69,6 @@ files:
69
69
  - .gitignore
70
70
  - CHANGELOG.md
71
71
  - Gemfile
72
- - Gemfile.lock
73
72
  - MIT-LICENSE
74
73
  - README.md
75
74
  - Rakefile
@@ -89,6 +88,7 @@ files:
89
88
  - test/compiler_test.rb
90
89
  - test/deep_nesting_test.rb
91
90
  - test/non_restful_response_test.rb
91
+ - test/render_test.rb
92
92
  - test/renderers/json_renderer_test.rb
93
93
  - test/test_helper.rb
94
94
  homepage: https://github.com/ccocchi/rabl-rails
@@ -111,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
111
  version: '0'
112
112
  requirements: []
113
113
  rubyforge_project:
114
- rubygems_version: 1.8.22
114
+ rubygems_version: 1.8.21
115
115
  signing_key:
116
116
  specification_version: 3
117
117
  summary: Fast Rails 3+ templating system with JSON and XML support
@@ -120,5 +120,6 @@ test_files:
120
120
  - test/compiler_test.rb
121
121
  - test/deep_nesting_test.rb
122
122
  - test/non_restful_response_test.rb
123
+ - test/render_test.rb
123
124
  - test/renderers/json_renderer_test.rb
124
125
  - test/test_helper.rb
data/Gemfile.lock DELETED
@@ -1,67 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- rabl-rails (0.1.0)
5
- activesupport (~> 3.0)
6
- railties (~> 3.0)
7
-
8
- GEM
9
- remote: http://rubygems.org/
10
- specs:
11
- actionpack (3.2.6)
12
- activemodel (= 3.2.6)
13
- activesupport (= 3.2.6)
14
- builder (~> 3.0.0)
15
- erubis (~> 2.7.0)
16
- journey (~> 1.0.1)
17
- rack (~> 1.4.0)
18
- rack-cache (~> 1.2)
19
- rack-test (~> 0.6.1)
20
- sprockets (~> 2.1.3)
21
- activemodel (3.2.6)
22
- activesupport (= 3.2.6)
23
- builder (~> 3.0.0)
24
- activesupport (3.2.6)
25
- i18n (~> 0.6)
26
- multi_json (~> 1.0)
27
- builder (3.0.0)
28
- erubis (2.7.0)
29
- hike (1.2.1)
30
- i18n (0.6.0)
31
- journey (1.0.4)
32
- json (1.7.3)
33
- multi_json (1.3.6)
34
- rack (1.4.1)
35
- rack-cache (1.2)
36
- rack (>= 0.4)
37
- rack-ssl (1.3.2)
38
- rack
39
- rack-test (0.6.1)
40
- rack (>= 1.0)
41
- railties (3.2.6)
42
- actionpack (= 3.2.6)
43
- activesupport (= 3.2.6)
44
- rack-ssl (~> 1.3.2)
45
- rake (>= 0.8.7)
46
- rdoc (~> 3.4)
47
- thor (>= 0.14.6, < 2.0)
48
- rake (0.9.2.2)
49
- rdoc (3.12)
50
- json (~> 1.4)
51
- rspec-mocks (2.11.1)
52
- sprockets (2.1.3)
53
- hike (~> 1.2)
54
- rack (~> 1.0)
55
- tilt (~> 1.1, != 1.3.0)
56
- thor (0.15.4)
57
- tilt (1.3.3)
58
- yajl-ruby (1.1.0)
59
-
60
- PLATFORMS
61
- ruby
62
-
63
- DEPENDENCIES
64
- actionpack (~> 3.0)
65
- rabl-rails!
66
- rspec-mocks
67
- yajl-ruby