rabl-rails 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,10 +4,21 @@ module RablRails
4
4
  ActiveSupport.on_load(:action_view) do
5
5
  ActionView::Template.register_template_handler :rabl, RablRails::Handlers::Rabl
6
6
  end
7
- end
8
7
 
9
- config.after_initialize do
10
- ActionController::Base.responder = RablRails::Responder if RablRails.configuration.use_custom_responder
8
+ if Rails::VERSION::MAJOR >= 5
9
+ module ::ActionController
10
+ module ApiRendering
11
+ include ActionView::Rendering
12
+ end
13
+ end
14
+
15
+ ActiveSupport.on_load :action_controller do
16
+ if self == ActionController::API
17
+ include ActionController::Helpers
18
+ include ActionController::ImplicitRender
19
+ end
20
+ end
21
+ end
11
22
  end
12
23
  end
13
24
  end
@@ -20,7 +20,6 @@ module RablRails
20
20
  visitor.instance_variable_get(template.data)
21
21
  end
22
22
  end
23
- collection_or_resource ||= locals[:resource] if locals
24
23
 
25
24
  render_with_cache(template.cache_key, collection_or_resource) do
26
25
  output_hash = if collection?(collection_or_resource)
@@ -82,4 +81,4 @@ module RablRails
82
81
  end
83
82
  end
84
83
  end
85
- end
84
+ end
@@ -3,8 +3,9 @@ module RablRails
3
3
  attr_accessor :nodes, :data, :root_name, :cache_key
4
4
 
5
5
  def initialize
6
- @nodes = []
7
- @cache_key = false
6
+ @nodes = []
7
+ @data = nil
8
+ @cache_key = false
8
9
  end
9
10
 
10
11
  def initialize_dup(other)
@@ -20,4 +21,4 @@ module RablRails
20
21
  @nodes.concat template.nodes
21
22
  end
22
23
  end
23
- end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module RablRails
2
- VERSION = '0.4.3'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -18,10 +18,6 @@ module Visitors
18
18
  @_result = {}
19
19
  end
20
20
 
21
- def visit_Array n
22
- n.each { |i| visit i }
23
- end
24
-
25
21
  def visit_Attribute n
26
22
  if !n.condition || instance_exec(_resource, &(n.condition))
27
23
  n.each { |k, v| @_result[k] = _resource.send(v) }
@@ -29,7 +25,7 @@ module Visitors
29
25
  end
30
26
 
31
27
  def visit_Child n
32
- object = object_from_data(_resource, n.data, n.instance_variable_data?)
28
+ object = object_from_data(_resource, n)
33
29
 
34
30
  @_result[n.name] = if object
35
31
  collection?(object) ? object.map { |o| sub_visit(o, n.nodes) } : sub_visit(object, n.nodes)
@@ -38,12 +34,17 @@ module Visitors
38
34
  end
39
35
  end
40
36
 
37
+ def visit_Glue n
38
+ object = object_from_data(_resource, n)
39
+ @_result.merge!(sub_visit(object, n.nodes)) if object
40
+ end
41
+
41
42
  def visit_Code n
42
43
  if !n.condition || instance_exec(_resource, &(n.condition))
43
44
  result = instance_exec _resource, &(n.block)
44
45
 
45
46
  if n.merge?
46
- raise RablRails::Renderer::PartialError, '`merge` block should return a hash' unless result.is_a?(Hash)
47
+ raise RablRails::PartialError, '`merge` block should return a hash' unless result.is_a?(Hash)
47
48
  @_result.merge!(result)
48
49
  else
49
50
  @_result[n.name] = result
@@ -55,9 +56,11 @@ module Visitors
55
56
  @_result.merge!(sub_visit(_resource, n.nodes)) if instance_exec _resource, &(n.condition)
56
57
  end
57
58
 
58
- def visit_Glue n
59
- object = object_from_data(_resource, n.data, n.instance_variable_data?)
60
- @_result.merge! sub_visit(object, n.template.nodes)
59
+ def visit_Extend n
60
+ @_locals = n.locals
61
+ @_result.merge!(sub_visit(_resource, n.nodes))
62
+ ensure
63
+ @_locals = {}
61
64
  end
62
65
 
63
66
  def result
@@ -65,13 +68,13 @@ module Visitors
65
68
  when 0
66
69
  @_result
67
70
  when 1
