rabl 0.5.5.b → 0.5.5.c

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,10 @@
1
1
  # CHANGELOG
2
2
 
3
- ## 0.5.5.a-b
3
+ ## 0.5.5.a-c
4
4
 
5
5
  * Change engine to only instantiate one builder when rendering a collection
6
6
  * Alias to\_msgpack to to\_mpac
7
+ * Cache template sources for faster partial lookups
7
8
 
8
9
  ## 0.5.4
9
10
 
@@ -6,6 +6,7 @@ require 'active_support/core_ext/hash/slice'
6
6
 
7
7
  require 'rabl/version'
8
8
  require 'rabl/helpers'
9
+ require 'rabl/partials'
9
10
  require 'rabl/engine'
10
11
  require 'rabl/builder'
11
12
  require 'rabl/configuration'
@@ -14,6 +15,7 @@ require 'rabl/railtie' if defined?(Rails) && Rails.version =~ /^3/
14
15
  # Rabl.register!
15
16
  module Rabl
16
17
  class << self
18
+
17
19
  def register!
18
20
  require 'rabl/template'
19
21
  end
@@ -38,6 +40,25 @@ module Rabl
38
40
  def reset_configuration!
39
41
  @_configuration = nil
40
42
  end
43
+
44
+ # Fetches from the source_cache, stores block result in cache if nil
45
+ # Used to cache the contents and paths to various rabl templates
46
+ # source_cache("users/index", "path/to/view") { "/full/path/to/template/users/index" }
47
+ def source_cache(file, view_path, &block)
48
+ @_source_cache ||= {}
49
+ cache_key = [file, view_path].compact.join(":")
50
+ if cached_result = @_source_cache[cache_key]
51
+ cached_result
52
+ else # store result of block
53
+ @_source_cache[cache_key] = yield
54
+ end
55
+ end
56
+
57
+ # Resets the RABL source cache
58
+ def reset_source_cache!
59
+ @_source_cache = {}
60
+ end
61
+
41
62
  end
42
63
  end
43
64
 
@@ -1,6 +1,6 @@
1
1
  module Rabl
2
2
  class Builder
3
- include Rabl::Helpers
3
+ include Rabl::Partials
4
4
 
5
5
  # Constructs a new rabl hash based on given object and options
6
6
  # options = { :format => "json", :attributes, :root => true,
@@ -15,7 +15,6 @@ module Rabl
15
15
  def build(data, options={})
16
16
  @_data = data
17
17
  @_object = data_object(data)
18
- @_result = {}
19
18
  compile_hash(options)
20
19
  end
21
20
 
@@ -24,6 +23,7 @@ module Rabl
24
23
  # Returns a hash representation of the data object
25
24
  # compile_hash(:root => true)
26
25
  def compile_hash(options={})
26
+ @_result = {}
27
27
  # Extends
28
28
  @options[:extends].each do |settings|
29
29
  extends(settings[:file], settings[:options], &settings[:block])
@@ -107,5 +107,17 @@ module Rabl
107
107
  result = self.partial(file, options, &block)
108
108
  @_result.merge!(result) if result
109
109
  end
110
+
111
+ protected
112
+
113
+ # resolve_condition(:if => true) => true
114
+ # resolve_condition(:if => lambda { |m| false }) => false
115
+ # resolve_condition(:unless => lambda { |m| true }) => true
116
+ def resolve_condition(options)
117
+ return true if options[:if].nil? && options[:unless].nil?
118
+ result = options[:if] == true || (options[:if].respond_to?(:call) && options[:if].call(@_object)) if options.has_key?(:if)
119
+ result = options[:unless] == false || (options[:unless].respond_to?(:call) && !options[:unless].call(@_object)) if options.has_key?(:unless)
120
+ result
121
+ end
110
122
  end
111
123
  end
@@ -1,6 +1,6 @@
1
1
  module Rabl
2
2
  class Engine
3
- include Rabl::Helpers
3
+ include Rabl::Partials
4
4
 
5
5
  # Constructs a new ejs engine based on given vars, handler and declarations
6
6
  # Rabl::Engine.new("...source...", { :format => "xml", :root => true, :view_path => "/path/to/views" })
@@ -193,6 +193,7 @@ module Rabl
193
193
  end
194
194
 
195
195
  private
196
+
196
197
  def clear_compile_state
197
198
  @_options.delete(:extends)
198
199
  @_options.delete(:attributes)
@@ -1,5 +1,6 @@
1
1
  module Rabl
2
2
  module Helpers
3
+
3
4
  # data_object(data) => <AR Object>
4
5
  # data_object(@user => :person) => @user
