grape_ape_rails 0.5.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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/grape_ape_rails.gemspec +46 -0
- data/lib/generators/setup_generator.rb +59 -0
- data/lib/generators/templates/initializer.rb +22 -0
- data/lib/grape_ape_rails/api.rb +88 -0
- data/lib/grape_ape_rails/base.rb +27 -0
- data/lib/grape_ape_rails/handlers/formatters.rb +134 -0
- data/lib/grape_ape_rails/handlers/header_versioning.rb +27 -0
- data/lib/grape_ape_rails/handlers/locale.rb +24 -0
- data/lib/grape_ape_rails/handlers/rails_logging.rb +33 -0
- data/lib/grape_ape_rails/handlers/responses.rb +32 -0
- data/lib/grape_ape_rails/handlers.rb +22 -0
- data/lib/grape_ape_rails/railtie.rb +9 -0
- data/lib/grape_ape_rails/version.rb +3 -0
- data/lib/grape_ape_rails.rb +55 -0
- data/lib/swagger/grape_swagger_modified.rb +470 -0
- data/lib/tasks/routes.rake +13 -0
- data/spec/dummy/.rspec +1 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +15 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/api/base.rb +18 -0
- data/spec/dummy/app/controllers/api/v1/monkeys.rb +17 -0
- data/spec/dummy/app/controllers/api/v1/widgets.rb +57 -0
- data/spec/dummy/app/controllers/api/v2/widgets.rb +18 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/models/monkey.rb +3 -0
- data/spec/dummy/app/models/monkey_serializer.rb +7 -0
- data/spec/dummy/app/models/widget.rb +6 -0
- data/spec/dummy/app/views/api/v1/base_widget.rabl +1 -0
- data/spec/dummy/app/views/api/v1/widget.rabl +2 -0
- data/spec/dummy/app/views/api/v1/widgets.rabl +2 -0
- data/spec/dummy/app/views/api/v2/base_widget.rabl +2 -0
- data/spec/dummy/app/views/api/v2/widget.rabl +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +28 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/grape_ape_rails.rb +23 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +5 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20140714154355_create_widgets.rb +10 -0
- data/spec/dummy/db/migrate/20140804173544_create_monkeys.rb +9 -0
- data/spec/dummy/db/schema.rb +30 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/requests/v1/monkeys_spec.rb +22 -0
- data/spec/requests/v1/widgets_spec.rb +125 -0
- data/spec/requests/v2/widgets_spec.rb +41 -0
- data/spec/spec_helper.rb +102 -0
- metadata +524 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 89bad81f1ef60d0be3b4f853574c8074cb8d4146
|
4
|
+
data.tar.gz: 2bd838b6accee93b10c03222b79812e2f8c79dcc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 37e00989c6ebfaa0d198cbec297d31b785e67a7814e9fc92c4a65073ef7197dfd19bae8549ae5fa45da9de7fb1dc233d7e712b6699bfed9423b229c0b768f5f2
|
7
|
+
data.tar.gz: ab3e091b4de17060f961a596293eaed147d46df39d685896b7c23f0795f5980b1469aace37a65446fe072ac649c60463815bb8aa2586914e412a88a965a4220b
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
grape-ape-rails
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.2
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Matt E. Patterson
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# GrapeApeRails
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'grape_ape_rails'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install grape_ape_rails
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it ( http://github.com/<my-github-username>/grape_ape_rails/fork )
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'grape_ape_rails/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "grape_ape_rails"
|
8
|
+
spec.version = GrapeApeRails::VERSION
|
9
|
+
spec.authors = ["Matt E. Patterson"]
|
10
|
+
spec.email = ["madraziel@gmail.com"]
|
11
|
+
spec.summary = %q{Provides customized Grape API functionality inside Rails}
|
12
|
+
spec.description = %q{Provides customized Grape API functionality inside Rails}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'activesupport'
|
22
|
+
spec.add_dependency 'multi_json'
|
23
|
+
spec.add_dependency 'oj'
|
24
|
+
spec.add_dependency "grape", "0.8.0"
|
25
|
+
spec.add_dependency 'grape-rabl'
|
26
|
+
spec.add_dependency 'grape-kaminari'
|
27
|
+
spec.add_dependency 'grape-rails-cache'
|
28
|
+
spec.add_dependency 'kramdown'
|
29
|
+
spec.add_dependency 'grape-active_model_serializers'
|
30
|
+
spec.add_dependency 'http_accept_language'
|
31
|
+
spec.add_dependency 'rabl'
|
32
|
+
spec.add_dependency 'hashie_rails'
|
33
|
+
|
34
|
+
spec.add_development_dependency "rails", "~> 4.1"
|
35
|
+
spec.add_development_dependency "minitest"
|
36
|
+
spec.add_development_dependency "sqlite3"
|
37
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
38
|
+
spec.add_development_dependency "rake"
|
39
|
+
spec.add_development_dependency "factory_girl_rails"
|
40
|
+
spec.add_development_dependency "rspec-rails", '~> 3.0.0'
|
41
|
+
spec.add_development_dependency 'shoulda-matchers'
|
42
|
+
spec.add_development_dependency 'database_cleaner'
|
43
|
+
spec.add_development_dependency 'timecop'
|
44
|
+
spec.add_development_dependency 'pry'
|
45
|
+
spec.add_development_dependency 'webmock'
|
46
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'digest'
|
2
|
+
module GrapeApeRails
|
3
|
+
module Generators
|
4
|
+
DEFAULT_TILT_ROOT = "app/views/api"
|
5
|
+
|
6
|
+
class SetupGenerator < Rails::Generators::Base
|
7
|
+
source_root File.expand_path("../../templates", __FILE__)
|
8
|
+
desc "Sets up GrapeApeRails for your application"
|
9
|
+
|
10
|
+
def create_initializer
|
11
|
+
say "\n\nCreating an initializer..."
|
12
|
+
say ("-"*80)
|
13
|
+
org_name = ask("Provide a name for your organization (all lowercase please):")
|
14
|
+
if org_name.blank?
|
15
|
+
say_status "error", "You must provide an organization name!", :red
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
app_name = ask("Provide a name for this app (all lowercase please):")
|
19
|
+
if app_name.blank?
|
20
|
+
say_status "error", "You must provide a name for the app!", :red
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
api_key = ask("Provide the primary API Secret Key (leave blank and I'll create one for you):")
|
24
|
+
if api_key.blank?
|
25
|
+
api_key = Digest::SHA256.hexdigest("#{app_name}#{Time.now.to_f.to_s}")
|
26
|
+
end
|
27
|
+
copy_file "initializer.rb", "config/initializers/grape_ape_rails.rb"
|
28
|
+
gsub_file "config/initializers/grape_ape_rails.rb", '%%ORGNAME%%', org_name.downcase, verbose: false
|
29
|
+
gsub_file "config/initializers/grape_ape_rails.rb", '%%APPNAME%%', app_name.downcase, verbose: false
|
30
|
+
gsub_file "config/initializers/grape_ape_rails.rb", '%%APIKEY%%', api_key, verbose: false
|
31
|
+
end
|
32
|
+
|
33
|
+
def configure_tilt_root
|
34
|
+
say "\n\nConfiguring Tilt for RABL templates..."
|
35
|
+
say ("-"*80)
|
36
|
+
|
37
|
+
if yes?("Will you be using RABL templates? (y/n)")
|
38
|
+
tilt_root = ask("What will be your RABL templates' root directory (default: #{DEFAULT_TILT_ROOT})?")
|
39
|
+
tilt_root = DEFAULT_TILT_ROOT if tilt_root.blank?
|
40
|
+
tilt_root = tilt_root[1..-1] if tilt_root[0] == '/'
|
41
|
+
say_status "modified", "config/application.rb", :green
|
42
|
+
say_status "NOTE", "Added a Rack::Config middleware block. You might have to move this around later once you start adding more stuff to your application.rb. It should generally be at the end.", :white
|
43
|
+
else
|
44
|
+
tilt_root = DEFAULT_TILT_ROOT
|
45
|
+
say_status "NOTE", "We'll set the default in case you want to use RABL later. You can always change it in application.rb", :white
|
46
|
+
say_status "modified", "config/application.rb", :green
|
47
|
+
end
|
48
|
+
application do
|
49
|
+
<<-RUBY.gsub(/^ {4}/, '')
|
50
|
+
config.middleware.use(Rack::Config) do |env|
|
51
|
+
env['api.tilt.root'] = Rails.root.join "#{tilt_root}"
|
52
|
+
end
|
53
|
+
RUBY
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
GrapeApeRails.configure do |config|
|
2
|
+
config.app_name = "%%APPNAME%%"
|
3
|
+
config.organization_name = "&&ORGNAME&&"
|
4
|
+
config.api_secret_key = "%%APIKEY%%"
|
5
|
+
# config.api_header_security_enabled = true
|
6
|
+
# config.api_security_algorithm = "sha256"
|
7
|
+
# config.security_envelope_debug = false
|
8
|
+
config.available_locales = %i[ en ]
|
9
|
+
end
|
10
|
+
|
11
|
+
# Subscribe to grape request and log with Rails.logger
|
12
|
+
ActiveSupport::Notifications.subscribe('grape.request') do |name, starts, ends, notification_id, payload|
|
13
|
+
api_version = payload[:api_version] ? "[#{payload[:api_version]}]" : nil
|
14
|
+
Rails.logger.info "[API]%s %s %s (%.3f ms) -> %s %s" % [
|
15
|
+
api_version,
|
16
|
+
payload[:request_method],
|
17
|
+
payload[:request_path],
|
18
|
+
(ends-starts)*1000,
|
19
|
+
(payload[:response_status] || "error"),
|
20
|
+
payload[:params] ? "| #{payload[:params].inspect}" : ""
|
21
|
+
]
|
22
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'grape'
|
2
|
+
require 'grape-kaminari'
|
3
|
+
require 'grape-rails-cache'
|
4
|
+
require 'swagger/grape_swagger_modified'
|
5
|
+
require 'hashie_rails' if defined?(::Rails)
|
6
|
+
require 'http_accept_language'
|
7
|
+
require 'grape_ape_rails/base'
|
8
|
+
require 'grape_ape_rails/handlers/header_versioning'
|
9
|
+
require 'grape_ape_rails/handlers/rails_logging'
|
10
|
+
|
11
|
+
|
12
|
+
module GrapeApeRails
|
13
|
+
class API < Grape::API
|
14
|
+
|
15
|
+
def self.api_keys_map
|
16
|
+
@api_keys_map ||= {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.api_version_cascades_map
|
20
|
+
@api_version_cascades ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.api_secret_key
|
24
|
+
@api_secret_key
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.api_secret_key=(val)
|
28
|
+
@api_secret_key = val
|
29
|
+
end
|
30
|
+
|
31
|
+
def API.grape_apis(&block)
|
32
|
+
res = yield
|
33
|
+
include GrapeApeRails::Base
|
34
|
+
res
|
35
|
+
end
|
36
|
+
|
37
|
+
# args:
|
38
|
+
# [0] => version name (e.g. 'v1')
|
39
|
+
# [1] => (optional) an array of cascades (e.g. ['V2', 'V1'])
|
40
|
+
def API.api(name, *args, &block)
|
41
|
+
puts "Spinning up Grape API: #{name} ..."
|
42
|
+
@gar_api_version = name
|
43
|
+
mounts_klass = Class.new(GrapeApeRails::API)
|
44
|
+
klass = GrapeApeRails.const_set("#{name}Base", mounts_klass)
|
45
|
+
api_key = GrapeApeRails.configuration.api_secret_key
|
46
|
+
api_key = args[0] if args[0].present? && args[0].is_a?(String)
|
47
|
+
|
48
|
+
api_version = name.underscore.gsub('_','.')
|
49
|
+
if args[0].present? && args[0].is_a?(Array)
|
50
|
+
GrapeApeRails::API.api_version_cascades_map.merge!({ api_version => args[0].map{ |v| v.underscore.gsub('_','.') } })
|
51
|
+
elsif args[1].present? && args[1].is_a?(Array)
|
52
|
+
GrapeApeRails::API.api_version_cascades_map.merge!({ api_version => args[1].map{ |v| v.underscore.gsub('_','.') } })
|
53
|
+
end
|
54
|
+
dotname = name.underscore.gsub('_','.')
|
55
|
+
GrapeApeRails::API.api_keys_map.merge!({ dotname => api_key })
|
56
|
+
yield
|
57
|
+
mount mounts_klass
|
58
|
+
ensure
|
59
|
+
puts "Swaggering #{api_version} endpoints..."
|
60
|
+
klass.add_swagger_documentation hide_documentation_path: true,
|
61
|
+
api_version: api_version.gsub('.','_'),
|
62
|
+
mount_with_version: true,
|
63
|
+
mount_path: "/api/docs"
|
64
|
+
end
|
65
|
+
|
66
|
+
def API.grape_mount(resource)
|
67
|
+
mounts_klass = "GrapeApeRails::#{@gar_api_version}Base".constantize
|
68
|
+
name = "API::#{@gar_api_version}::#{resource.to_s.camelize}"
|
69
|
+
puts " endpoints: #{name}"
|
70
|
+
mounts_klass.send(:mount, name.constantize)
|
71
|
+
rescue NameError => e
|
72
|
+
puts " [ERROR] Could not instantiate API Endpoints at '#{name}'. Maybe you still need to create the class file?"
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class Grape::Endpoint
|
79
|
+
def error!(message, status = nil, headers = nil)
|
80
|
+
if defined?(::Rails) && Rails.respond_to?(:logger)
|
81
|
+
api_version = "[#{env['rack.routing_args'][:route_info].route_version}]" rescue nil
|
82
|
+
Rails.logger.warn "[API]#{api_version} Responding with #{status} #{message}"
|
83
|
+
end
|
84
|
+
status = settings[:default_error_status] unless status
|
85
|
+
throw :error, message: message, status: status, headers: headers
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'grape'
|
2
|
+
require 'http_accept_language'
|
3
|
+
|
4
|
+
module GrapeApeRails
|
5
|
+
module Base
|
6
|
+
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
use ::GrapeApeRails::Handlers::RailsLogging
|
11
|
+
|
12
|
+
['/health', '/'].each do |route|
|
13
|
+
get route do
|
14
|
+
status 200
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# global exception handler, used for error notifications
|
20
|
+
rescue_from :all do |e|
|
21
|
+
error_response(message: { error: { code: "INTERNAL_SERVER_ERROR", message: e.message } }, status: 500)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
require 'rabl'
|
3
|
+
require 'grape-active_model_serializers'
|
4
|
+
|
5
|
+
Rabl.configure do |config|
|
6
|
+
config.include_json_root = false
|
7
|
+
end
|
8
|
+
Rabl.register!
|
9
|
+
|
10
|
+
module Grape
|
11
|
+
module Formatter
|
12
|
+
module GarJsonSerializer
|
13
|
+
def self.call(resource, env)
|
14
|
+
MultiJson.dump({ result: resource })
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
module GarError
|
20
|
+
def self.call(message, backtrace, options, env)
|
21
|
+
err = { error: { code: 'ERROR', message: message } }
|
22
|
+
if message.is_a?(Hash) && message[:code].present? && message[:message].present?
|
23
|
+
full_msg = "[#{message[:code]}] #{message[:message]}"
|
24
|
+
err = { error: { code: message[:code], message: full_msg } }
|
25
|
+
err[:error].merge!({ data: message[:data] }) if message[:data].present?
|
26
|
+
elsif message.respond_to?(:error_code) && message.respond_to?(:message)
|
27
|
+
full_msg = "[#{message.error_code}] #{message.message}"
|
28
|
+
err = { error: { code: message.error_code, message: full_msg } }
|
29
|
+
end
|
30
|
+
MultiJson.dump err
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module GarActiveModelSerializers
|
35
|
+
def self.call(resource, env)
|
36
|
+
if serializer = Grape::Formatter::ActiveModelSerializers.fetch_serializer(resource, env)
|
37
|
+
single = serializer.try(:resource_singular) || serializer.object.class.name.underscore
|
38
|
+
plural = serializer.try(:resource_plural) || serializer.object.class.name.underscore.pluralize
|
39
|
+
hash = serializer.as_json
|
40
|
+
output = if hash[single].present?
|
41
|
+
hash[single].is_a?(Array) ? hash[single] : [hash[single]]
|
42
|
+
else
|
43
|
+
hash.is_a?(Array) ? hash : [hash]
|
44
|
+
end
|
45
|
+
template = MultiJson.dump({ result: { plural => "***" } })
|
46
|
+
template.gsub(%Q("***"), MultiJson.dump(output))
|
47
|
+
else
|
48
|
+
Grape::Formatter::GarJsonSerializer.call serializer.object, env
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module GarRabl
|
54
|
+
class << self
|
55
|
+
attr_reader :env
|
56
|
+
attr_reader :endpoint
|
57
|
+
|
58
|
+
def call(object, env)
|
59
|
+
@env = env
|
60
|
+
@endpoint = env['api.endpoint']
|
61
|
+
if rablable?
|
62
|
+
rabl do |template|
|
63
|
+
engine = ::Tilt.new(view_path(template), tilt_options)
|
64
|
+
output = engine.render endpoint, {}
|
65
|
+
output = wrap_output(output)
|
66
|
+
if layout_template
|
67
|
+
layout_template.render(endpoint) { output }
|
68
|
+
else
|
69
|
+
output
|
70
|
+
end
|
71
|
+
end
|
72
|
+
else
|
73
|
+
Grape::Formatter::GarJsonSerializer.call object, env
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def wrap_output(output)
|
80
|
+
# root_resource = endpoint.route.route_namespace.gsub('/','').pluralize
|
81
|
+
template = MultiJson.dump({ result: "***" })
|
82
|
+
# output = "[#{output}]" if output[0] != '[' && output[-1] != ']'
|
83
|
+
template.gsub(%Q("***"), output)
|
84
|
+
end
|
85
|
+
|
86
|
+
def view_path(template)
|
87
|
+
# api_version = endpoint.route.route_version || '.'
|
88
|
+
if template.split('.')[-1] == 'rabl'
|
89
|
+
File.join(env['api.tilt.root'], template)
|
90
|
+
else
|
91
|
+
File.join(env['api.tilt.root'], (template + '.rabl'))
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def rablable?
|
96
|
+
!!endpoint.options[:route_options][:rabl]
|
97
|
+
end
|
98
|
+
|
99
|
+
def rabl
|
100
|
+
template = endpoint.options[:route_options][:rabl]
|
101
|
+
fail 'missing rabl template' unless template
|
102
|
+
set_view_root unless env['api.tilt.root']
|
103
|
+
yield template
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_view_root
|
107
|
+
fail "Use Rack::Config to set 'api.tilt.root' in config.ru"
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_layouts_base
|
111
|
+
fail "Use Rack::Config to set 'api.title.layouts_base' in config.ru"
|
112
|
+
end
|
113
|
+
|
114
|
+
def tilt_options
|
115
|
+
{ format: env['api.format'], view_path: env['api.tilt.root'] }
|
116
|
+
end
|
117
|
+
|
118
|
+
def layout_template
|
119
|
+
set_layouts_base unless env['api.tilt.layouts_base']
|
120
|
+
ver = env['rack.routing_args'][:route_info].route_version
|
121
|
+
layout_path = "#{env['api.tilt.layouts_base']}/#{ver}.json.haml"
|
122
|
+
if File.exist?(layout_path)
|
123
|
+
::Tilt.new(layout_path, tilt_options.merge(format: :xhtml, ugly: true))
|
124
|
+
else
|
125
|
+
nil
|
126
|
+
end
|
127
|
+
rescue
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|