68
- @_result.each { |k, v| @_result[k] = '' if v == nil }
71
+ @_result.each { |k, v| @_result[k] = ''.freeze if v == nil }
69
72
  when 2, 3
70
- @_result.each { |k, v| @_result[k] = nil if v == '' }
73
+ @_result.each { |k, v| @_result[k] = nil if v == ''.freeze }
71
74
  when 4, 5
72
75
  @_result.delete_if { |_, v| v == nil }
73
76
  when 6
74
- @_result.delete_if { |_, v| v == nil || v == '' }
77
+ @_result.delete_if { |_, v| v == nil || v == ''.freeze }
75
78
  end
76
79
  end
77
80
 
@@ -95,7 +98,7 @@ module Visitors
95
98
  # rendering time).
96
99
  #
97
100
  def partial(template_path, options = {})
98
- raise RablRails::Renderer::PartialError.new("No object was given to partial #{template_path}") unless options[:object]
101
+ raise RablRails::PartialError.new("No object was given to partial #{template_path}") unless options[:object]
99
102
  object = options[:object]
100
103
  @_locals = options[:locals].freeze
101
104
 
@@ -115,7 +118,7 @@ module Visitors
115
118
 
116
119
  def copy_instance_variables_from_context
117
120
  @_context.instance_variable_get(:@_assigns).each_pair { |k, v|
118
- instance_variable_set("@#{k}", v) unless k.to_s.start_with?('_')
121
+ instance_variable_set("@#{k}", v) unless k.to_s.start_with?('_'.freeze)
119
122
  }
120
123
  end
121
124
 
@@ -128,10 +131,11 @@ module Visitors
128
131
  @_result, @_resource = old_result, old_resource
129
132
  end
130
133
 
131
- def object_from_data(resource, symbol, is_variable)
132
- return resource if symbol == nil
134
+ def object_from_data(resource, node)
135
+ return resource if node.data == nil
133
136
 
134
- if is_variable
137
+ symbol = node.data
138
+ if node.instance_variable_data?
135
139
  instance_variable_get(symbol)
136
140
  else
137
141
  resource.respond_to?(symbol) ? resource.send(symbol) : @_context.send(symbol)
@@ -1,7 +1,11 @@
1
1
  module Visitors
2
2
  class Visitor
3
3
  def visit(node)
4
- dispatch node
4
+ dispatch(node)
5
+ end
6
+
7
+ def visit_Array a
8
+ a.each { |n| dispatch(n) }
5
9
  end
6
10
 
7
11
  private
@@ -14,4 +18,4 @@ module Visitors
14
18
  send DISPATCH[node.class], node
15
19
  end
16
20
  end
17
- end
21
+ end
data/rabl-rails.gemspec CHANGED
@@ -8,17 +8,20 @@ Gem::Specification.new do |s|
8
8
  s.authors = ["Christopher Cocchi-Perrier"]
9
9
  s.email = ["cocchi.c@gmail.com"]
10
10
  s.homepage = "https://github.com/ccocchi/rabl-rails"
11
- s.summary = "Fast Rails 3+ templating system with JSON, XML and PList support"
12
- s.description = "Fast Rails 3+ templating system with JSON, XML and PList support"
11
+ s.summary = "Fast Rails 4+ templating system with JSON, XML and PList support"
12
+ s.description = "Fast Rails 4+ templating system with JSON, XML and PList support"
13
13
  s.license = 'MIT'
14
14
 
15
+ s.required_ruby_version = '>= 2.2.0'
16
+
15
17
  s.files = `git ls-files`.split("\n")
16
18
  s.test_files = `git ls-files -- test/*`.split("\n")
17
19
  s.require_paths = ["lib"]
18
20
 
19
- s.add_dependency 'activesupport', '>= 3.1'
20
- s.add_dependency 'railties', '>= 3.1'
21
- s.add_dependency 'thread_safe', '~> 0.3.1'
21
+ s.add_dependency 'activesupport', '>= 4.2'
22
+ s.add_dependency 'railties', '>= 4.2'
23
+ s.add_dependency 'concurrent-ruby', '~> 1.0.0'
22
24
 
23
- s.add_development_dependency 'actionpack', '>= 3.1'
25
+ s.add_development_dependency 'actionpack', '>= 4.2'
26
+ s.add_development_dependency 'actionview', '>= 4.2'
24
27
  end