5
6
  # data_object(:user => :person) => @_object.send(:user)
@@ -26,38 +27,6 @@ module Rabl
26
27
  end
27
28
  end
28
29
 
29
- # Renders a partial hash based on another rabl template
30
- # partial("users/show", :object => @user)
31
- # options must have :object
32
- # options can have :view_path, :child_root, :root
33
- def partial(file, options={}, &block)
34
- object, view_path = options.delete(:object), options.delete(:view_path)
35
- source, location = self.fetch_source(file, :view_path => view_path)
36
- engine_options = options.merge(:source => source, :source_location => location)
37
- self.object_to_hash(object, engine_options, &block)
38
- end
39
-
40
- # Returns a hash based representation of any data object given ejs template block
41
- # object_to_hash(@user) { attribute :full_name } => { ... }
42
- # object_to_hash(@user, :source => "...") { attribute :full_name } => { ... }
43
- # options must have :source (rabl file contents)
44
- # options can have :source_location (source filename)
45
- def object_to_hash(object, options={}, &block)
46
- return object unless is_object?(object) || is_collection?(object)
47
- engine_options = options.merge(:format => "hash", :root => (options[:root] || false))
48
- Rabl::Engine.new(options[:source], engine_options).render(@_scope, :object => object, &block)
49
- end
50
-
51
- # resolve_condition(:if => true) => true
52
- # resolve_condition(:if => lambda { |m| false }) => false
53
- # resolve_condition(:unless => lambda { |m| true }) => true
54
- def resolve_condition(options)
55
- return true if options[:if].nil? && options[:unless].nil?
56
- result = options[:if] == true || (options[:if].respond_to?(:call) && options[:if].call(@_object)) if options.has_key?(:if)
57
- result = options[:unless] == false || (options[:unless].respond_to?(:call) && !options[:unless].call(@_object)) if options.has_key?(:unless)
58
- result
59
- end
60
-
61
30
  # Returns true if obj is not enumerable
62
31
  # is_object?(@user) => true
63
32
  # is_object?([]) => false
@@ -71,29 +40,5 @@ module Rabl
71
40
  obj && data_object(obj).respond_to?(:each)
72
41
  end
73
42
 
74
- # Returns source for a given relative file
75
- # fetch_source("show", :view_path => "...") => "...contents..."
76
- def fetch_source(file, options={})
77
- if defined? Rails
78
- root_path = Rails.root
79
- view_path = options[:view_path] || File.join(root_path, "app/views/")
80
- file_path = Dir[File.join(view_path, file + ".{*.,}rabl")].first
81
- elsif defined? Padrino
82
- root_path = Padrino.root
83
- # use Padrino's own template resolution mechanism
84
- file_path, _ = @_scope.instance_eval { resolve_template(file) }
85
- # Padrino chops the extension, stitch it back on
86
- file_path = File.join(@_scope.settings.views, (file_path.to_s + ".rabl"))
87
- elsif defined? Sinatra
88
- view_path = options[:view_path] || @_scope.settings.views
89
- file_path = Dir[File.join(view_path, file + ".{*.,}rabl")].first
90
- end
91
-
92
- if file_path
93
- return File.read(file_path.to_s), file_path.to_s
94
- else # no file path specified
95
- nil
96
- end
97
- end
98
43
  end
99
44
  end
@@ -0,0 +1,51 @@
1
+ module Rabl
2
+ module Partials
3
+ include Rabl::Helpers
4
+
5
+ # Renders a partial hash based on another rabl template
6
+ # partial("users/show", :object => @user)
7
+ # options must have :object
8
+ # options can have :view_path, :child_root, :root
9
+ def partial(file, options={}, &block)
10
+ object, view_path = options.delete(:object), options.delete(:view_path)
11
+ source, location = self.fetch_source(file, :view_path => view_path)
12
+ engine_options = options.merge(:source => source, :source_location => location)
13
+ self.object_to_hash(object, engine_options, &block)
14
+ end
15
+
16
+ # Returns a hash based representation of any data object given ejs template block
17
+ # object_to_hash(@user) { attribute :full_name } => { ... }
18
+ # object_to_hash(@user, :source => "...") { attribute :full_name } => { ... }
19
+ # options must have :source (rabl file contents)
20
+ # options can have :source_location (source filename)
21
+ def object_to_hash(object, options={}, &block)
22
+ return object unless is_object?(object) || is_collection?(object)
23
+ engine_options = options.merge(:format => "hash", :root => (options[:root] || false))
24
+ Rabl::Engine.new(options[:source], engine_options).render(@_scope, :object => object, &block)
25
+ end
26
+
27
+ # Returns source for a given relative file
28
+ # fetch_source("show", :view_path => "...") => "...contents..."
29
+ def fetch_source(file, options={})
30
+ Rabl.source_cache(file, options[:view_path]) do
31
+ if defined? Padrino
32
+ root_path = Padrino.root
33
+ # use Padrino's own template resolution mechanism
34
+ file_path, _ = @_scope.instance_eval { resolve_template(file) }
35
+ # Padrino chops the extension, stitch it back on
36
+ file_path = File.join(@_scope.settings.views, (file_path.to_s + ".rabl"))
37
+ elsif defined? Rails
38
+ root_path = Rails.root
39
+ view_path = options[:view_path] || File.join(root_path, "app/views/")
40
+ file_path = Dir[File.join(view_path, file + ".{*.,}rabl")].first
41
+ elsif defined? Sinatra
42
+ view_path = options[:view_path] || @_scope.settings.views
43
+ file_path = Dir[File.join(view_path, file + ".{*.,}rabl")].first
44
+ end
45
+
46
+ [File.read(file_path.to_s), file_path.to_s] if file_path
47
+ end
48
+ end
49
+
50
+ end # Partials
51
+ end # Rabl
@@ -1,3 +1,3 @@
1
1
  module Rabl
