├── .coveralls.yml
├── .gitignore
├── .rspec
├── .rubocop.yml
├── .rubocop_todo.yml
├── .travis.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Dangerfile
├── Gemfile
├── LICENSE
├── README.md
├── RELEASING.md
├── Rakefile
├── UPGRADING.md
├── grape-rabl.gemspec
├── lib
├── grape-rabl.rb
├── grape-rabl
│ ├── configuration.rb
│ ├── formatter.rb
│ ├── render.rb
│ ├── tilt.rb
│ └── version.rb
└── grape
│ └── rabl.rb
└── spec
├── grape_rabl_configuration.rb
├── grape_rabl_formatter_spec.rb
├── grape_rabl_layout_spec.rb
├── grape_rabl_partials_spec.rb
├── grape_rabl_spec.rb
├── grape_rabl_xml_spec.rb
├── spec_helper.rb
├── support
└── my_helper.rb
└── views
├── _partial.rabl
├── admin.rabl
├── helper.rabl
├── info.rabl
├── layout_test
├── layouts
│ ├── another.rabl
│ └── application.rabl
└── user.rabl
├── project.rabl
└── user.rabl
/.coveralls.yml:
--------------------------------------------------------------------------------
1 | service_name: travis-ci
2 | repo_token: budbVe8MwqMKtO4OalAxPvXy4P4kY284P
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.gem
2 | *.rbc
3 | .bundle
4 | .config
5 | .yardoc
6 | Gemfile.lock
7 | InstalledFiles
8 | _yardoc
9 | coverage
10 | doc/
11 | lib/bundler/man
12 | pkg
13 | rdoc
14 | spec/reports
15 | test/tmp
16 | test/version_tmp
17 | tmp
18 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --format=documentation
3 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | Exclude:
3 | - vendor/**
4 | - .bundle
5 |
6 | inherit_from: .rubocop_todo.yml
7 |
--------------------------------------------------------------------------------
/.rubocop_todo.yml:
--------------------------------------------------------------------------------
1 | # This configuration was generated by
2 | # `rubocop --auto-gen-config`
3 | # on 2017-11-17 09:51:46 -0500 using RuboCop version 0.51.0.
4 | # The point is for the user to remove these configuration records
5 | # one by one as the offenses are removed from the code base.
6 | # Note that changes in the inspected code, or installation of new
7 | # versions of RuboCop, may require this file to be generated again.
8 |
9 | # Offense count: 1
10 | Lint/RescueException:
11 | Exclude:
12 | - 'spec/grape_rabl_spec.rb'
13 |
14 | # Offense count: 8
15 | # Configuration parameters: CountComments, ExcludedMethods.
16 | Metrics/BlockLength:
17 | Max: 169
18 |
19 | # Offense count: 23
20 | # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
21 | # URISchemes: http, https
22 | Metrics/LineLength:
23 | Max: 148
24 |
25 | # Offense count: 1
26 | # Configuration parameters: CountComments.
27 | Metrics/MethodLength:
28 | Max: 13
29 |
30 | # Offense count: 1
31 | # Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
32 | # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
33 | Naming/FileName:
34 | Exclude:
35 | - 'lib/grape-rabl.rb'
36 |
37 | # Offense count: 5
38 | Style/Documentation:
39 | Exclude:
40 | - 'spec/**/*'
41 | - 'test/**/*'
42 | - 'lib/grape-rabl.rb'
43 | - 'lib/grape-rabl/configuration.rb'
44 | - 'lib/grape-rabl/formatter.rb'
45 | - 'lib/grape-rabl/render.rb'
46 | - 'lib/grape/rabl.rb'
47 |
48 | # Offense count: 1
49 | Style/DoubleNegation:
50 | Exclude:
51 | - 'lib/grape-rabl/formatter.rb'
52 |
53 | # Offense count: 1
54 | Style/IfInsideElse:
55 | Exclude:
56 | - 'lib/grape-rabl/formatter.rb'
57 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | before_install: gem install bundler -v '1.15.0'
2 | rvm:
3 | - 2.2.0
4 | - 2.3.0
5 | - ruby-head
6 |
7 | matrix:
8 | include:
9 | - rvm: 2.3.1
10 | script:
11 | - bundle exec danger
12 | allow_failures:
13 | - rvm: ruby-head
14 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | #### Next
2 |
3 | * Your contribution here.
4 |
5 | #### v0.5.0
6 |
7 | * [#34](https://github.com/ruby-grape/grape-rabl/pulls/34): If no RABL template is specified, fallback to the default response format as determined by Grape - [@chrisbloom7](https://github.com/chrisbloom7).
8 |
9 | #### v0.4.3
10 |
11 | * [#44](https://github.com/ruby-grape/grape-rabl/issues/44): Don't require unused hashie - [@tsuwatch](https://github.com/tsuwatch).
12 | * [#44](https://github.com/ruby-grape/grape-rabl/issues/44): Support Ruby >= 2.2 - [@tsuwatch](https://github.com/tsuwatch).
13 | * [#45](https://github.com/ruby-grape/grape-rabl/pull/45): Added danger, PR linter - [@dblock](https://github.com/dblock).
14 |
15 | #### v0.4.2
16 |
17 | * [#43](https://github.com/ruby-grape/grape-rabl/pull/43): Fix template caching for multiple formats - [@kushkella](https://github.com/kushkella).
18 |
19 | #### v0.4.1
20 |
21 | * [#39](https://github.com/ruby-grape/grape-rabl/issues/39): Automatically require 'grape/rabl' - [@martinezcoder](https://github.com/martinezcoder).
22 |
23 | #### v0.4.0
24 |
25 | * [#37](https://github.com/ruby-grape/grape-rabl/issues/37): Make grape-rabl thread-safe - [@kushkella](https://github.com/kushkella).
26 |
27 | #### v0.3.1
28 |
29 | * [#35](https://github.com/ruby-grape/grape-rabl/issues/35): The `render` method will no longer modify endpoint options at runtime - [@yesmeck](https://github.com/yesmeck).
30 |
31 | #### v0.3.0
32 |
33 | * [#22](https://github.com/ruby-grape/grape-rabl/pull/22): Enable using a layout template in Rabl - [@koko1000ban](https://github.com/koko1000ban).
34 | * Implemented Rubocop, Ruby style linter - [@dblock](https://github.com/dblock).
35 | * Removed JRuby support - [@dblock](https://github.com/dblock).
36 | * Enable using locals with `.render` - [@hobofan](https://github.com/hobofan).
37 | * Enable support for template caching - [@kushkella](https://github.com/kushkella).
38 |
39 |
40 | #### v0.2.2
41 |
42 | * [#20](https://github.com/ruby-grape/grape-rabl/pull/20): Relaxed dependency on a specific version of Grape - [@cheef](https://github.com/cheef).
43 |
44 | #### v0.2.1
45 |
46 | * [#11](https://github.com/ruby-grape/grape-rabl/pull/11): Fix: render template according to request format - [@alovak](https://github.com/alovak).
47 |
48 | #### v0.2.0
49 |
50 | * [#10](https://github.com/ruby-grape/grape-rabl/pull/10): Allow to use partials in Grape - [@ichilton](https://github.com/ichilton).
51 | * Stick to gem conventions - [@LTe](https://github.com/lte).
52 | * [#13](https://github.com/ruby-grape/grape-rabl/pull/13): Update for Grape 0.3 compatibility - [@alovak](https://github.com/alovak).
53 | * Format fix - [@LTe](https://github.com/LTe).
54 |
55 | #### v0.1.0
56 |
57 | * Updated w/released Grape 0.2.3 - [@dblock](https://github.com/dblock).
58 | * Added link to Rabl - [@dblock](https://github.com/dblock).
59 | * Grape 0.2.x and put back dependency status - [@dblock](https://github.com/dblock).
60 | * Grape 0.2.3 - [@dblock](https://github.com/dblock).
61 | * Updated Grape dependency via .gemspec - [@dblock](https://github.com/dblock).
62 |
63 | #### v0.0.6
64 |
65 | * [#6](https://github.com/ruby-grape/grape-rabl/pull/6): Use Grape formatter syntax instead of monkey-patching - [@dblock](https://github.com/dblock).
66 | * Close block code in README - [@LTe](https://github.com/LTe).
67 | * Change home to user - [@LTe](https://github.com/LTe).
68 |
69 | #### v0.0.5
70 |
71 | * Respect `default_format` for rabl response - [@LTe](https://github.com/LTe).
72 |
73 | #### v0.0.4
74 |
75 | * Require `grape/rabl` - [@LTe](https://github.com/LTe).
76 |
77 | #### v0.0.3
78 |
79 | * Template without `.rabl` - [@LTe](https://github.com/LTe).
80 |
81 | #### v0.0.2
82 |
83 | * Add Travis - [@LTe](https://github.com/LTe).
84 | * Remove ruby debug - [@LTe](https://github.com/LTe).
85 | * Works with rubinius - [@LTe](https://github.com/LTe).
86 | * Add dependency status - [@LTe](https://github.com/LTe).
87 |
88 | #### v0.0.1
89 |
90 | * Initial public release - [@LTe](https://github.com/lte).
91 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributing to Grape-Rabl
2 | ==========================
3 |
4 | Grape-Rabl is work of [many of contributors](https://github.com/ruby-grape/grape-rabl/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/ruby-grape/grape-rabl/pulls), [propose features and discuss issues](https://github.com/ruby-grape/grape-rabl/issues). When in doubt, ask a question in the [Grape Google Group](http://groups.google.com/group/ruby-grape).
5 |
6 | #### Fork the Project
7 |
8 | Fork the [project on Github](https://github.com/ruby-grape/grape-rabl) and check out your copy.
9 |
10 | ```
11 | git clone https://github.com/contributor/grape-rabl.git
12 | cd grape-rabl
13 | git remote add upstream https://github.com/ruby-grape/grape-rabl.git
14 | ```
15 |
16 | #### Create a Topic Branch
17 |
18 | Make sure your fork is up-to-date and create a topic branch for your feature or bug fix.
19 |
20 | ```
21 | git checkout master
22 | git pull upstream master
23 | git checkout -b my-feature-branch
24 | ```
25 |
26 | #### Bundle Install and Test
27 |
28 | Ensure that you can build the project and run tests.
29 |
30 | ```
31 | bundle install
32 | bundle exec rake
33 | ```
34 |
35 | #### Write Tests
36 |
37 | Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build. Add to [spec/grape-rabl](spec/grape-rabl).
38 |
39 | We definitely appreciate pull requests that highlight or reproduce a problem, even without a fix.
40 |
41 | #### Write Code
42 |
43 | Implement your feature or bug fix.
44 |
45 | Ruby style is enforced with [Rubocop](https://github.com/bbatsov/rubocop), run `bundle exec rubocop` and fix any style issues highlighted.
46 |
47 | Make sure that `bundle exec rake` completes without errors.
48 |
49 | #### Write Documentation
50 |
51 | Document any external behavior in the [README](README.md).
52 |
53 | #### Update Changelog
54 |
55 | Add a line to [CHANGELOG](CHANGELOG.md) under *Next Release*. Make it look like every other line, including your name and link to your Github account.
56 |
57 | #### Commit Changes
58 |
59 | Make sure git knows your name and email address:
60 |
61 | ```
62 | git config --global user.name "Your Name"
63 | git config --global user.email "contributor@example.com"
64 | ```
65 |
66 | Writing good commit logs is important. A commit log should describe what changed and why.
67 |
68 | ```
69 | git add ...
70 | git commit
71 | ```
72 |
73 | #### Push
74 |
75 | ```
76 | git push origin my-feature-branch
77 | ```
78 |
79 | #### Make a Pull Request
80 |
81 | Go to https://github.com/contributor/grape-rabl and select your feature branch. Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
82 |
83 | #### Rebase
84 |
85 | If you've been working on a change for a while, rebase with upstream/master.
86 |
87 | ```
88 | git fetch upstream
89 | git rebase upstream/master
90 | git push origin my-feature-branch -f
91 | ```
92 |
93 | #### Update CHANGELOG Again
94 |
95 | Update the [CHANGELOG](CHANGELOG.md) with the pull request number. A typical entry looks as follows.
96 |
97 | ```
98 | * [#123](https://github.com/ruby-grape/grape-rabl/pull/123): Reticulated splines - [@contributor](https://github.com/contributor).
99 | ```
100 |
101 | Amend your previous commit and force push the changes.
102 |
103 | ```
104 | git commit --amend
105 | git push origin my-feature-branch -f
106 | ```
107 |
108 | #### Check on Your Pull Request
109 |
110 | Go back to your pull request after a few minutes and see whether it passed muster with Travis-CI. Everything should look green, otherwise fix issues and amend your commit as described above.
111 |
112 | #### Be Patient
113 |
114 | It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang on there!
115 |
116 | #### Thank You
117 |
118 | Please do know that we really appreciate and value your time and work. We love you, really.
119 |
--------------------------------------------------------------------------------
/Dangerfile:
--------------------------------------------------------------------------------
1 | danger.import_dangerfile(gem: 'ruby-grape-danger')
2 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gemspec
4 |
5 | group :development do
6 | gem 'rubocop', '0.51.0'
7 | end
8 |
9 | group :test do
10 | gem 'coveralls', require: false
11 | gem 'json'
12 | gem 'rabl'
13 | gem 'rack-test'
14 | gem 'rake'
15 | gem 'rspec'
16 | gem 'ruby-grape-danger', '~> 0.1.1', require: false
17 | end
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012 Piotr Niełacny
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Grape::Rabl
2 |
3 | Use [Rabl](https://github.com/nesquena/rabl) templates in [Grape](https://github.com/ruby-grape/grape)!
4 |
5 | [](http://badge.fury.io/rb/grape-rabl)
6 | [](https://travis-ci.org/ruby-grape/grape-rabl)
7 | [](https://codeclimate.com/github/ruby-grape/grape-rabl)
8 | [](https://coveralls.io/r/ruby-grape/grape-rabl?branch=master)
9 |
10 | ## Installation
11 |
12 | Add the `grape` and `grape-rabl` gems to Gemfile.
13 |
14 | ```ruby
15 | gem 'grape'
16 | gem 'grape-rabl'
17 | ```
18 |
19 | And then execute:
20 |
21 | $ bundle
22 |
23 | ## Upgrading
24 |
25 | See [UPGRADING](UPGRADING.md).
26 |
27 | ## Usage
28 |
29 | ### Setup view root directory
30 |
31 | ```ruby
32 | # config.ru
33 | use Rack::Config do |env|
34 | env['api.tilt.root'] = '/path/to/view/root/directory'
35 | end
36 | ```
37 |
38 | ### Tell your API to use Grape::Formatter::Rabl
39 |
40 | ```ruby
41 | class API < Grape::API
42 | format :json
43 | formatter :json, Grape::Formatter::Rabl
44 | end
45 | ```
46 |
47 | ### Use rabl templates conditionally
48 |
49 | Add the template name to the API options.
50 |
51 | ```ruby
52 | get "/user/:id", :rabl => "user.rabl" do
53 | @user = User.find(params[:id])
54 | end
55 | ```
56 |
57 | You can use instance variables in the Rabl template.
58 |
59 | ```ruby
60 | object @user => :user
61 | attributes :name, :email
62 |
63 | child @project => :project do
64 | attributes :name
65 | end
66 | ```
67 |
68 | ### Use rabl layout
69 |
70 | Gape-rabl first looks for a layout file in `#{env['api.tilt.root']}/layouts/application.rabl`.
71 |
72 | You can override the default layout conventions:
73 |
74 | ```ruby
75 | # config.ru
76 | use Rack::Config do |env|
77 | env['api.tilt.root'] = '/path/to/view/root/directory'
78 | env['api.tilt.layout'] = 'layouts/another'
79 | end
80 | ```
81 |
82 | ### Enable template caching
83 |
84 | Grape-rabl allows for template caching after templates are loaded initially.
85 |
86 | You can enable template caching:
87 |
88 | ```ruby
89 | # config.ru
90 | Grape::Rabl.configure do |config|
91 | config.cache_template_loading = true # default: false
92 | end
93 | ```
94 |
95 | ## You can omit .rabl
96 |
97 | The following are identical.
98 |
99 | ```ruby
100 | get "/home", :rabl => "view"
101 | get "/home", :rabl => "view.rabl"
102 | ```
103 |
104 | ### Example
105 |
106 | ```ruby
107 | # config.ru
108 | use Rack::Config do |env|
109 | env['api.tilt.root'] = '/path/to/view/root/directory'
110 | end
111 |
112 | class UserAPI < Grape::API
113 | format :json
114 | formatter :json, Grape::Formatter::Rabl
115 |
116 | get '/user/:id' do
117 | @user = User.find(params[:id])
118 |
119 | # use rabl with 'user.rabl' or 'admin.rabl' template
120 | if @user.admin?
121 | # pass locals with the #render method
122 | render rabl: 'admin', locals: { details: 'this user is an admin' }
123 | else
124 | render rabl: 'user'
125 | end
126 | end
127 |
128 | get '/admin/:id', :rabl => 'admin' do
129 | @user = User.find(params[:id])
130 |
131 | # use rabl with 'super_admin.rabl'
132 | render rabl: 'super_admin' if @user.super_admin?
133 | # when render method has not been used use template from endpoint definition
134 | end
135 |
136 | # use rabl with 'user_history.rabl' template
137 | get '/user/:id/history', :rabl => 'user_history' do
138 | @history = User.find(params[:id]).history
139 | end
140 |
141 | # do not use rabl, fallback to the default Grape response formatter
142 | get '/users' do
143 | User.all
144 | end
145 | end
146 | ```
147 |
148 | ```ruby
149 | # user.rabl
150 | object @user => :user
151 |
152 | attributes :name
153 | ```
154 |
155 | ## Usage with rails
156 |
157 | Create grape application
158 |
159 | ```ruby
160 | # app/api/user.rb
161 | class MyAPI < Grape::API
162 | format :json
163 | formatter :json, Grape::Formatter::Rabl
164 | get '/user/:id', :rabl => "user" do
165 | @user = User.find(params[:id])
166 | end
167 | end
168 | ```
169 |
170 | ```ruby
171 | # app/views/api/user.rabl
172 | object @user => :user
173 | ```
174 |
175 | Edit your **config/application.rb** and add view path
176 |
177 | ```ruby
178 | # application.rb
179 | class Application < Rails::Application
180 | config.middleware.use(Rack::Config) do |env|
181 | env['api.tilt.root'] = Rails.root.join "app", "views", "api"
182 | end
183 | end
184 | ```
185 |
186 | Mount application to rails router
187 |
188 | ```ruby
189 | # routes.rb
190 | GrapeExampleRails::Application.routes.draw do
191 | mount MyAPI , :at => "/api"
192 | end
193 | ```
194 |
195 | ## Specs
196 |
197 | See ["Writing Tests"](https://github.com/ruby-grape/grape#writing-tests) in [grape](https://github.com/ruby-grape/grape) README.
198 |
199 | Enjoy :)
200 |
201 | ## Contributing
202 |
203 | See [CONTRIBUTING](CONTRIBUTING.md).
204 |
--------------------------------------------------------------------------------
/RELEASING.md:
--------------------------------------------------------------------------------
1 | # Releasing Grape-Rabl
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.
4 |
5 | ### Release
6 |
7 | Run tests, check that all tests succeed locally.
8 |
9 | ```
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 |
16 | Increment the version, modify [lib/grape-rabl/version.rb](lib/grape-rabl/version.rb).
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`).
20 |
21 | Change "Next Release" in [CHANGELOG.md](CHANGELOG.md) to the new version.
22 |
23 | ```
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 |
29 | Commit your changes.
30 |
31 | ```
32 | git add CHANGELOG.md lib/grape-rabl/version.rb
33 | git commit -m "Preparing for release, 0.7.2."
34 | git push origin master
35 | ```
36 |
37 | Release.
38 |
39 | ```
40 | $ rake release
41 |
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.
46 | ```
47 |
48 | ### Prepare for the Next Version
49 |
50 | Add the next release to [CHANGELOG.md](CHANGELOG.md).
51 |
52 | ```
53 | #### Next
54 |
55 | * Your contribution here.
56 | ```
57 |
58 | Commit your changes.
59 |
60 | ```
61 | git add CHANGELOG.md
62 | git commit -m "Preparing for next development iteration, 0.7.3."
63 | git push origin master
64 | ```
65 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 | require 'bundler/gem_tasks'
3 |
4 | require 'rspec/core'
5 | require 'rspec/core/rake_task'
6 | RSpec::Core::RakeTask.new(:spec) do |spec|
7 | spec.rspec_opts = ['-fd -c']
8 | spec.pattern = FileList['spec/**/*_spec.rb']
9 | end
10 |
11 | require 'rubocop/rake_task'
12 | RuboCop::RakeTask.new(:rubocop)
13 |
14 | task default: %i[rubocop spec]
15 |
--------------------------------------------------------------------------------
/UPGRADING.md:
--------------------------------------------------------------------------------
1 | # Upgrading Grape::Rabl
2 |
3 | ## Upgrading to >= 0.5
4 |
5 | ### Fallback rendering when no RABL template is defined
6 |
7 | 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)
8 |
9 | ```ruby
10 | class SampleApi < Grape::API
11 | format :xml
12 | formatter :xml, Grape::Formatter::Rabl
13 |
14 | get 'list' do
15 | %w[thing]
16 | end
17 | end
18 | ```
19 |
20 | #### Former behavior
21 |
22 | ```ruby
23 | response.body # => ["thing"]
24 | ```
25 |
26 | #### Current behavior
27 |
28 | ```ruby
29 | response.body # => \n\n thing\n
30 | ```
31 |
32 | See [#34](https://github.com/ruby-grape/grape-rabl/pull/34) for more information.
33 |
--------------------------------------------------------------------------------
/grape-rabl.gemspec:
--------------------------------------------------------------------------------
1 |
2 | require File.expand_path('../lib/grape-rabl/version', __FILE__)
3 |
4 | Gem::Specification.new do |gem|
5 | gem.authors = ['Piotr Niełacny']
6 | gem.email = ['piotr.nielacny@gmail.com']
7 | gem.description = 'Use rabl in grape'
8 | gem.summary = 'Use rabl in grape'
9 | gem.homepage = 'https://github.com/ruby-grape/grape-rabl'
10 |
11 | gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
12 | gem.files = `git ls-files`.split("\n")
13 | gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14 | gem.name = 'grape-rabl'
15 | gem.require_paths = ['lib']
16 | gem.version = Grape::Rabl::VERSION
17 | gem.required_ruby_version = '>= 2.2.0'
18 |
19 | gem.add_dependency 'grape'
20 | gem.add_dependency 'i18n'
21 | gem.add_dependency 'rabl'
22 | gem.add_dependency 'tilt'
23 | end
24 |
--------------------------------------------------------------------------------
/lib/grape-rabl.rb:
--------------------------------------------------------------------------------
1 | require 'rabl'
2 | require 'grape'
3 | require 'grape/rabl'
4 | require 'grape-rabl/tilt'
5 | require 'grape-rabl/version'
6 | require 'grape-rabl/formatter'
7 | require 'grape-rabl/render'
8 | require 'grape-rabl/configuration'
9 |
10 | module Grape
11 | module Rabl
12 | class << self
13 | def configure
14 | yield(configuration)
15 | configuration
16 | end
17 |
18 | def configuration
19 | @configuration ||= Configuration.new
20 | end
21 |
22 | def reset_configuration!
23 | @configuration = nil
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/lib/grape-rabl/configuration.rb:
--------------------------------------------------------------------------------
1 | module Grape
2 | module Rabl
3 | class Configuration
4 | attr_accessor :cache_template_loading
5 |
6 | def initialize
7 | @cache_template_loading = false
8 | end
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/lib/grape-rabl/formatter.rb:
--------------------------------------------------------------------------------
1 | require 'json'
2 |
3 | module Grape
4 | module Rabl
5 | class Formatter
6 | class << self
7 | def tilt_cache
8 | @tilt_cache ||= ::Tilt::Cache.new
9 | end
10 | end
11 |
12 | attr_reader :env, :endpoint, :object
13 |
14 | def initialize(object, env)
15 | @env = env
16 | @endpoint = env['api.endpoint']
17 | @object = object
18 | end
19 |
20 | def render
21 | if rablable?
22 | rabl do |template|
23 | engine = tilt_template(template)
24 | output = engine.render endpoint, locals
25 | if layout_template
26 | layout_template.render(endpoint) { output }
27 | else
28 | output
29 | end
30 | end
31 | else
32 | fallback_formatter.call object, env
33 | end
34 | end
35 |
36 | private
37 |
38 | # Find a formatter to fallback to. `env[Grape::Env::API_FORMAT]` will always be a
39 | # valid formatter, otherwise a HTTP 406 error would have already have been thrown
40 | def fallback_formatter
41 | Grape::Formatter.formatter_for(env[Grape::Env::API_FORMAT])
42 | end
43 |
44 | def view_path(template)
45 | if template.split('.')[-1] == 'rabl'
46 | File.join(env['api.tilt.root'], template)
47 | else
48 | File.join(env['api.tilt.root'], (template + '.rabl'))
49 | end
50 | end
51 |
52 | def rablable?
53 | !!rabl_template
54 | end
55 |
56 | def rabl
57 | raise 'missing rabl template' unless rabl_template
58 | set_view_root unless env['api.tilt.root']
59 | yield rabl_template
60 | end
61 |
62 | def locals
63 | env['api.tilt.rabl_locals'] || endpoint.options[:route_options][:rabl_locals] || {}
64 | end
65 |
66 | def rabl_template
67 | env['api.tilt.rabl'] || endpoint.options[:route_options][:rabl]
68 | end
69 |
70 | def set_view_root
71 | raise "Use Rack::Config to set 'api.tilt.root' in config.ru"
72 | end
73 |
74 | def tilt_template(template)
75 | if Grape::Rabl.configuration.cache_template_loading
76 | Grape::Rabl::Formatter.tilt_cache.fetch(tilt_cache_key(template)) { ::Tilt.new(view_path(template), tilt_options) }
77 | else
78 | ::Tilt.new(view_path(template), tilt_options)
79 | end
80 | end
81 |
82 | def tilt_options
83 | { format: env['api.format'], view_path: env['api.tilt.root'] }
84 | end
85 |
86 | def layout_template
87 | layout_path = view_path(env['api.tilt.layout'] || 'layouts/application')
88 | if Grape::Rabl.configuration.cache_template_loading
89 | Grape::Rabl::Formatter.tilt_cache.fetch(tilt_cache_key(layout_path)) { ::Tilt.new(layout_path, tilt_options) if File.exist?(layout_path) }
90 | else
91 | ::Tilt.new(layout_path, tilt_options) if File.exist?(layout_path)
92 | end
93 | end
94 |
95 | def tilt_cache_key(path)
96 | Digest::MD5.hexdigest("#{path}#{tilt_options}")
97 | end
98 | end
99 | end
100 | end
101 |
--------------------------------------------------------------------------------
/lib/grape-rabl/render.rb:
--------------------------------------------------------------------------------
1 | module Grape
2 | module Rabl
3 | module Render
4 | def render(options = {})
5 | env['api.tilt.rabl'] = options[:rabl]
6 | env['api.tilt.rabl_locals'] = options[:locals]
7 | end
8 | end
9 | end
10 | end
11 |
12 | Grape::Endpoint.send(:include, Grape::Rabl::Render)
13 |
--------------------------------------------------------------------------------
/lib/grape-rabl/tilt.rb:
--------------------------------------------------------------------------------
1 | require 'tilt'
2 |
3 | Rabl.register!
4 |
--------------------------------------------------------------------------------
/lib/grape-rabl/version.rb:
--------------------------------------------------------------------------------
1 | module Grape
2 | module Rabl
3 | VERSION = '0.5.0'.freeze
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/lib/grape/rabl.rb:
--------------------------------------------------------------------------------
1 | require 'grape-rabl'
2 |
3 | module Grape
4 | module Formatter
5 | module Rabl
6 | class << self
7 | def call(object, env)
8 | Grape::Rabl::Formatter.new(object, env).render
9 | end
10 | end
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/grape_rabl_configuration.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'Grape::Rabl configuration' do
4 | context 'configuration' do
5 | it 'returns default values' do
6 | expect(Grape::Rabl.configuration.cache_template_loading).to eq(false)
7 | end
8 |
9 | it 'should set and reset configuration' do
10 | Grape::Rabl.configure do |config|
11 | config.cache_template_loading = true
12 | end
13 | expect(Grape::Rabl.configuration.cache_template_loading).to eq(true)
14 | Grape::Rabl.reset_configuration!
15 | expect(Grape::Rabl.configuration.cache_template_loading).to eq(false)
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/spec/grape_rabl_formatter_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'Grape::Rabl formatter' do
4 | subject do
5 | Class.new(Grape::API)
6 | end
7 |
8 | let(:xml_render) do
9 | %(
10 |
11 |
12 | bad
13 | things
14 | happened
15 |
16 |
17 | )
18 | end
19 |
20 | def app
21 | subject
22 | end
23 |
24 | context 'rendering' do
25 | context 'when no rabl template is specified' do
26 | before do
27 | # Grape::API defaults to the following declarations:
28 | # content_type :xml, 'application/xml'
29 | # content_type :json, 'application/json'
30 | # content_type :binary, 'application/octet-stream'
31 | # content_type :txt, 'text/plain'
32 | # default_format :txt
33 | subject.formatter :xml, Grape::Formatter::Rabl
34 | subject.formatter :txt, Grape::Formatter::Rabl
35 | subject.get('/oops') { { errors: %w[bad things happened] } }
36 | expect_any_instance_of(Grape::Rabl::Formatter).to receive(:render).and_call_original
37 | end
38 |
39 | it 'falls back to :txt given no other format information' do
40 | get '/oops'
41 | expect(last_response.body).to eq('{:errors=>["bad", "things", "happened"]}')
42 | expect(last_response.headers['Content-Type']).to eq('text/plain')
43 | end
44 |
45 | it 'falls back to the file extension if it is a valid format' do
46 | get '/oops.xml'
47 | expect(last_response.body).to eq(xml_render)
48 | expect(last_response.headers['Content-Type']).to eq('application/xml')
49 | end
50 |
51 | it 'falls back to the value of the `format` parameter in the query string if it is provided' do
52 | get '/oops?format=xml'
53 | expect(last_response.body).to eq(xml_render)
54 | expect(last_response.headers['Content-Type']).to eq('application/xml')
55 | end
56 |
57 | it 'falls back to the format set by the `format` option if it is a valid format' do
58 | # `format` option must be declared before endpoint
59 | subject.format :xml
60 | subject.get('/oops/2') { { errors: %w[bad things happened] } }
61 |
62 | get '/oops/2'
63 | expect(last_response.body).to eq(xml_render)
64 | expect(last_response.headers['Content-Type']).to eq('application/xml')
65 | end
66 |
67 | it 'falls back to the `Accept` header if it is a valid format' do
68 | get '/oops', {}, 'HTTP_ACCEPT' => 'application/xml'
69 | expect(last_response.body).to eq(xml_render)
70 | expect(last_response.headers['Content-Type']).to eq('application/xml')
71 | end
72 |
73 | it 'falls back to the default_format option if it is a valid format' do
74 | # `default_format` option must be declared before endpoint
75 | subject.default_format :xml
76 | subject.get('/oops/2') { { errors: %w[bad things happened] } }
77 |
78 | get '/oops/2'
79 | expect(last_response.body).to eq(xml_render)
80 | expect(last_response.headers['Content-Type']).to eq('application/xml')
81 | end
82 | end
83 | end
84 | end
85 |
--------------------------------------------------------------------------------
/spec/grape_rabl_layout_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'Grape::Rabl layout' do
4 | let(:parsed_response) { JSON.parse(last_response.body) }
5 |
6 | subject do
7 | Class.new(Grape::API)
8 | end
9 |
10 | before do
11 | subject.format :json
12 | subject.formatter :json, Grape::Formatter::Rabl
13 | subject.before do
14 | env['api.tilt.root'] = "#{File.dirname(__FILE__)}/views/layout_test"
15 | end
16 | end
17 |
18 | def app
19 | subject
20 | end
21 |
22 | context 'default' do
23 | it 'proper render with default layout' do
24 | subject.get('/about', rabl: 'user') do
25 | @user = OpenStruct.new(name: 'LTe')
26 | @project = OpenStruct.new(name: 'First')
27 | @status = 200
28 | end
29 |
30 | get('/about')
31 | expect(parsed_response).to eq(
32 | JSON.parse(%({"status":200,"result":{"user":{"name":"LTe","project":{"name":"First"}}}}))
33 | )
34 | end
35 | end
36 |
37 | context 'tilt layout is setup' do
38 | before do
39 | subject.before { env['api.tilt.layout'] = 'layouts/another' }
40 | end
41 |
42 | it 'proper render with specified layout' do
43 | subject.get('/about', rabl: 'user') do
44 | @user = OpenStruct.new(name: 'LTe')
45 | @project = OpenStruct.new(name: 'First')
46 | @status = 200
47 | end
48 |
49 | get('/about')
50 | puts last_response.body
51 | expect(parsed_response).to eq(
52 | JSON.parse(%({"result":{"user":{"name":"LTe","project":{"name":"First"}}}}))
53 | )
54 | end
55 | end
56 |
57 | context 'layout cache' do
58 | before do
59 | @views_dir = FileUtils.mkdir_p("#{File.expand_path('..', File.dirname(__FILE__))}/tmp")[0]
60 | @layout = "#{@views_dir}/layouts/application.rabl"
61 | FileUtils.cp_r("#{File.dirname(__FILE__)}/views/layout_test/.", @views_dir)
62 | subject.before { env['api.tilt.root'] = "#{File.expand_path('..', File.dirname(__FILE__))}/tmp" }
63 | subject.get('/home', rabl: 'user') do
64 | @user = OpenStruct.new(name: 'LTe', email: 'email@example.com')
65 | @project = OpenStruct.new(name: 'First')
66 | @status = 200
67 | end
68 | end
69 |
70 | after do
71 | Grape::Rabl.reset_configuration!
72 | FileUtils.rm_f(@views_dir)
73 | end
74 |
75 | it 'should serve from cache if cache_template_loading' do
76 | Grape::Rabl.configure do |config|
77 | config.cache_template_loading = true
78 | end
79 | get '/home'
80 | expect(last_response.status).to eq(200)
81 | old_response = last_response.body
82 | open(@layout, 'a') { |f| f << 'node(:test) { "test" }' }
83 | get '/home'
84 | expect(last_response.status).to eq(200)
85 | new_response = last_response.body
86 | expect(old_response).to eq(new_response)
87 | end
88 |
89 | it 'should serve new template if cache_template_loading' do
90 | get '/home'
91 | expect(last_response.status).to eq(200)
92 | old_response = last_response.body
93 | open(@layout, 'a') { |f| f << 'node(:test) { "test" }' }
94 | get '/home'
95 | expect(last_response.status).to eq(200)
96 | new_response = last_response.body
97 | expect(old_response).not_to eq(new_response)
98 | end
99 | end
100 | end
101 |
--------------------------------------------------------------------------------
/spec/grape_rabl_partials_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'Grape::Rabl partials' do
4 | let(:parsed_response) { JSON.parse(last_response.body) }
5 |
6 | subject do
7 | Class.new(Grape::API)
8 | end
9 |
10 | before do
11 | subject.format :json
12 | subject.formatter :json, Grape::Formatter::Rabl
13 | subject.before { env['api.tilt.root'] = "#{File.dirname(__FILE__)}/views" }
14 | end
15 |
16 | def app
17 | subject
18 | end
19 |
20 | it 'proper render partials' do
21 | subject.get('/home', rabl: 'project') do
22 | @author = OpenStruct.new(author: 'LTe')
23 | @type = OpenStruct.new(type: 'paper')
24 | @project = OpenStruct.new(name: 'First', type: @type, author: @author)
25 | end
26 |
27 | get('/home')
28 | expect(parsed_response).to eq(
29 | JSON.parse('{"project":{"name":"First","info":{"type":"paper"},"author":{"author":"LTe"}}}')
30 | )
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/spec/grape_rabl_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Grape::Rabl do
4 | subject do
5 | Class.new(Grape::API)
6 | end
7 |
8 | before do
9 | subject.default_format :json
10 | subject.formatter :json, Grape::Formatter::Rabl
11 | subject.formatter :xml, Grape::Formatter::Rabl
12 | subject.helpers MyHelper
13 | end
14 |
15 | def app
16 | subject
17 | end
18 |
19 | it 'should work without rabl template' do
20 | subject.get('/home') { 'Hello World' }
21 | get '/home'
22 | expect(last_response.body).to eq('"Hello World"')
23 | end
24 |
25 | it 'should raise error about root directory' do
26 | begin
27 | subject.get('/home', rabl: true) {}
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
32 | end
33 |
34 | context 'titl root is setup' do
35 | let(:parsed_response) { JSON.parse(last_response.body) }
36 |
37 | before do
38 | subject.before { env['api.tilt.root'] = "#{File.dirname(__FILE__)}/views" }
39 | end
40 |
41 | describe 'helpers' do
42 | it 'should execute helper' do
43 | subject.get('/home', rabl: 'helper') { @user = OpenStruct.new }
44 | get '/home'
45 | expect(parsed_response).to eq(JSON.parse('{"user":{"helper":"my_helper"}}'))
46 | end
47 | end
48 |
49 | describe '#render' do
50 | before do
51 | subject.get('/home', rabl: 'user') do
52 | @user = OpenStruct.new(name: 'LTe')
53 | render rabl: 'admin'
54 | end
55 |
56 | subject.get('/admin/:id', rabl: 'user') do
57 | @user = OpenStruct.new(name: 'LTe')
58 |
59 | render rabl: 'admin' if params[:id] == '1'
60 | end
61 |
62 | subject.get('/home-detail', rabl: 'user') do
63 | @user = OpenStruct.new(name: 'LTe')
64 | render rabl: 'admin', locals: { details: 'amazing detail' }
65 | end
66 |
67 | subject.get('/about', rabl: 'user') do
68 | @user = OpenStruct.new(name: 'LTe')
69 | end
70 |
71 | subject.get('/about-detail', rabl: 'user') do
72 | @user = OpenStruct.new(name: 'LTe')
73 | render locals: { details: 'just a user' }
74 | end
75 | end
76 |
77 | it 'renders template passed as argument to render method' do
78 | get('/home')
79 | expect(parsed_response).to eq(JSON.parse('{"admin":{"name":"LTe"}}'))
80 | end
81 |
82 | it 'renders admin template' do
83 | get('/admin/1')
84 | expect(parsed_response).to eq(JSON.parse('{"admin":{"name":"LTe"}}'))
85 | end
86 |
87 | it 'renders user template' do
88 | get('/admin/2')
89 | expect(parsed_response).to eq(JSON.parse('{"user":{"name":"LTe","project":null}}'))
90 | end
91 |
92 | it 'renders template passed as argument to render method with locals' do
93 | get('/home-detail')
94 | expect(parsed_response).to eq(JSON.parse('{"admin":{"name":"LTe","details":"amazing detail"}}'))
95 | end
96 |
97 | it 'renders with locals without overriding template' do
98 | get('/about-detail')
99 | expect(parsed_response).to eq(JSON.parse('{"user":{"name":"LTe","details":"just a user","project":null}}'))
100 | end
101 |
102 | it 'does not save rabl options after called #render method' do
103 | get('/home')
104 | get('/about')
105 | expect(parsed_response).to eq(JSON.parse('{"user":{"name":"LTe","project":null}}'))
106 | end
107 |
108 | it 'does not modify endpoint options' do
109 | get '/home'
110 | expect(last_request.env['api.endpoint'].options[:route_options][:rabl]).to eq 'user'
111 | end
112 | end
113 |
114 | it 'should respond with proper content-type' do
115 | subject.get('/home', rabl: 'user') {}
116 | get('/home')
117 | expect(last_response.headers['Content-Type']).to eq('application/json')
118 | end
119 |
120 | it 'should not raise error about root directory' do
121 | subject.get('/home', rabl: 'user') {}
122 | get '/home'
123 | expect(last_response.status).to eq 200
124 | expect(last_response.body).not_to include "Use Rack::Config to set 'api.tilt.root' in config.ru"
125 | end
126 |
127 | ['user', 'user.rabl'].each do |rabl_option|
128 | it "should render rabl template (#{rabl_option})" do
129 | subject.get('/home', rabl: rabl_option) do
130 | @user = OpenStruct.new(name: 'LTe', email: 'email@example.com')
131 | @project = OpenStruct.new(name: 'First')
132 | end
133 |
134 | get '/home'
135 | expect(parsed_response).to eq(JSON.parse('{"user":{"name":"LTe","email":"email@example.com","project":{"name":"First"}}}'))
136 | end
137 | end
138 |
139 | describe 'template cache' do
140 | before do
141 | @views_dir = FileUtils.mkdir_p("#{File.expand_path('..', File.dirname(__FILE__))}/tmp")[0]
142 | @template = "#{@views_dir}/user.rabl"
143 | FileUtils.cp("#{File.dirname(__FILE__)}/views/user.rabl", @template)
144 | subject.before { env['api.tilt.root'] = "#{File.expand_path('..', File.dirname(__FILE__))}/tmp" }
145 | subject.get('/home', rabl: 'user') do
146 | @user = OpenStruct.new(name: 'LTe', email: 'email@example.com')
147 | @project = OpenStruct.new(name: 'First')
148 | end
149 | end
150 |
151 | after do
152 | Grape::Rabl.reset_configuration!
153 | FileUtils.rm_r(@views_dir)
154 | end
155 |
156 | it 'should serve from cache if cache_template_loading' do
157 | Grape::Rabl.configure do |config|
158 | config.cache_template_loading = true
159 | end
160 | get '/home'
161 | expect(last_response.status).to eq(200)
162 | old_response = last_response.body
163 | open(@template, 'a') { |f| f << 'node(:test) { "test" }' }
164 | get '/home'
165 | expect(last_response.status).to eq(200)
166 | new_response = last_response.body
167 | expect(old_response).to eq(new_response)
168 | end
169 |
170 | it 'should maintain different cached templates for different formats' do
171 | Grape::Rabl.configure do |config|
172 | config.cache_template_loading = true
173 | end
174 | get '/home'
175 | expect(last_response.status).to eq(200)
176 | json_response = last_response.body
177 | get '/home.xml'
178 | expect(last_response.status).to eq(200)
179 | xml_response = last_response.body
180 | expect(json_response).not_to eq(xml_response)
181 | open(@template, 'a') { |f| f << 'node(:test) { "test" }' }
182 | get '/home.xml'
183 | expect(last_response.status).to eq(200)
184 | expect(last_response.body).to eq(xml_response)
185 | get '/home.json'
186 | expect(last_response.status).to eq(200)
187 | expect(last_response.body).to eq(json_response)
188 | end
189 |
190 | it 'should serve new template unless cache_template_loading' do
191 | get '/home'
192 | expect(last_response.status).to eq(200)
193 | old_response = last_response.body
194 | open(@template, 'a') { |f| f << 'node(:test) { "test" }' }
195 | get '/home'
196 | expect(last_response.status).to eq(200)
197 | new_response = last_response.body
198 | expect(old_response).not_to eq(new_response)
199 | end
200 | end
201 | end
202 | end
203 |
--------------------------------------------------------------------------------
/spec/grape_rabl_xml_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Grape::Rabl do
4 | subject do
5 | Class.new(Grape::API)
6 | end
7 |
8 | before do
9 | subject.format :xml
10 | subject.formatter :xml, Grape::Formatter::Rabl
11 | end
12 |
13 | def app
14 | subject
15 | end
16 |
17 | context 'with xml format' do
18 | before do
19 | subject.before do
20 | env['api.tilt.root'] = "#{File.dirname(__FILE__)}/views"
21 | env['api.format'] = :xml
22 | end
23 | end
24 |
25 | it 'should respond with proper content-type' do
26 | subject.get('/home', rabl: 'user') {}
27 | get('/home')
28 | expect(last_response.headers['Content-Type']).to eq('application/xml')
29 | end
30 |
31 | ['user', 'user.rabl'].each do |rabl_option|
32 | it "should render rabl template (#{rabl_option})" do
33 | subject.get('/home', rabl: rabl_option) do
34 | @user = OpenStruct.new(name: 'LTe', email: 'email@example.com')
35 | @project = OpenStruct.new(name: 'First')
36 | end
37 |
38 | get '/home'
39 |
40 | expect(last_response.body).to eq(%(
41 |
42 | LTe
43 | email@example.com
44 |
45 | First
46 |
47 |
48 | ))
49 | end
50 | end
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2 | $LOAD_PATH.unshift(File.dirname(__FILE__))
3 |
4 | require 'bundler'
5 | Bundler.setup :default, :test
6 |
7 | require 'coveralls'
8 | Coveralls.wear!
9 |
10 | require 'active_support/core_ext/hash/conversions'
11 | require 'grape/rabl'
12 | require 'rspec'
13 | require 'rack/test'
14 | require 'ostruct'
15 |
16 | RSpec.configure do |config|
17 | config.include Rack::Test::Methods
18 | config.raise_errors_for_deprecations!
19 | end
20 |
21 | Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
22 |
--------------------------------------------------------------------------------
/spec/support/my_helper.rb:
--------------------------------------------------------------------------------
1 | module MyHelper
2 | def my_helper
3 | 'my_helper'
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/views/_partial.rabl:
--------------------------------------------------------------------------------
1 | attributes :type
2 |
--------------------------------------------------------------------------------
/spec/views/admin.rabl:
--------------------------------------------------------------------------------
1 | object @user => :admin
2 | attributes :name
3 |
4 | node :details, unless: ->(_n) { locals[:details].nil? } do |_m|
5 | locals[:details]
6 | end
7 |
--------------------------------------------------------------------------------
/spec/views/helper.rabl:
--------------------------------------------------------------------------------
1 | object @user => :user
2 |
3 | node(:helper) { my_helper }
4 |
--------------------------------------------------------------------------------
/spec/views/info.rabl:
--------------------------------------------------------------------------------
1 | attributes :author
2 |
--------------------------------------------------------------------------------
/spec/views/layout_test/layouts/another.rabl:
--------------------------------------------------------------------------------
1 | node(:result) do
2 | JSON.parse(yield)
3 | end
4 |
--------------------------------------------------------------------------------
/spec/views/layout_test/layouts/application.rabl:
--------------------------------------------------------------------------------
1 | node(:status) { @status }
2 |
3 | node(:result) do
4 | JSON.parse(yield)
5 | end
6 |
--------------------------------------------------------------------------------
/spec/views/layout_test/user.rabl:
--------------------------------------------------------------------------------
1 | object @user => :user
2 | attributes :name, :email
3 |
4 | child @project => :project do
5 | attributes :name
6 | end
7 |
--------------------------------------------------------------------------------
/spec/views/project.rabl:
--------------------------------------------------------------------------------
1 | object @project => :project
2 | attributes :name
3 |
4 | node :info do
5 | partial 'partial', object: @project.type
6 | end
7 |
8 | child @author => :author do
9 | extends 'info'
10 | end
11 |
--------------------------------------------------------------------------------
/spec/views/user.rabl:
--------------------------------------------------------------------------------
1 | object @user => :user
2 | attributes :name, :email
3 |
4 | child @project => :project do
5 | attributes :name
6 | end
7 |
8 | node :details, unless: ->(_n) { locals[:details].nil? } do |_m|
9 | locals[:details]
10 | end
11 |
--------------------------------------------------------------------------------