data/test/helper.rb CHANGED
@@ -9,7 +9,6 @@ require 'rabl-rails'
9
9
  require 'plist'
10
10
  require 'action_dispatch/http/mime_type'
11
11
  require 'action_view'
12
- require 'active_support/core_ext/string/starts_ends_with'
13
12
 
14
13
  if RUBY_ENGINE == 'jruby'
15
14
  require 'nokogiri'
@@ -17,12 +16,6 @@ elsif RUBY_ENGINE == 'ruby'
17
16
  require 'libxml'
18
17
  end
19
18
 
20
- MINITEST_TEST_CLASS = if defined?(Minitest::Test)
21
- Minitest::Test
22
- else
23
- Minitest::Unit::TestCase
24
- end
25
-
26
19
  ActionView::Template.register_template_handler :rabl, RablRails::Handlers::Rabl
27
20
 
28
21
  module Configurable
@@ -35,7 +28,7 @@ module Configurable
35
28
  RablRails.configuration.send(accessor, old_value)
36
29
  end
37
30
  end
38
- MINITEST_TEST_CLASS.send(:include, Configurable)
31
+ Minitest::Test.send(:include, Configurable)
39
32
 
40
33
  module Rails
41
34
  def self.cache
@@ -1,9 +1,9 @@
1
1
  require 'helper'
2
2
 
3
- class TestHashRenderer < MINITEST_TEST_CLASS
3
+ class TestHashRenderer < Minitest::Test
4
4
  describe 'hash renderer' do
5
- def render(locals = nil)
6
- RablRails::Renderers::Hash.render(@template, @context, locals)
5
+ def render
6
+ RablRails::Renderers::Hash.render(@template, @context, {})
7
7
  end
8
8
 
9
9
  def with_cache
@@ -71,12 +71,6 @@ class TestHashRenderer < MINITEST_TEST_CLASS
71
71
  assert_equal({ name: 'Marty' }, render)
72
72
  end
73
73
 
74
- it "uses resource passed in locals if template don't have data" do
75
- @template.data = nil
76
- resource = User.new(2, 'Biff')
77
- assert_equal({ name: 'Biff' }, render(resource: resource))
78
- end
79
-
80
74
  it 'uses template root_name option' do
81
75
  @template.root_name = :user
82
76
  assert_equal({ user: { name: 'Marty' } }, render)
@@ -87,4 +81,4 @@ class TestHashRenderer < MINITEST_TEST_CLASS
87
81
  assert_equal([{ name: 'Marty' }], render)
88
82
  end
89
83
  end
90
- end
84
+ end
@@ -1,6 +1,6 @@
1
1
  require 'helper'
2
2
 
3
- class TestJSONRenderer < MINITEST_TEST_CLASS
3
+ class TestJSONRenderer < Minitest::Test
4
4
  describe 'JSON renderer' do
5
5
  def render
6
6
  RablRails::Renderers::JSON.render(@template, @context)
@@ -1,6 +1,6 @@
1
1
  require 'helper'
2
2
 
3
- class TestPListRenderer < MINITEST_TEST_CLASS
3
+ class TestPListRenderer < Minitest::Test
4
4
  INDENT_REGEXP = /\n(\s)*/
5
5
  HEADER_REGEXP = /<\?[^>]+><![^>]+>/
6
6
 
@@ -1,6 +1,6 @@
1
1
  require 'helper'
2
2
 
3
- class TestXMLRenderer < MINITEST_TEST_CLASS
3
+ class TestXMLRenderer < Minitest::Test
4
4
  INDENT_REGEXP = /\n(\s)*/
5
5
  HEADER_REGEXP = /<[^>]+>/
6
6
 
@@ -2,9 +2,15 @@ require 'helper'
2
2
  require 'pathname'
3
3
  require 'tmpdir'
4
4
 
5
- class TestCompiler < MINITEST_TEST_CLASS
5
+ class TestCompiler < Minitest::Test
6
6
  @@tmp_path = Pathname.new(Dir.mktmpdir)
7
7
 
8
+ File.open(@@tmp_path + 'user.rabl', 'w') do |f|
9
+ f.puts %q{
10
+ attributes :id
11
+ }
12
+ end
13
+
8
14
  describe 'compiler' do
9
15
  def extract_attributes(nodes)
10
16
  nodes.map(&:hash)