2
- VERSION = "0.5.5.b"
2
+ VERSION = "0.5.5.c"
3
3
  end
@@ -2,67 +2,10 @@ require 'tmpdir'
2
2
  require 'pathname'
3
3
  require File.expand_path('../../lib/rabl', __FILE__)
4
4
 
5
- class TestHelper
5
+ class TestPartial
6
6
  include Rabl::Helpers
7
7
  end
8
8
 
9
9
  context "Rabl::Helpers" do
10
- context "fetch_source" do
11
- helper(:tmp_path) { @tmp_path ||= Pathname.new(Dir.mktmpdir) }
12
-
13
- setup do
14
- ::Rails = stub(Class.new)
15
- ::Rails.root.returns(tmp_path)
16
- File.open(tmp_path + "test.json.rabl", "w") do |f|
17
- f.puts "content"
18
- end
19
- File.open(tmp_path + "test_v1.json.rabl", "w") do |f|
20
- f.puts "content_v1"
21
- end
22
- FileUtils.touch tmp_path + "test_v2.json.rabl"
23
- [TestHelper.new.fetch_source('test', :view_path => tmp_path.to_s),
24
- TestHelper.new.fetch_source('test_v1', :view_path => tmp_path.to_s)]
25
- end
26
-
27
- asserts(:first).equals {["content\n", (tmp_path + "test.json.rabl").to_s ]}
28
- asserts(:last).equals {["content_v1\n", (tmp_path + "test_v1.json.rabl").to_s ]}
29
- teardown { Object.send(:remove_const, :Rails) }
30
- end
31
-
32
- context "fetch_source" do
33
- helper(:tmp_path) { @tmp_path ||= Pathname.new(Dir.mktmpdir) }
34
-
35
- setup do
36
- ::Rails = stub(Class.new)
37
- ::Rails.root.returns(tmp_path)
38
- File.open(tmp_path + "test.rabl", "w") do |f|
39
- f.puts "content"
40
- end
41
- TestHelper.new.fetch_source('test', :view_path => tmp_path.to_s)
42
- end
43
- asserts('detects file.rabl') { topic }.equals do
44
- ["content\n", (tmp_path + 'test.rabl').to_s]
45
- end
46
- teardown { Object.send(:remove_const, :Rails) }
47
- end
48
-
49
- context "fetch_source" do
50
- helper(:tmp_path) { @tmp_path ||= Pathname.new(Dir.mktmpdir) }
51
-
52
- setup do
53
- ::Rails = stub(Class.new)
54
- ::Rails.root.returns(tmp_path)
55
- File.open(tmp_path + "test.rabl", "w") do |f|
56
- f.puts "content"
57
- end
58
- File.open(tmp_path + "test.json.rabl", "w") do |f|
59
- f.puts "content2"
60
- end
61
- TestHelper.new.fetch_source('test', :view_path => tmp_path.to_s)
62
- end
63
- asserts('detects file.json.rabl first') { topic }.equals do
64
- ["content2\n", (tmp_path + 'test.json.rabl').to_s]
65
- end
66
- teardown { Object.send(:remove_const, :Rails) }
67
- end
68
- end
10
+ # TODO needs tests
11
+ end
@@ -0,0 +1,68 @@
1
+ require 'tmpdir'
2
+ require 'pathname'
3
+ require File.expand_path('../../lib/rabl', __FILE__)
4
+
5
+ class TestPartial
6
+ include Rabl::Partials
7
+ end
8
+
9
+ context "Rabl::Partials" do
10
+ context "fetch_source" do
11
+ helper(:tmp_path) { @tmp_path ||= Pathname.new(Dir.mktmpdir) }
12
+
13
+ setup do
14
+ ::Rails = stub(Class.new)
15
+ ::Rails.root.returns(tmp_path)
16
+ File.open(tmp_path + "test.json.rabl", "w") do |f|
17
+ f.puts "content"
18
+ end
19
+ File.open(tmp_path + "test_v1.json.rabl", "w") do |f|
20
+ f.puts "content_v1"
21
+ end
22
+ FileUtils.touch tmp_path + "test_v2.json.rabl"
23
+ [TestPartial.new.fetch_source('test', :view_path => tmp_path.to_s),
24
+ TestPartial.new.fetch_source('test_v1', :view_path => tmp_path.to_s)]
25
+ end
26
+
27
+ asserts(:first).equals {["content\n", (tmp_path + "test.json.rabl").to_s ]}
28
+ asserts(:last).equals {["content_v1\n", (tmp_path + "test_v1.json.rabl").to_s ]}
29
+ teardown { Object.send(:remove_const, :Rails) }
30
+ end
31
+
32
+ context "fetch_source" do
33
+ helper(:tmp_path) { @tmp_path ||= Pathname.new(Dir.mktmpdir) }
34
+
35
+ setup do
36
+ ::Rails = stub(Class.new)
37
+ ::Rails.root.returns(tmp_path)
38
+ File.open(tmp_path + "test.rabl", "w") do |f|
39
+ f.puts "content"
40
+ end
41
+ TestPartial.new.fetch_source('test', :view_path => tmp_path.to_s)
42
+ end
43
+ asserts('detects file.rabl') { topic }.equals do
44
+ ["content\n", (tmp_path + 'test.rabl').to_s]
45
+ end
46
+ teardown { Object.send(:remove_const, :Rails) }
47
+ end
48
+
49
+ context "fetch_source" do
50
+ helper(:tmp_path) { @tmp_path ||= Pathname.new(Dir.mktmpdir) }
51
+
52
+ setup do
53
+ ::Rails = stub(Class.new)
54
+ ::Rails.root.returns(tmp_path)
55
+ File.open(tmp_path + "test.rabl", "w") do |f|
56
+ f.puts "content"
57
+ end
58
+ File.open(tmp_path + "test.json.rabl", "w") do |f|
59
+ f.puts "content2"
60
+ end
61
+ TestPartial.new.fetch_source('test', :view_path => tmp_path.to_s)
62
+ end
63
+ asserts('detects file.json.rabl first') { topic }.equals do
64
+ ["content2\n", (tmp_path + 'test.json.rabl').to_s]
65
+ end
66
+ teardown { Object.send(:remove_const, :Rails) }
67
+ end
68
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: rabl
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: 6
5
- version: 0.5.5.b
5
+ version: 0.5.5.c
6
6
  platform: ruby
