grape-rabl 0.4.3 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/danger-comment.yml +11 -0
- data/.github/workflows/danger.yml +13 -0
- data/.github/workflows/test.yml +60 -0
- data/.rubocop.yml +3 -1
- data/.rubocop_todo.yml +24 -22
- data/CHANGELOG.md +30 -17
- data/CONTRIBUTING.md +12 -1
- data/Dangerfile +2 -0
- data/Gemfile +12 -5
- data/README.md +300 -203
- data/RELEASING.md +50 -35
- data/Rakefile +3 -1
- data/UPGRADING.md +36 -0
- data/grape-rabl.gemspec +7 -6
- data/lib/grape/rabl.rb +2 -0
- data/lib/grape-rabl/configuration.rb +4 -1
- data/lib/grape-rabl/formatter.rb +31 -7
- data/lib/grape-rabl/render.rb +3 -1
- data/lib/grape-rabl/tilt.rb +2 -0
- data/lib/grape-rabl/version.rb +3 -1
- data/lib/grape-rabl.rb +2 -0
- data/spec/grape_rabl_configuration.rb +2 -0
- data/spec/grape_rabl_formatter_spec.rb +218 -0
- data/spec/grape_rabl_layout_spec.rb +10 -8
- data/spec/grape_rabl_partials_spec.rb +5 -3
- data/spec/grape_rabl_spec.rb +19 -21
- data/spec/grape_rabl_xml_spec.rb +5 -3
- data/spec/spec_helper.rb +11 -4
- data/spec/support/my_helper.rb +2 -0
- data/spec/views/_partial.rabl +3 -1
- data/spec/views/admin.rabl +3 -1
- data/spec/views/helper.rabl +2 -0
- data/spec/views/info.rabl +3 -1
- data/spec/views/layout_test/layouts/another.rabl +2 -0
- data/spec/views/layout_test/layouts/application.rabl +2 -0
- data/spec/views/layout_test/user.rabl +2 -0
- data/spec/views/project.rabl +5 -3
- data/spec/views/user.rabl +3 -1
- metadata +15 -31
- data/.coveralls.yml +0 -2
- data/.travis.yml +0 -13
data/UPGRADING.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Upgrading Grape::Rabl
|
|
2
|
+
|
|
3
|
+
## Upgrading to the next release
|
|
4
|
+
|
|
5
|
+
Ruby 2.7 or newer is required. Grape 1.x through 4.x are covered by CI, with Grape 3.x and 4.x tested on Ruby 3.3 and newer. Applications on Grape 1.x must use Rack 2.x.
|
|
6
|
+
|
|
7
|
+
## Upgrading to >= 0.5
|
|
8
|
+
|
|
9
|
+
### Fallback rendering when no RABL template is defined
|
|
10
|
+
|
|
11
|
+
Prior to v0.5.0, Grape::Rabl would always render content as JSON when no Rabl template was specified for a request. Beginning in v0.5.0 Grape::Rabl will now fallback to using the default response format [as determined by Grape](https://github.com/ruby-grape/grape#api-formats)
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
class SampleApi < Grape::API
|
|
15
|
+
format :xml
|
|
16
|
+
formatter :xml, Grape::Formatter::Rabl
|
|
17
|
+
|
|
18
|
+
get 'list' do
|
|
19
|
+
%w[thing]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
#### Former behavior
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
response.body # => ["thing"]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Current behavior
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
response.body # => <?xml version="1.0" encoding="UTF-8"?>\n<strings type="array">\n <string>thing</string>\n</strings>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
See [#34](https://github.com/ruby-grape/grape-rabl/pull/34) for more information.
|
data/grape-rabl.gemspec
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path('lib/grape-rabl/version', __dir__)
|
|
3
4
|
|
|
4
5
|
Gem::Specification.new do |gem|
|
|
5
|
-
gem.authors = [
|
|
6
|
+
gem.authors = ['Piotr Niełacny']
|
|
6
7
|
gem.email = ['piotr.nielacny@gmail.com']
|
|
7
8
|
gem.description = 'Use rabl in grape'
|
|
8
9
|
gem.summary = 'Use rabl in grape'
|
|
@@ -10,14 +11,14 @@ Gem::Specification.new do |gem|
|
|
|
10
11
|
|
|
11
12
|
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
|
12
13
|
gem.files = `git ls-files`.split("\n")
|
|
13
|
-
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
14
14
|
gem.name = 'grape-rabl'
|
|
15
15
|
gem.require_paths = ['lib']
|
|
16
16
|
gem.version = Grape::Rabl::VERSION
|
|
17
|
-
gem.required_ruby_version = '>= 2.
|
|
17
|
+
gem.required_ruby_version = '>= 2.7.0'
|
|
18
18
|
|
|
19
19
|
gem.add_dependency 'grape'
|
|
20
|
+
gem.add_dependency 'i18n'
|
|
20
21
|
gem.add_dependency 'rabl'
|
|
21
22
|
gem.add_dependency 'tilt'
|
|
22
|
-
gem.
|
|
23
|
+
gem.metadata['rubygems_mfa_required'] = 'true'
|
|
23
24
|
end
|
data/lib/grape/rabl.rb
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Grape
|
|
2
4
|
module Rabl
|
|
3
5
|
class Configuration
|
|
4
|
-
attr_accessor :cache_template_loading
|
|
6
|
+
attr_accessor :cache_template_loading, :tilt_root
|
|
5
7
|
|
|
6
8
|
def initialize
|
|
7
9
|
@cache_template_loading = false
|
|
10
|
+
@tilt_root = nil
|
|
8
11
|
end
|
|
9
12
|
end
|
|
10
13
|
end
|
data/lib/grape-rabl/formatter.rb
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'json'
|
|
2
4
|
|
|
3
5
|
module Grape
|
|
4
6
|
module Rabl
|
|
5
7
|
class Formatter
|
|
8
|
+
@tilt_cache = {}
|
|
9
|
+
@tilt_cache_mutex = Mutex.new
|
|
10
|
+
|
|
6
11
|
class << self
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
attr_reader :tilt_cache
|
|
13
|
+
|
|
14
|
+
def fetch_cached_template(key)
|
|
15
|
+
@tilt_cache_mutex.synchronize do
|
|
16
|
+
tilt_cache.fetch(key) { tilt_cache[key] = yield }
|
|
17
|
+
end
|
|
9
18
|
end
|
|
10
19
|
end
|
|
11
20
|
|
|
@@ -29,17 +38,23 @@ module Grape
|
|
|
29
38
|
end
|
|
30
39
|
end
|
|
31
40
|
else
|
|
32
|
-
|
|
41
|
+
fallback_formatter.call object, env
|
|
33
42
|
end
|
|
34
43
|
end
|
|
35
44
|
|
|
36
45
|
private
|
|
37
46
|
|
|
47
|
+
# Find a formatter to fallback to. `env[Grape::Env::API_FORMAT]` will always be a
|
|
48
|
+
# valid formatter, otherwise a HTTP 406 error would have already have been thrown
|
|
49
|
+
def fallback_formatter
|
|
50
|
+
Grape::Formatter.formatter_for(env[Grape::Env::API_FORMAT], formatters: {})
|
|
51
|
+
end
|
|
52
|
+
|
|
38
53
|
def view_path(template)
|
|
39
54
|
if template.split('.')[-1] == 'rabl'
|
|
40
55
|
File.join(env['api.tilt.root'], template)
|
|
41
56
|
else
|
|
42
|
-
File.join(env['api.tilt.root'],
|
|
57
|
+
File.join(env['api.tilt.root'], "#{template}.rabl")
|
|
43
58
|
end
|
|
44
59
|
end
|
|
45
60
|
|
|
@@ -49,6 +64,7 @@ module Grape
|
|
|
49
64
|
|
|
50
65
|
def rabl
|
|
51
66
|
raise 'missing rabl template' unless rabl_template
|
|
67
|
+
|
|
52
68
|
set_view_root unless env['api.tilt.root']
|
|
53
69
|
yield rabl_template
|
|
54
70
|
end
|
|
@@ -62,12 +78,18 @@ module Grape
|
|
|
62
78
|
end
|
|
63
79
|
|
|
64
80
|
def set_view_root
|
|
65
|
-
|
|
81
|
+
root = Grape::Rabl.configuration.tilt_root
|
|
82
|
+
env['api.tilt.root'] = root.is_a?(Proc) ? endpoint.instance_exec(&root) : root
|
|
83
|
+
return if env['api.tilt.root']
|
|
84
|
+
|
|
85
|
+
raise "Use Rack::Config to set 'api.tilt.root' in config.ru or configure 'tilt_root'"
|
|
66
86
|
end
|
|
67
87
|
|
|
68
88
|
def tilt_template(template)
|
|
69
89
|
if Grape::Rabl.configuration.cache_template_loading
|
|
70
|
-
Grape::Rabl::Formatter.
|
|
90
|
+
Grape::Rabl::Formatter.fetch_cached_template(tilt_cache_key(template)) do
|
|
91
|
+
::Tilt.new(view_path(template), tilt_options)
|
|
92
|
+
end
|
|
71
93
|
else
|
|
72
94
|
::Tilt.new(view_path(template), tilt_options)
|
|
73
95
|
end
|
|
@@ -80,7 +102,9 @@ module Grape
|
|
|
80
102
|
def layout_template
|
|
81
103
|
layout_path = view_path(env['api.tilt.layout'] || 'layouts/application')
|
|
82
104
|
if Grape::Rabl.configuration.cache_template_loading
|
|
83
|
-
Grape::Rabl::Formatter.
|
|
105
|
+
Grape::Rabl::Formatter.fetch_cached_template(tilt_cache_key(layout_path)) do
|
|
106
|
+
::Tilt.new(layout_path, tilt_options) if File.exist?(layout_path)
|
|
107
|
+
end
|
|
84
108
|
else
|
|
85
109
|
::Tilt.new(layout_path, tilt_options) if File.exist?(layout_path)
|
|
86
110
|
end
|
data/lib/grape-rabl/render.rb
CHANGED
data/lib/grape-rabl/tilt.rb
CHANGED
data/lib/grape-rabl/version.rb
CHANGED
data/lib/grape-rabl.rb
CHANGED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Grape::Rabl::Formatter do
|
|
6
|
+
before do
|
|
7
|
+
hide_const('Tilt::Cache')
|
|
8
|
+
described_class.tilt_cache.clear
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
after do
|
|
12
|
+
described_class.tilt_cache.clear
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'reuses a cached template without Tilt::Cache' do
|
|
16
|
+
template = described_class.fetch_cached_template(:template) { Object.new }
|
|
17
|
+
|
|
18
|
+
expect(described_class.fetch_cached_template(:template) { raise 'recompiled' })
|
|
19
|
+
.to equal(template)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'memoizes missing layouts' do
|
|
23
|
+
expect(described_class.fetch_cached_template(:missing) { nil }).to be_nil
|
|
24
|
+
expect(described_class.fetch_cached_template(:missing) { raise 'looked up again' })
|
|
25
|
+
.to be_nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'creates one cached template for concurrent requests' do
|
|
29
|
+
threads = 4.times.map do
|
|
30
|
+
Thread.new do
|
|
31
|
+
described_class.fetch_cached_template(:concurrent) do
|
|
32
|
+
sleep 0.01
|
|
33
|
+
Object.new
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
expect(threads.map(&:value).map(&:object_id).uniq.size).to eq(1)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe 'configured template roots' do
|
|
43
|
+
let(:app) { Class.new(Grape::API) }
|
|
44
|
+
let(:request_root) { nil }
|
|
45
|
+
let(:root) do
|
|
46
|
+
lambda {
|
|
47
|
+
File.join(__dir__, 'views', env['api.version'] == 'v2' ? 'layout_test' : '')
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
before do
|
|
52
|
+
Grape::Rabl.configuration.tilt_root = root
|
|
53
|
+
Grape::Rabl::Formatter.tilt_cache.clear
|
|
54
|
+
app.version %w[v1 v2], using: :path
|
|
55
|
+
app.format :json
|
|
56
|
+
app.formatter :json, Grape::Formatter::Rabl
|
|
57
|
+
override = request_root
|
|
58
|
+
app.before { env['api.tilt.root'] = override } if override
|
|
59
|
+
app.get('/user', rabl: 'user', rabl_locals: { details: 'base template' }) do
|
|
60
|
+
@user = Struct.new(:name).new('Jane')
|
|
61
|
+
@project = Struct.new(:name).new('First')
|
|
62
|
+
@status = 200
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
after do
|
|
67
|
+
Grape::Rabl.reset_configuration!
|
|
68
|
+
Grape::Rabl::Formatter.tilt_cache.clear
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
[false, true].each do |cache|
|
|
72
|
+
context "with template caching #{cache ? 'enabled' : 'disabled'}" do
|
|
73
|
+
before do
|
|
74
|
+
Grape::Rabl.configuration.cache_template_loading = cache
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'resolves templates and layouts per request without leaking roots' do
|
|
78
|
+
user = { 'user' => { 'name' => 'Jane', 'project' => { 'name' => 'First' } } }
|
|
79
|
+
base_user = { 'user' => user.fetch('user').merge('details' => 'base template') }
|
|
80
|
+
|
|
81
|
+
get '/v1/user'
|
|
82
|
+
expect(JSON.parse(last_response.body)).to eq(base_user)
|
|
83
|
+
|
|
84
|
+
get '/v2/user'
|
|
85
|
+
expect(JSON.parse(last_response.body)).to eq('status' => 200, 'result' => user)
|
|
86
|
+
|
|
87
|
+
get '/v1/user'
|
|
88
|
+
expect(JSON.parse(last_response.body)).to eq(base_user)
|
|
89
|
+
expect(Grape::Rabl.configuration.tilt_root).to equal(root)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context 'a static configured root' do
|
|
95
|
+
let(:root) { File.join(__dir__, 'views') }
|
|
96
|
+
|
|
97
|
+
it 'does not automatically append the API version' do
|
|
98
|
+
get '/v2/user'
|
|
99
|
+
expect(JSON.parse(last_response.body)).to have_key('user')
|
|
100
|
+
expect(last_request.env['api.tilt.root']).to eq(root)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
context 'an explicit request root' do
|
|
105
|
+
let(:root) { -> { raise 'configured root should not run' } }
|
|
106
|
+
let(:request_root) { File.join(__dir__, 'views') }
|
|
107
|
+
|
|
108
|
+
it 'takes precedence over the configured root' do
|
|
109
|
+
get '/v1/user'
|
|
110
|
+
expect(JSON.parse(last_response.body)).to have_key('user')
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
context 'a missing resolved root' do
|
|
115
|
+
let(:root) { -> {} }
|
|
116
|
+
|
|
117
|
+
it 'raises the configuration error' do
|
|
118
|
+
expect { get '/v1/user' }.to raise_error(RuntimeError, /configure 'tilt_root'/)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context 'a failing root resolver' do
|
|
123
|
+
let(:root) { -> { raise 'root lookup failed' } }
|
|
124
|
+
|
|
125
|
+
it 'propagates the error' do
|
|
126
|
+
expect { get '/v1/user' }.to raise_error(RuntimeError, 'root lookup failed')
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'does not run when falling back to the default formatter' do
|
|
130
|
+
app.get('/health') { { healthy: true } }
|
|
131
|
+
get '/v1/health'
|
|
132
|
+
expect(JSON.parse(last_response.body)).to eq('healthy' => true)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
describe 'Grape::Rabl formatter' do
|
|
138
|
+
subject do
|
|
139
|
+
Class.new(Grape::API)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
let(:xml_render) do
|
|
143
|
+
%(<?xml version="1.0" encoding="UTF-8"?>
|
|
144
|
+
<hash>
|
|
145
|
+
<errors type="array">
|
|
146
|
+
<error>bad</error>
|
|
147
|
+
<error>things</error>
|
|
148
|
+
<error>happened</error>
|
|
149
|
+
</errors>
|
|
150
|
+
</hash>
|
|
151
|
+
)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def app
|
|
155
|
+
subject
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
context 'rendering' do
|
|
159
|
+
context 'when no rabl template is specified' do
|
|
160
|
+
before do
|
|
161
|
+
# Grape::API defaults to the following declarations:
|
|
162
|
+
# content_type :xml, 'application/xml'
|
|
163
|
+
# content_type :json, 'application/json'
|
|
164
|
+
# content_type :binary, 'application/octet-stream'
|
|
165
|
+
# content_type :txt, 'text/plain'
|
|
166
|
+
# default_format :txt
|
|
167
|
+
subject.formatter :xml, Grape::Formatter::Rabl
|
|
168
|
+
subject.formatter :txt, Grape::Formatter::Rabl
|
|
169
|
+
subject.get('/oops') { { errors: %w[bad things happened] } }
|
|
170
|
+
expect_any_instance_of(Grape::Rabl::Formatter).to receive(:render).and_call_original
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it 'falls back to :txt given no other format information' do
|
|
174
|
+
get '/oops'
|
|
175
|
+
expect(last_response.body).to eq({ errors: %w[bad things happened] }.to_s)
|
|
176
|
+
expect(last_response.headers['Content-Type']).to eq('text/plain')
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it 'falls back to the file extension if it is a valid format' do
|
|
180
|
+
get '/oops.xml'
|
|
181
|
+
expect(last_response.body).to eq(xml_render)
|
|
182
|
+
expect(last_response.headers['Content-Type']).to eq('application/xml')
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it 'falls back to the value of the `format` parameter in the query string if it is provided' do
|
|
186
|
+
get '/oops?format=xml'
|
|
187
|
+
expect(last_response.body).to eq(xml_render)
|
|
188
|
+
expect(last_response.headers['Content-Type']).to eq('application/xml')
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it 'falls back to the format set by the `format` option if it is a valid format' do
|
|
192
|
+
# `format` option must be declared before endpoint
|
|
193
|
+
subject.format :xml
|
|
194
|
+
subject.get('/oops/2') { { errors: %w[bad things happened] } }
|
|
195
|
+
|
|
196
|
+
get '/oops/2'
|
|
197
|
+
expect(last_response.body).to eq(xml_render)
|
|
198
|
+
expect(last_response.headers['Content-Type']).to eq('application/xml')
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it 'falls back to the `Accept` header if it is a valid format' do
|
|
202
|
+
get '/oops', {}, 'HTTP_ACCEPT' => 'application/xml'
|
|
203
|
+
expect(last_response.body).to eq(xml_render)
|
|
204
|
+
expect(last_response.headers['Content-Type']).to eq('application/xml')
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it 'falls back to the default_format option if it is a valid format' do
|
|
208
|
+
# `default_format` option must be declared before endpoint
|
|
209
|
+
subject.default_format :xml
|
|
210
|
+
subject.get('/oops/2') { { errors: %w[bad things happened] } }
|
|
211
|
+
|
|
212
|
+
get '/oops/2'
|
|
213
|
+
expect(last_response.body).to eq(xml_render)
|
|
214
|
+
expect(last_response.headers['Content-Type']).to eq('application/xml')
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe 'Grape::Rabl layout' do
|
|
@@ -22,8 +24,8 @@ describe 'Grape::Rabl layout' do
|
|
|
22
24
|
context 'default' do
|
|
23
25
|
it 'proper render with default layout' do
|
|
24
26
|
subject.get('/about', rabl: 'user') do
|
|
25
|
-
@user =
|
|
26
|
-
@project =
|
|
27
|
+
@user = Struct.new(:name).new('LTe')
|
|
28
|
+
@project = Struct.new(:name).new('First')
|
|
27
29
|
@status = 200
|
|
28
30
|
end
|
|
29
31
|
|
|
@@ -41,8 +43,8 @@ describe 'Grape::Rabl layout' do
|
|
|
41
43
|
|
|
42
44
|
it 'proper render with specified layout' do
|
|
43
45
|
subject.get('/about', rabl: 'user') do
|
|
44
|
-
@user =
|
|
45
|
-
@project =
|
|
46
|
+
@user = Struct.new(:name).new('LTe')
|
|
47
|
+
@project = Struct.new(:name).new('First')
|
|
46
48
|
@status = 200
|
|
47
49
|
end
|
|
48
50
|
|
|
@@ -61,8 +63,8 @@ describe 'Grape::Rabl layout' do
|
|
|
61
63
|
FileUtils.cp_r("#{File.dirname(__FILE__)}/views/layout_test/.", @views_dir)
|
|
62
64
|
subject.before { env['api.tilt.root'] = "#{File.expand_path('..', File.dirname(__FILE__))}/tmp" }
|
|
63
65
|
subject.get('/home', rabl: 'user') do
|
|
64
|
-
@user =
|
|
65
|
-
@project =
|
|
66
|
+
@user = Struct.new(:name, :email).new('LTe', 'email@example.com')
|
|
67
|
+
@project = Struct.new(:name).new('First')
|
|
66
68
|
@status = 200
|
|
67
69
|
end
|
|
68
70
|
end
|
|
@@ -79,7 +81,7 @@ describe 'Grape::Rabl layout' do
|
|
|
79
81
|
get '/home'
|
|
80
82
|
expect(last_response.status).to eq(200)
|
|
81
83
|
old_response = last_response.body
|
|
82
|
-
open(@layout, 'a') { |f| f << 'node(:test) { "test" }' }
|
|
84
|
+
File.open(@layout, 'a') { |f| f << 'node(:test) { "test" }' }
|
|
83
85
|
get '/home'
|
|
84
86
|
expect(last_response.status).to eq(200)
|
|
85
87
|
new_response = last_response.body
|
|
@@ -90,7 +92,7 @@ describe 'Grape::Rabl layout' do
|
|
|
90
92
|
get '/home'
|
|
91
93
|
expect(last_response.status).to eq(200)
|
|
92
94
|
old_response = last_response.body
|
|
93
|
-
open(@layout, 'a') { |f| f << 'node(:test) { "test" }' }
|
|
95
|
+
File.open(@layout, 'a') { |f| f << 'node(:test) { "test" }' }
|
|
94
96
|
get '/home'
|
|
95
97
|
expect(last_response.status).to eq(200)
|
|
96
98
|
new_response = last_response.body
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe 'Grape::Rabl partials' do
|
|
@@ -19,9 +21,9 @@ describe 'Grape::Rabl partials' do
|
|
|
19
21
|
|
|
20
22
|
it 'proper render partials' do
|
|
21
23
|
subject.get('/home', rabl: 'project') do
|
|
22
|
-
@author =
|
|
23
|
-
@type =
|
|
24
|
-
@project =
|
|
24
|
+
@author = Struct.new(:author).new('LTe')
|
|
25
|
+
@type = Struct.new(:type).new('paper')
|
|
26
|
+
@project = Struct.new(:name, :type, :author).new('First', @type, @author)
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
get('/home')
|
data/spec/grape_rabl_spec.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe Grape::Rabl do
|
|
@@ -23,12 +25,8 @@ describe Grape::Rabl do
|
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
it 'should raise error about root directory' do
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
get '/home'
|
|
29
|
-
rescue Exception => e
|
|
30
|
-
expect(e.message).to include "Use Rack::Config to set 'api.tilt.root' in config.ru"
|
|
31
|
-
end
|
|
28
|
+
subject.get('/home', rabl: true) { nil }
|
|
29
|
+
expect { get '/home' }.to raise_error(RuntimeError, /Use Rack::Config to set 'api.tilt.root' in config.ru/)
|
|
32
30
|
end
|
|
33
31
|
|
|
34
32
|
context 'titl root is setup' do
|
|
@@ -40,7 +38,7 @@ describe Grape::Rabl do
|
|
|
40
38
|
|
|
41
39
|
describe 'helpers' do
|
|
42
40
|
it 'should execute helper' do
|
|
43
|
-
subject.get('/home', rabl: 'helper') { @user =
|
|
41
|
+
subject.get('/home', rabl: 'helper') { @user = Object.new }
|
|
44
42
|
get '/home'
|
|
45
43
|
expect(parsed_response).to eq(JSON.parse('{"user":{"helper":"my_helper"}}'))
|
|
46
44
|
end
|
|
@@ -49,27 +47,27 @@ describe Grape::Rabl do
|
|
|
49
47
|
describe '#render' do
|
|
50
48
|
before do
|
|
51
49
|
subject.get('/home', rabl: 'user') do
|
|
52
|
-
@user =
|
|
50
|
+
@user = Struct.new(:name).new('LTe')
|
|
53
51
|
render rabl: 'admin'
|
|
54
52
|
end
|
|
55
53
|
|
|
56
54
|
subject.get('/admin/:id', rabl: 'user') do
|
|
57
|
-
@user =
|
|
55
|
+
@user = Struct.new(:name).new('LTe')
|
|
58
56
|
|
|
59
57
|
render rabl: 'admin' if params[:id] == '1'
|
|
60
58
|
end
|
|
61
59
|
|
|
62
60
|
subject.get('/home-detail', rabl: 'user') do
|
|
63
|
-
@user =
|
|
61
|
+
@user = Struct.new(:name).new('LTe')
|
|
64
62
|
render rabl: 'admin', locals: { details: 'amazing detail' }
|
|
65
63
|
end
|
|
66
64
|
|
|
67
65
|
subject.get('/about', rabl: 'user') do
|
|
68
|
-
@user =
|
|
66
|
+
@user = Struct.new(:name).new('LTe')
|
|
69
67
|
end
|
|
70
68
|
|
|
71
69
|
subject.get('/about-detail', rabl: 'user') do
|
|
72
|
-
@user =
|
|
70
|
+
@user = Struct.new(:name).new('LTe')
|
|
73
71
|
render locals: { details: 'just a user' }
|
|
74
72
|
end
|
|
75
73
|
end
|
|
@@ -112,13 +110,13 @@ describe Grape::Rabl do
|
|
|
112
110
|
end
|
|
113
111
|
|
|
114
112
|
it 'should respond with proper content-type' do
|
|
115
|
-
subject.get('/home', rabl: 'user') {}
|
|
113
|
+
subject.get('/home', rabl: 'user') { nil }
|
|
116
114
|
get('/home')
|
|
117
115
|
expect(last_response.headers['Content-Type']).to eq('application/json')
|
|
118
116
|
end
|
|
119
117
|
|
|
120
118
|
it 'should not raise error about root directory' do
|
|
121
|
-
subject.get('/home', rabl: 'user') {}
|
|
119
|
+
subject.get('/home', rabl: 'user') { nil }
|
|
122
120
|
get '/home'
|
|
123
121
|
expect(last_response.status).to eq 200
|
|
124
122
|
expect(last_response.body).not_to include "Use Rack::Config to set 'api.tilt.root' in config.ru"
|
|
@@ -127,8 +125,8 @@ describe Grape::Rabl do
|
|
|
127
125
|
['user', 'user.rabl'].each do |rabl_option|
|
|
128
126
|
it "should render rabl template (#{rabl_option})" do
|
|
129
127
|
subject.get('/home', rabl: rabl_option) do
|
|
130
|
-
@user =
|
|
131
|
-
@project =
|
|
128
|
+
@user = Struct.new(:name, :email).new('LTe', 'email@example.com')
|
|
129
|
+
@project = Struct.new(:name).new('First')
|
|
132
130
|
end
|
|
133
131
|
|
|
134
132
|
get '/home'
|
|
@@ -143,8 +141,8 @@ describe Grape::Rabl do
|
|
|
143
141
|
FileUtils.cp("#{File.dirname(__FILE__)}/views/user.rabl", @template)
|
|
144
142
|
subject.before { env['api.tilt.root'] = "#{File.expand_path('..', File.dirname(__FILE__))}/tmp" }
|
|
145
143
|
subject.get('/home', rabl: 'user') do
|
|
146
|
-
@user =
|
|
147
|
-
@project =
|
|
144
|
+
@user = Struct.new(:name, :email).new('LTe', 'email@example.com')
|
|
145
|
+
@project = Struct.new(:name).new('First')
|
|
148
146
|
end
|
|
149
147
|
end
|
|
150
148
|
|
|
@@ -160,7 +158,7 @@ describe Grape::Rabl do
|
|
|
160
158
|
get '/home'
|
|
161
159
|
expect(last_response.status).to eq(200)
|
|
162
160
|
old_response = last_response.body
|
|
163
|
-
open(@template, 'a') { |f| f << 'node(:test) { "test" }' }
|
|
161
|
+
File.open(@template, 'a') { |f| f << 'node(:test) { "test" }' }
|
|
164
162
|
get '/home'
|
|
165
163
|
expect(last_response.status).to eq(200)
|
|
166
164
|
new_response = last_response.body
|
|
@@ -178,7 +176,7 @@ describe Grape::Rabl do
|
|
|
178
176
|
expect(last_response.status).to eq(200)
|
|
179
177
|
xml_response = last_response.body
|
|
180
178
|
expect(json_response).not_to eq(xml_response)
|
|
181
|
-
open(@template, 'a') { |f| f << 'node(:test) { "test" }' }
|
|
179
|
+
File.open(@template, 'a') { |f| f << 'node(:test) { "test" }' }
|
|
182
180
|
get '/home.xml'
|
|
183
181
|
expect(last_response.status).to eq(200)
|
|
184
182
|
expect(last_response.body).to eq(xml_response)
|
|
@@ -191,7 +189,7 @@ describe Grape::Rabl do
|
|
|
191
189
|
get '/home'
|
|
192
190
|
expect(last_response.status).to eq(200)
|
|
193
191
|
old_response = last_response.body
|
|
194
|
-
open(@template, 'a') { |f| f << 'node(:test) { "test" }' }
|
|
192
|
+
File.open(@template, 'a') { |f| f << 'node(:test) { "test" }' }
|
|
195
193
|
get '/home'
|
|
196
194
|
expect(last_response.status).to eq(200)
|
|
197
195
|
new_response = last_response.body
|
data/spec/grape_rabl_xml_spec.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe Grape::Rabl do
|
|
@@ -23,7 +25,7 @@ describe Grape::Rabl do
|
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
it 'should respond with proper content-type' do
|
|
26
|
-
subject.get('/home', rabl: 'user') {}
|
|
28
|
+
subject.get('/home', rabl: 'user') { nil }
|
|
27
29
|
get('/home')
|
|
28
30
|
expect(last_response.headers['Content-Type']).to eq('application/xml')
|
|
29
31
|
end
|
|
@@ -31,8 +33,8 @@ describe Grape::Rabl do
|
|
|
31
33
|
['user', 'user.rabl'].each do |rabl_option|
|
|
32
34
|
it "should render rabl template (#{rabl_option})" do
|
|
33
35
|
subject.get('/home', rabl: rabl_option) do
|
|
34
|
-
@user =
|
|
35
|
-
@project =
|
|
36
|
+
@user = Struct.new(:name, :email).new('LTe', 'email@example.com')
|
|
37
|
+
@project = Struct.new(:name).new('First')
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
get '/home'
|