@@ -159,11 +165,7 @@ class TestCompiler < MINITEST_TEST_CLASS
159
165
  end
160
166
 
161
167
  it "compiles child with inline partial notation" do
162
- File.open(@@tmp_path + 'user.rabl', 'w') do |f|
163
- f.puts %q{
164
- attributes :id
165
- }
166
- end
168
+
167
169
 
168
170
  t = @compiler.compile_source(%{child(:user, :partial => 'user') })
169
171
  child_node = t.nodes.first
@@ -205,12 +207,17 @@ class TestCompiler < MINITEST_TEST_CLASS
205
207
  assert_equal(:foo, code_node.name)
206
208
  end
207
209
 
210
+ it "compiles glue with a partial" do
211
+ t = @compiler.compile_source(%{
212
+ glue(:@user, partial: 'user')
213
+ })
214
+
215
+ glue_node = t.nodes.first
216
+ assert_equal(1, glue_node.nodes.size)
217
+ assert_equal([{ :id => :id }], extract_attributes(glue_node.nodes))
218
+ end
219
+
208
220
  it "extends other template" do
209
- File.open(@@tmp_path + 'user.rabl', 'w') do |f|
210
- f.puts %q{
211
- attributes :id
212
- }
213
- end
214
221
  t = @compiler.compile_source(%{ extends 'user' })
215
222
  assert_equal([{ :id => :id }], extract_attributes(t.nodes))
216
223
  end
@@ -229,17 +236,21 @@ class TestCompiler < MINITEST_TEST_CLASS
229
236
  end
230
237
 
231
238
  it "extends template that has been compiled previously by ActionView" do
232
- File.open(@@tmp_path + 'user.rabl', 'w') do |f|
233
- f.puts %q{
234
- attributes :id
235
- }
236
- end
237
239
  t = @view.lookup_context.find_template('user')
238
240
  t.send(:compile!, @view)
239
241
  t = @compiler.compile_source(%{ extends 'user' })
240
242
  assert_equal([{ :id => :id }], extract_attributes(t.nodes))
241
243
  end
242
244
 
245
+ it "compiles extends with locals" do
246
+ t = @compiler.compile_source(%{ extends 'user', locals: { display_credit_card: false } })
247
+ node = t.nodes.first
248
+
249
+ assert_instance_of RablRails::Nodes::Extend, node
250
+ assert_equal([{ :id => :id }], extract_attributes(node.nodes))
251
+ assert_equal({ display_credit_card: false }, node.locals)
252
+ end
253
+
243
254
  it "compiles node" do
244
255
  t = @compiler.compile_source(%{ node(:foo) { bar } })
245
256
 
@@ -262,13 +273,19 @@ class TestCompiler < MINITEST_TEST_CLASS
262
273
  assert_nil node.name
263
274
  end
264
275
 
265
- it "compiles merge like a node but with a reserved keyword as name" do
276
+ it "compiles merge like a node" do
266
277
  t = @compiler.compile_source(%{ merge do |m| m.foo end })
267
278
  node = t.nodes.first
268
279
  assert_instance_of RablRails::Nodes::Code, node
269
280
  assert_nil node.name
270
281
  end
271
282
 
283
+ it "compiles merge with options" do
284
+ t = @compiler.compile_source(%{ merge(->(m) { true }) do |m| m.foo end })
285
+ node = t.nodes.first
286
+ refute_nil node.condition
287
+ end
288
+
272
289
  it "compiles condition" do
273
290
  t = @compiler.compile_source(%{ condition(->(u) {}) do attributes :secret end })
274
291
 
@@ -1,6 +1,6 @@
1
1
  require 'helper'
2
2
 
3
- class TestConfiguration < MINITEST_TEST_CLASS
3
+ class TestConfiguration < Minitest::Test
4
4
  describe 'Configuration' do
5
5
  it 'has a zero score by default' do
6
6
  config = RablRails::Configuration.new
@@ -28,4 +28,4 @@ class TestConfiguration < MINITEST_TEST_CLASS
28
28
  assert_equal 3, config.result_flags
29
29
  end
30
30
  end
31
- end
31
+ end
@@ -1,6 +1,6 @@
1
1
  require 'helper'
2
2
 
3
- class TestHashVisitor < MINITEST_TEST_CLASS
3
+ class TestHashVisitor < Minitest::Test
4
4
  describe 'hash visitor' do