7
7
  authors:
8
8
  - Nathan Esquenazi
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-02-10 00:00:00 Z
13
+ date: 2012-02-11 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: multi_json
@@ -245,6 +245,7 @@ files:
245
245
  - lib/rabl/configuration.rb
246
246
  - lib/rabl/engine.rb
247
247
  - lib/rabl/helpers.rb
248
+ - lib/rabl/partials.rb
248
249
  - lib/rabl/railtie.rb
249
250
  - lib/rabl/template.rb
250
251
  - lib/rabl/version.rb
@@ -260,6 +261,7 @@ files:
260
261
  - test/models/ormless.rb
261
262
  - test/models/user.rb
262
263
  - test/msgpack_engine_test.rb
264
+ - test/partials_test.rb
263
265
  - test/silence.rb
264
266
  - test/template_test.rb
265
267
  - test/teststrap.rb
@@ -286,7 +288,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
286
288
  requirements: []
287
289
 
288
290
  rubyforge_project: rabl
289
- rubygems_version: 1.8.12
291
+ rubygems_version: 1.8.15
290
292
  signing_key:
291
293
  specification_version: 3
292
294
  summary: General ruby templating for json or xml
@@ -301,6 +303,7 @@ test_files:
301
303
  - test/models/ormless.rb
302
304
  - test/models/user.rb
303
305
  - test/msgpack_engine_test.rb
306
+ - test/partials_test.rb
304
307
  - test/silence.rb
305
308
  - test/template_test.rb
306
309
  - test/teststrap.rb