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.
data/README.md CHANGED
@@ -1,203 +1,300 @@
1
- # Grape::Rabl
2
-
3
- Use [Rabl](https://github.com/nesquena/rabl) templates in [Grape](https://github.com/intridea/grape)!
4
-
5
- [![Gem Version](http://img.shields.io/gem/v/grape-rabl.svg)](http://badge.fury.io/rb/grape-rabl)
6
- [![Build Status](http://img.shields.io/travis/ruby-grape/grape-rabl.svg)](https://travis-ci.org/ruby-grape/grape-rabl)
7
- [![Dependency Status](https://gemnasium.com/ruby-grape/grape-rabl.svg)](https://gemnasium.com/ruby-grape/grape-rabl)
8
- [![Code Climate](https://codeclimate.com/github/ruby-grape/grape-rabl.svg)](https://codeclimate.com/github/ruby-grape/grape-rabl)
9
- [![Coverage Status](https://img.shields.io/coveralls/ruby-grape/grape-rabl.svg)](https://coveralls.io/r/ruby-grape/grape-rabl?branch=master)
10
-
11
- ## Installation
12
-
13
- Add the `grape` and `grape-rabl` gems to Gemfile.
14
-
15
- ```ruby
16
- gem 'grape'
17
- gem 'grape-rabl'
18
- ```
19
-
20
- And then execute:
21
-
22
- $ bundle
23
-
24
- ## Usage
25
-
26
- ### Setup view root directory
27
-
28
- ```ruby
29
- # config.ru
30
- use Rack::Config do |env|
31
- env['api.tilt.root'] = '/path/to/view/root/directory'
32
- end
33
- ```
34
-
35
- ### Tell your API to use Grape::Formatter::Rabl
36
-
37
- ```ruby
38
- class API < Grape::API
39
- format :json
40
- formatter :json, Grape::Formatter::Rabl
41
- end
42
- ```
43
-
44
- ### Use rabl templates conditionally
45
-
46
- Add the template name to the API options.
47
-
48
- ```ruby
49
- get "/user/:id", :rabl => "user.rabl" do
50
- @user = User.find(params[:id])
51
- end
52
- ```
53
-
54
- You can use instance variables in the Rabl template.
55
-
56
- ```ruby
57
- object @user => :user
58
- attributes :name, :email
59
-
60
- child @project => :project do
61
- attributes :name
62
- end
63
- ```
64
-
65
- ### Use rabl layout
66
-
67
- Gape-rabl first looks for a layout file in `#{env['api.tilt.root']}/layouts/application.rabl`.
68
-
69
- You can override the default layout conventions:
70
-
71
- ```ruby
72
- # config.ru
73
- use Rack::Config do |env|
74
- env['api.tilt.root'] = '/path/to/view/root/directory'
75
- env['api.tilt.layout'] = 'layouts/another'
76
- end
77
- ```
78
-
79
- ### Enable template caching
80
-
81
- Grape-rabl allows for template caching after templates are loaded initially.
82
-
83
- You can enable template caching:
84
-
85
- ```ruby
86
- # config.ru
87
- Grape::Rabl.configure do |config|
88
- config.cache_template_loading = true # default: false
89
- end
90
- ```
91
-
92
- ## You can omit .rabl
93
-
94
- The following are identical.
95
-
96
- ```ruby
97
- get "/home", :rabl => "view"
98
- get "/home", :rabl => "view.rabl"
99
- ```
100
-
101
- ### Example
102
-
103
- ```ruby
104
- # config.ru
105
- use Rack::Config do |env|
106
- env['api.tilt.root'] = '/path/to/view/root/directory'
107
- end
108
-
109
- class UserAPI < Grape::API
110
- format :json
111
- formatter :json, Grape::Formatter::Rabl
112
-
113
- get '/user/:id' do
114
- @user = User.find(params[:id])
115
-
116
- # use rabl with 'user.rabl' or 'admin.rabl' template
117
- if @user.admin?
118
- # pass locals with the #render method
119
- render rabl: 'admin', locals: { details: 'this user is an admin' }
120
- else
121
- render rabl: 'user'
122
- end
123
- end
124
-
125
- get '/admin/:id', :rabl => 'admin' do
126
- @user = User.find(params[:id])
127
-
128
- # use rabl with 'super_admin.rabl'
129
- render rabl: 'super_admin' if @user.super_admin?
130
- # when render method has not been used use template from endpoint definition
131
- end
132
-
133
- # use rabl with 'user_history.rabl' template
134
- get '/user/:id/history', :rabl => 'user_history' do
135
- @history = User.find(params[:id]).history
136
- end
137
-
138
- # do not use rabl, fallback to the defalt Grape JSON formatter
139
- get '/users' do
140
- User.all
141
- end
142
- end
143
- ```
144
-
145
- ```ruby
146
- # user.rabl
147
- object @user => :user
148
-
149
- attributes :name
150
- ```
151
-
152
- ## Usage with rails
153
-
154
- Create grape application
155
-
156
- ```ruby
157
- # app/api/user.rb
158
- class MyAPI < Grape::API
159
- format :json
160
- formatter :json, Grape::Formatter::Rabl
161
- get '/user/:id', :rabl => "user" do
162
- @user = User.find(params[:id])
163
- end
164
- end
165
- ```
166
-
167
- ```ruby
168
- # app/views/api/user.rabl
169
- object @user => :user
170
- ```
171
-
172
- Edit your **config/application.rb** and add view path
173
-
174
- ```ruby
175
- # application.rb
176
- class Application < Rails::Application
177
- config.middleware.use(Rack::Config) do |env|
178
- env['api.tilt.root'] = Rails.root.join "app", "views", "api"
179
- end
180
- end
181
- ```
182
-
183
- Mount application to rails router
184
-
185
- ```ruby
186
- # routes.rb
187
- GrapeExampleRails::Application.routes.draw do
188
- mount MyAPI , :at => "/api"
189
- end
190
- ```
191
-
192
- ## Specs
193
-
194
- See ["Writing Tests"](https://github.com/intridea/grape#writing-tests) in [https://github.com/intridea/grape](grape) README.
195
-
196
- Enjoy :)
197
-
198
- ## Contributing
199
-
200
- See [CONTRIBUTING](CONTRIBUTING.md).
201
-
202
- [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/ruby-grape/grape-rabl/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
203
-
1
+ # Grape::Rabl
2
+
3
+ Use [Rabl](https://github.com/nesquena/rabl) templates in [Grape](https://github.com/ruby-grape/grape)!
4
+
5
+ [![Gem Version](https://img.shields.io/gem/v/grape-rabl.svg)](https://rubygems.org/gems/grape-rabl)
6
+ [![Build Status](https://github.com/ruby-grape/grape-rabl/actions/workflows/test.yml/badge.svg?branch=master&event=push)](https://github.com/ruby-grape/grape-rabl/actions/workflows/test.yml?query=branch%3Amaster)
7
+ [![Coverage Status](https://coveralls.io/repos/github/ruby-grape/grape-rabl/badge.svg?branch=master)](https://coveralls.io/github/ruby-grape/grape-rabl?branch=master)
8
+
9
+ # Table of Contents
10
+
11
+ - [Installation](#installation)
12
+ - [Upgrading](#upgrading)
13
+ - [Usage](#usage)
14
+ - [Setup view root directory](#setup-view-root-directory)
15
+ - [Configure request-aware view roots](#configure-request-aware-view-roots)
16
+ - [Tell your API to use Grape::Formatter::Rabl](#tell-your-api-to-use-grapeformatterrabl)
17
+ - [Use rabl templates conditionally](#use-rabl-templates-conditionally)
18
+ - [Use rabl layout](#use-rabl-layout)
19
+ - [Enable template caching](#enable-template-caching)
20
+ - [You can omit .rabl](#you-can-omit-rabl)
21
+ - [Example](#example)
22
+ - [Usage with rails](#usage-with-rails)
23
+ - [Swagger documentation](#swagger-documentation)
24
+ - [Specs](#specs)
25
+ - [Contributing](#contributing)
26
+
27
+ ## Installation
28
+
29
+ Requires Ruby 2.7 or newer. CI covers Grape 1.x, 2.x, 3.x, and 4.x; Grape 3.x and 4.x are tested on Ruby 3.3 and newer. Grape 1.x requires Rack 2.x.
30
+
31
+ Add the `grape` and `grape-rabl` gems to Gemfile.
32
+
33
+ ```ruby
34
+ gem 'grape'
35
+ gem 'grape-rabl'
36
+ ```
37
+
38
+ And then execute:
39
+
40
+ $ bundle
41
+
42
+ ## Upgrading
43
+
44
+ See [UPGRADING](UPGRADING.md).
45
+
46
+ ## Usage
47
+
48
+ ### Setup view root directory
49
+
50
+ ```ruby
51
+ # config.ru
52
+ use Rack::Config do |env|
53
+ env['api.tilt.root'] = '/path/to/view/root/directory'
54
+ end
55
+ ```
56
+
57
+ ### Configure request-aware view roots
58
+
59
+ Instead of setting a root with middleware, configure a static directory or a zero-argument Proc/lambda:
60
+
61
+ ```ruby
62
+ Grape::Rabl.configure do |config|
63
+ config.tilt_root = -> { File.join('/path/to/views', env['api.version'].to_s) }
64
+ end
65
+ ```
66
+
67
+ The Proc runs in the current Grape endpoint's context, so it can access `env`, `params`, and API helpers. The example uses `/path/to/views/v1` for version `v1` and `/path/to/views` for an unversioned request. Version directories are opt-in: a static `config.tilt_root` or existing `env['api.tilt.root']` is used unchanged.
68
+
69
+ An explicit `env['api.tilt.root']` takes precedence over the configured root, and the Proc is not called in that case. Resolution happens only when rendering a Rabl template; the resolved root is stored in the request environment, not back into configuration. Templates, partials, and layouts use that root, and cached templates remain separated by resolved directory and format. Resolver exceptions propagate; returning `nil` or `false` raises the missing-root configuration error.
70
+
71
+ ### Tell your API to use Grape::Formatter::Rabl
72
+
73
+ ```ruby
74
+ class API < Grape::API
75
+ format :json
76
+ formatter :json, Grape::Formatter::Rabl
77
+ end
78
+ ```
79
+
80
+ ### Use rabl templates conditionally
81
+
82
+ Add the template name to the API options.
83
+
84
+ ```ruby
85
+ get "/user/:id", :rabl => "user.rabl" do
86
+ @user = User.find(params[:id])
87
+ end
88
+ ```
89
+
90
+ You can use instance variables in the Rabl template.
91
+
92
+ ```ruby
93
+ object @user => :user
94
+ attributes :name, :email
95
+
96
+ child @project => :project do
97
+ attributes :name
98
+ end
99
+ ```
100
+
101
+ ### Use rabl layout
102
+
103
+ Gape-rabl first looks for a layout file in `#{env['api.tilt.root']}/layouts/application.rabl`.
104
+
105
+ You can override the default layout conventions:
106
+
107
+ ```ruby
108
+ # config.ru
109
+ use Rack::Config do |env|
110
+ env['api.tilt.root'] = '/path/to/view/root/directory'
111
+ env['api.tilt.layout'] = 'layouts/another'
112
+ end
113
+ ```
114
+
115
+ ### Enable template caching
116
+
117
+ Grape-rabl allows for template caching after templates are loaded initially.
118
+
119
+ Template creation and cache lookups are synchronized across requests, including cached missing layouts. Caching does not depend on the deprecated `Tilt::Cache` class. Disable caching during development if templates need to reload after changes.
120
+
121
+ You can enable template caching:
122
+
123
+ ```ruby
124
+ # config.ru
125
+ Grape::Rabl.configure do |config|
126
+ config.cache_template_loading = true # default: false
127
+ end
128
+ ```
129
+
130
+ ## You can omit .rabl
131
+
132
+ The following are identical.
133
+
134
+ ```ruby
135
+ get "/home", :rabl => "view"
136
+ get "/home", :rabl => "view.rabl"
137
+ ```
138
+
139
+ ### Example
140
+
141
+ ```ruby
142
+ # config.ru
143
+ use Rack::Config do |env|
144
+ env['api.tilt.root'] = '/path/to/view/root/directory'
145
+ end
146
+
147
+ class UserAPI < Grape::API
148
+ format :json
149
+ formatter :json, Grape::Formatter::Rabl
150
+
151
+ get '/user/:id' do
152
+ @user = User.find(params[:id])
153
+
154
+ # use rabl with 'user.rabl' or 'admin.rabl' template
155
+ if @user.admin?
156
+ # pass locals with the #render method
157
+ render rabl: 'admin', locals: { details: 'this user is an admin' }
158
+ else
159
+ render rabl: 'user'
160
+ end
161
+ end
162
+
163
+ get '/admin/:id', :rabl => 'admin' do
164
+ @user = User.find(params[:id])
165
+
166
+ # use rabl with 'super_admin.rabl'
167
+ render rabl: 'super_admin' if @user.super_admin?
168
+ # when render method has not been used use template from endpoint definition
169
+ end
170
+
171
+ # use rabl with 'user_history.rabl' template
172
+ get '/user/:id/history', :rabl => 'user_history' do
173
+ @history = User.find(params[:id]).history
174
+ end
175
+
176
+ # do not use rabl, fallback to the default Grape response formatter
177
+ get '/users' do
178
+ User.all
179
+ end
180
+ end
181
+ ```
182
+
183
+ ```ruby
184
+ # user.rabl
185
+ object @user => :user
186
+
187
+ attributes :name
188
+ ```
189
+
190
+ ## Usage with rails
191
+
192
+ Create grape application
193
+
194
+ ```ruby
195
+ # app/api/user.rb
196
+ class MyAPI < Grape::API
197
+ format :json
198
+ formatter :json, Grape::Formatter::Rabl
199
+ get '/user/:id', :rabl => "user" do
200
+ @user = User.find(params[:id])
201
+ end
202
+ end
203
+ ```
204
+
205
+ ```ruby
206
+ # app/views/api/user.rabl
207
+ object @user => :user
208
+ ```
209
+
210
+ Edit your **config/application.rb** and add view path
211
+
212
+ ```ruby
213
+ # application.rb
214
+ class Application < Rails::Application
215
+ config.middleware.use(Rack::Config) do |env|
216
+ env['api.tilt.root'] = Rails.root.join "app", "views", "api"
217
+ end
218
+ end
219
+ ```
220
+
221
+ Mount application to rails router
222
+
223
+ ```ruby
224
+ # routes.rb
225
+ GrapeExampleRails::Application.routes.draw do
226
+ mount MyAPI , :at => "/api"
227
+ end
228
+ ```
229
+
230
+ ## Swagger documentation
231
+
232
+ Use [grape-swagger](https://github.com/ruby-grape/grape-swagger) to generate Swagger/OpenAPI 2.0 documentation. Rabl still renders the responses: Swagger does not infer a response schema by executing a template or reading its Ruby code.
233
+
234
+ One option is to define documentation-only entities with the optional [grape-swagger-entity](https://github.com/ruby-grape/grape-swagger-entity) parser. Add these gems to your application's Gemfile, choosing versions compatible with your Grape version:
235
+
236
+ ```ruby
237
+ gem 'grape-rabl'
238
+ gem 'grape-entity'
239
+ gem 'grape-swagger'
240
+ gem 'grape-swagger-entity'
241
+ ```
242
+
243
+ Load the parser before generating documentation. For example, with an application-provided `User` model:
244
+
245
+ ```ruby
246
+ # config.ru
247
+ require 'grape/rabl'
248
+ require 'grape-swagger'
249
+ require 'grape-swagger/entity'
250
+
251
+ class UserFields < Grape::Entity
252
+ expose :id, documentation: { type: Integer }
253
+ expose :name, documentation: { type: String }
254
+ end
255
+
256
+ class UserResponse < Grape::Entity
257
+ expose :user, using: UserFields
258
+ end
259
+
260
+ class API < Grape::API
261
+ format :json
262
+ formatter :json, Grape::Formatter::Rabl
263
+
264
+ desc 'Return a user', success: UserResponse
265
+ get '/users/:id', rabl: 'user' do
266
+ @user = User.find(params[:id])
267
+ end
268
+
269
+ add_swagger_documentation
270
+ end
271
+
272
+ use Rack::Config do |env|
273
+ env['api.tilt.root'] = File.expand_path('views', __dir__)
274
+ end
275
+ run API
276
+ ```
277
+
278
+ ```ruby
279
+ # views/user.rabl
280
+ object @user => :user
281
+ attributes :id, :name
282
+ ```
283
+
284
+ `GET /users/1` returns a Rabl-rendered response such as `{ "user": { "id": 1, "name": "Jane" } }`. `GET /swagger_doc` returns the documentation, with the endpoint's success response referencing `UserResponse` and its nested `UserFields` definition.
285
+
286
+ The entities describe the output only; do not call `present` or replace the Rabl formatter with an Entity formatter. `success: UserResponse` selects the documented schema, not the response serializer. Documentation endpoints have no Rabl template and use the normal JSON fallback.
287
+
288
+ Keep the schema aligned with the actual template, including root envelopes, collections, layouts, partials, and conditional fields. These are not inferred from Rabl automatically. For a schema system other than Entity, use grape-swagger's [custom model parser interface](https://github.com/ruby-grape/grape-swagger#custom-model-parsers). None of these documentation dependencies is required for normal Rabl rendering.
289
+
290
+ ## Specs
291
+
292
+ Spec runs generate `coverage/lcov/grape-rabl.lcov` with SimpleCov. CI merges coverage from every stable Ruby/Grape matrix job in Coveralls using the built-in GitHub token; ruby-head remains experimental and does not publish coverage.
293
+
294
+ See ["Writing Tests"](https://github.com/ruby-grape/grape#writing-tests) in [grape](https://github.com/ruby-grape/grape) README.
295
+
296
+ Enjoy :)
297
+
298
+ ## Contributing
299
+
300
+ See [CONTRIBUTING](CONTRIBUTING.md).
data/RELEASING.md CHANGED
@@ -1,64 +1,79 @@
1
1
  # Releasing Grape-Rabl
2
2
 
3
- There're no particular rules about when to release grape-rabl. Release bug fixes frequently, features not so frequently and breaking API changes rarely.
3
+ Release bug fixes frequently, features less frequently, and breaking API changes deliberately. Publishing requires repository push access, RubyGems ownership, and RubyGems multi-factor authentication.
4
4
 
5
- ### Release
5
+ ## Prepare the release
6
6
 
7
- Run tests, check that all tests succeed locally.
7
+ Use a clean checkout whose `origin` points to the canonical `ruby-grape/grape-rabl` repository, not a fork:
8
8
 
9
+ ```sh
10
+ git remote get-url origin
11
+ git switch master
12
+ git pull --ff-only origin master
13
+ git status --short
9
14
  ```
10
- bundle install
11
- rake
12
- ```
13
-
14
- Check that the last build succeeded in [Travis CI](https://travis-ci.org/ruby-grape/grape-rabl) for all supported platforms.
15
15
 
16
- Increment the version, modify [lib/grape-rabl/version.rb](lib/grape-rabl/version.rb).
16
+ Update `Grape::Rabl::VERSION` in [lib/grape-rabl/version.rb](lib/grape-rabl/version.rb). Increment the patch version for fixes and the minor version for new features or breaking changes while the gem is below 1.0.
17
17
 
18
- * Increment the third number if the release has bug fixes and/or very minor features, only (eg. change `0.7.1` to `0.7.2`).
19
- * Increment the second number if the release contains major features or breaking API changes (eg. change `0.7.1` to `0.8.0`).
18
+ Replace `(Next)` in [CHANGELOG.md](CHANGELOG.md) with the version and release date, remove `Your contribution here.`, and keep entries contiguous with a single blank line between release sections:
20
19
 
21
- Change "Next Release" in [CHANGELOG.md](CHANGELOG.md) to the new version.
20
+ ```markdown
21
+ #### 0.6.0 (2026-10-27)
22
22
 
23
+ * Release entry.
23
24
  ```
24
- ### 0.7.2 (February 6, 2014)
25
- ```
26
-
27
- Remove the line with "Your contribution here.", since there will be no more contributions to this release.
28
25
 
29
- Commit your changes.
26
+ Resolve dependencies if necessary and run the existing lint and spec tasks:
30
27
 
28
+ ```sh
29
+ bundle install
30
+ bundle exec rake
31
31
  ```
32
- git add CHANGELOG.md lib/grape-rabl/version.rb
33
- git commit -m "Preparing for release, 0.7.2."
32
+
33
+ Commit and push the release preparation:
34
+
35
+ ```sh
36
+ git add CHANGELOG.md RELEASING.md lib/grape-rabl/version.rb
37
+ git commit -m "Prepare grape-rabl 0.6.0"
34
38
  git push origin master
35
39
  ```
36
40
 
37
- Release.
41
+ Wait for the [GitHub Actions test workflow](https://github.com/ruby-grape/grape-rabl/actions/workflows/test.yml) to pass for that exact commit. The test matrix covers the supported Ruby/Grape combinations, including an experimental ruby-head job. If using a release-preparation PR, also require its Danger checks to pass; Danger does not run on direct pushes to `master`. Review the minimum Ruby requirement and other compatibility changes before publishing.
38
42
 
39
- ```
40
- $ rake release
43
+ ## Publish
41
44
 
42
- grape-rabl 0.7.2 built to pkg/grape-rabl-0.7.2.gem.
43
- Tagged v0.7.2.
44
- Pushed git commits and tags.
45
- Pushed grape-rabl 0.7.2 to rubygems.org.
45
+ Confirm that the version is not already published and that the worktree is clean. From the canonical checkout, Bundler's release task builds the gem, creates and pushes the version tag, and publishes to RubyGems:
46
+
47
+ ```sh
48
+ bundle exec rake release
46
49
  ```
47
50
 
48
- ### Prepare for the Next Version
51
+ Supply a fresh RubyGems one-time password when requested. Never put credentials or one-time passwords in repository files. If publishing fails after the tag was pushed, diagnose the failure and resume with `gem push pkg/grape-rabl-0.6.0.gem`; do not move an existing release tag.
49
52
 
50
- Add the next release to [CHANGELOG.md](CHANGELOG.md).
53
+ Verify that the RubyGems version, gem checksum, and remote tag match the artifact and release commit:
51
54
 
55
+ ```sh
56
+ gem specification pkg/grape-rabl-0.6.0.gem version
57
+ shasum -a 256 pkg/grape-rabl-0.6.0.gem
58
+ curl --fail https://rubygems.org/api/v2/rubygems/grape-rabl/versions/0.6.0.json
59
+ git ls-remote origin 'refs/tags/v0.6.0*'
52
60
  ```
53
- #### Next
54
61
 
55
- * Your contribution here.
62
+ Create a non-draft GitHub release from the existing tag using the matching changelog section as its release notes:
63
+
64
+ ```sh
65
+ gh release create v0.6.0 --repo ruby-grape/grape-rabl \
66
+ --verify-tag --title "grape-rabl 0.6.0" --notes-file /path/to/release-notes.txt
56
67
  ```
57
68
 
58
- Commit your changes.
69
+ ## Prepare the next development version
59
70
 
71
+ After confirming publication, bump the version to the next patch development iteration and add an empty changelog section:
72
+
73
+ ```markdown
74
+ #### (Next)
75
+
76
+ * Your contribution here.
60
77
  ```
61
- git add CHANGELOG.md
62
- git commit -m "Preparing for next development iteration, 0.7.3."
63
- git push origin master
64
- ```
78
+
79
+ For example, after releasing 0.6.0, set the version to `0.6.1`, commit the version and changelog changes, and push `master` normally. Never force-push `master` or overwrite a published gem or release tag.
data/Rakefile CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env rake
2
+ # frozen_string_literal: true
3
+
2
4
  require 'bundler/gem_tasks'
3
5
 
4
6
  require 'rspec/core'
@@ -11,4 +13,4 @@ end
11
13
  require 'rubocop/rake_task'
12
14
  RuboCop::RakeTask.new(:rubocop)
13
15
 
14
- task default: [:rubocop, :spec]
16
+ task default: %i[rubocop spec]