5
5
  def visitor_result
6
6
  visitor = Visitors::ToHash.new(@context)
@@ -45,12 +45,12 @@ class TestHashVisitor < MINITEST_TEST_CLASS
45
45
  before do
46
46
  @template = RablRails::CompiledTemplate.new
47
47
  @template.add_node(RablRails::Nodes::Attribute.new(city: :city))
48
- @nodes << RablRails::Nodes::Child.new(:address, @template)
49
48
  @address = Address.new('Paris')
50
49
  end
51
50
 
52
51
  it 'renders with resource association as data source' do
53
52
  @template.data = :address
53
+ @nodes << RablRails::Nodes::Child.new(:address, @template)
54
54
  def @resource.address; end
55
55
  @resource.stub :address, @address do
56
56
  assert_equal({ address: { city: 'Paris' } }, visitor_result)
@@ -59,12 +59,14 @@ class TestHashVisitor < MINITEST_TEST_CLASS
59
59
 
60
60
  it 'renders with arbitrary data source' do
61
61
  @template.data = :@address
62
+ @nodes = [RablRails::Nodes::Child.new(:address, @template)]
62
63
  @context.assigns['address'] = @address
63
64
  assert_equal({ address: { city: 'Paris' } }, visitor_result)
64
65
  end
65
66
 
66
67
  it 'renders with local method as data source' do
67
68
  @template.data = :address
69
+ @nodes << RablRails::Nodes::Child.new(:address, @template)
68
70
  def @context.address; end
69
71
  @context.stub :address, @address do
70
72
  assert_equal({ address: { city: 'Paris' } }, visitor_result)
@@ -73,6 +75,7 @@ class TestHashVisitor < MINITEST_TEST_CLASS
73
75
 
74
76
  it 'renders with a collection as data source' do
75
77
  @template.data = :address
78
+ @nodes << RablRails::Nodes::Child.new(:address, @template)
76
79
  def @context.address; end
77
80
  @context.stub :address, [@address, @address] do
78
81
  assert_equal({ address: [
@@ -84,6 +87,7 @@ class TestHashVisitor < MINITEST_TEST_CLASS
84
87
 
85
88
  it 'renders if the source is nil' do
86
89
  @template.data = :address
90
+ @nodes << RablRails::Nodes::Child.new(:address, @template)
87
91
  def @resource.address; end
88
92
  @resource.stub :address, nil do
89
93
  assert_equal({ address: nil }, visitor_result)
@@ -157,7 +161,7 @@ class TestHashVisitor < MINITEST_TEST_CLASS
157
161
  it 'raises an exception when trying to merge a non hash object' do
158
162
  proc = ->(c) { c.name }
159
163
  @nodes << RablRails::Nodes::Code.new(nil, proc)
160
- assert_raises(RablRails::Renderer::PartialError) { visitor_result }
164
+ assert_raises(RablRails::PartialError) { visitor_result }
161
165
  end
162
166
 
163
167
  it 'renders partial defined in node' do
@@ -192,6 +196,17 @@ class TestHashVisitor < MINITEST_TEST_CLASS
192
196
  library.verify
193
197
  end
194
198
 
199
+ it 'renders extend with locals' do
200
+ n = RablRails::Nodes::Attribute.new(id: :id)
201
+ n.condition = lambda { |_| locals[:display_id] }
202
+
203
+ @nodes << RablRails::Nodes::Extend.new(n, display_id: true)
204
+ assert_equal({ id: 1 }, visitor_result)
205
+
206
+ @nodes.first.locals[:display_id] = false
207
+ assert_equal({}, visitor_result)
208
+ end
209
+
195
210
  it 'renders partial with empty target' do
196
211
  proc = ->(u) { partial('users/base', object: []) }
197
212
  @nodes << RablRails::Nodes::Code.new(:users, proc)
@@ -201,7 +216,7 @@ class TestHashVisitor < MINITEST_TEST_CLASS
201
216
  it 'raises an exception when calling a partial without a target' do
202
217
  proc = ->(u) { partial('users/base') }
203
218
  @nodes << RablRails::Nodes::Code.new(:user, proc)
204
- assert_raises(RablRails::Renderer::PartialError) { visitor_result }
219
+ assert_raises(RablRails::PartialError) { visitor_result }
205
220
  end
206
221
 
207
222
  describe 'when hash options are set' do