grape
An opinionated micro-framework for creating REST-like APIs in Ruby.
Ruby Grape | An opinionated micro-framework for creating REST-like APIs in Ruby.
A sample script ss.groovy:
@Grab(group='org.codehaus.groovy.modules.http-builder',
module='http-builder',
version='0.5.0')
import groovyx.net.http.HTTPBuilder
println('done')
for some reason takes ~25 seconds to load when run with
groovy ss.groovy
and ~5 seconds when run with
groovy -Dgroovy.grape.autoDownload=false ss.groovy
as per this StackOverflow explanation. I tried doing manual initialization with
Grape.enableAutoDownload = false
Grape.grab(group:'org.codehaus.groovy.modules.http-builder',
module:'http-builder',
version:'0.5.0')
import groovyx.net.http.HTTPBuilder
println('done')
but this fails on import with:
/tmp/ss.groovy: 3: unable to resolve class groovyx.net.http.HTTPBuilder
@ line 3, column 1.
import groovyx.net.http.HTTPBuilder
^
Is there a contained way to either:
- Make it not download the artifacts automatically (preferred, as it allows for solving other issues, e.g. external site down while an artifact already exists in the local cache)
- Make it startup faster in any other way
By contained I mean that all additional instructions should be either within script or, if no such one exists, an acceptable default (e.g. don't check the cached artifacts for updates - I would still, however, like to have automatic downloads globally) to be put in some of groovy config files (e.g. ~/.groovy/grapeConfig.xml or similar).
Source: (StackOverflow)
I'm starting to build a really small API and I need to authenticate some endpoints, not all of them. I want to be able to select which endpoint to force authentication with an authenticate!
method to be called in the body of the 'route'.
For example:
resource :groups do
desc 'List all groups.'
get do
authenticate!
{ groups: "list of groups v1"}
end
end
I have this working. I used a helper where I manually get the base64 encoded data from the header using: request.env["HTTP_AUTHORIZATION"]
. I decode that data and check against the database if the user and secret belongs to a registered user. This is working fine, but I want to use Grape's helper to avoid all the base64 decoding etc etc:
http_basic do |username, password|
end
My idea is inside that method always return true, assign username and password to @username and @password and have a helper that grabs those variables and check against the db. All that works fine, the problem is that for routes that doesn't require authentication as the 'Authorization' header is empty the popup asking for password appears, and I want to avoid that. Is there a way to use the helper to do what I want to do??
BTW: I'm using grape mounted on rails-api
Thanks!
Source: (StackOverflow)
I have Rails app with Grape API.
The interface is done with Backbone and Grape API provides it all data.
All it returns is user-specific stuff, so i need reference to currently logged in user.
Simplified version looks like this:
API initialization:
module MyAPI
class API < Grape::API
format :json
helpers MyAPI::APIHelpers
mount MyAPI::Endpoints::Notes
end
end
Endpoint:
module MyAPI
module Endpoints
class Notes < Grape::API
before do
authenticate!
end
# (...) Api methods
end
end
end
API helper:
module MyAPI::APIHelpers
# @return [User]
def current_user
env['warden'].user
end
def authenticate!
unless current_user
error!('401 Unauthorized', 401)
end
end
end
So, as you can see, i get the current user from Warden and it works fine. But the problem is with testing.
describe MyAPI::Endpoints::Notes do
describe 'GET /notes' do
it 'it renders all notes when no keyword is given' do
Note.expects(:all).returns(@notes)
get '/notes'
it_presents(@notes)
end
end
end
How can I stub helpers's method *current_user* with some specific user?
I tried:
- setting env/request, but it doesn't exist before calling get method.
- stubbing MyAPI::APIHelpers#current_user method with Mocha
- stubbing MyAPI::Endpoints::Notes.any_instance.stub with Mocha
Edit:
At the moment, it's stubbed this way:
spec:
# (...)
before :all do
load 'patches/api_helpers'
@user = STUBBED_USER
end
# (...)
spec/patches/api_helpers.rb:
STUBBED_USER = FactoryGirl.create(:user)
module MyAPI::APIHelpers
def current_user
STUBBED_USER
end
end
But it's definitely not the answer :).
Source: (StackOverflow)
After updating my ubuntu system I have problem to run groovy grapes scripts. All dependecies are download but process is still running in about 100 %
I have ubuntu :
lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 12.10
Release: 12.10
Codename: quantal
groovy version:
Groovy Version: 1.8.6 JVM: 1.7.0_25 Vendor: Oracle Corporation OS: Linux
My simple script look like:
@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.6')
@GrabExclude('asm:*')
import groovyx.net.http.*
import groovy.util.CliBuilder
import groovy.xml.XmlUtil
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class MyGroovyScript {
static main(args) {
println "?????"
}
}
and output is:
groovy -Dgroovy.grape.report.downloads=true my-groovy-script.groovy
Resolving dependency: org.codehaus.groovy.modules.http-builder#http-builder;0.6 {default=[default]}
Preparing to download artifact org.codehaus.groovy.modules.http-builder#http-builder;0.6!http-builder.jar
Preparing to download artifact org.apache.httpcomponents#httpclient;4.2.1!httpclient.jar
Preparing to download artifact net.sf.json-lib#json-lib;2.3!json-lib.jar
Preparing to download artifact org.codehaus.groovy#groovy;1.8.8!groovy.jar
Preparing to download artifact net.sourceforge.nekohtml#nekohtml;1.9.16!nekohtml.jar
Preparing to download artifact xml-resolver#xml-resolver;1.2!xml-resolver.jar
Preparing to download artifact org.apache.httpcomponents#httpcore;4.2.1!httpcore.jar
Preparing to download artifact commons-logging#commons-logging;1.1.1!commons-logging.jar
Preparing to download artifact commons-codec#commons-codec;1.6!commons-codec.jar
Preparing to download artifact commons-beanutils#commons-beanutils;1.8.0!commons-beanutils.jar
Preparing to download artifact commons-collections#commons-collections;3.2.1!commons-collections.jar
Preparing to download artifact commons-lang#commons-lang;2.4!commons-lang.jar
Preparing to download artifact net.sf.ezmorph#ezmorph;1.0.6!ezmorph.jar
Preparing to download artifact antlr#antlr;2.7.7!antlr.jar
Preparing to download artifact xerces#xercesImpl;2.9.1!xercesImpl.jar
Preparing to download artifact xml-apis#xml-apis;1.3.04!xml-apis.jar
Downloaded 9854 Kbytes in 134ms:
[SUCCESSFUL ] org.codehaus.groovy.modules.http-builder#http-builder;0.6!http-builder.jar (5ms)
[SUCCESSFUL ] org.apache.httpcomponents#httpclient;4.2.1!httpclient.jar (7ms)
[SUCCESSFUL ] org.apache.httpcomponents#httpcore;4.2.1!httpcore.jar (2ms)
[SUCCESSFUL ] commons-logging#commons-logging;1.1.1!commons-logging.jar (1ms)
[SUCCESSFUL ] commons-codec#commons-codec;1.6!commons-codec.jar (2ms)
[SUCCESSFUL ] net.sf.json-lib#json-lib;2.3!json-lib.jar (2ms)
[SUCCESSFUL ] commons-beanutils#commons-beanutils;1.8.0!commons-beanutils.jar (3ms)
[SUCCESSFUL ] commons-collections#commons-collections;3.2.1!commons-collections.jar (5ms)
[SUCCESSFUL ] commons-lang#commons-lang;2.4!commons-lang.jar (2ms)
[SUCCESSFUL ] net.sf.ezmorph#ezmorph;1.0.6!ezmorph.jar (24ms)
[SUCCESSFUL ] org.codehaus.groovy#groovy;1.8.8!groovy.jar (34ms)
[SUCCESSFUL ] antlr#antlr;2.7.7!antlr.jar (5ms)
[SUCCESSFUL ] net.sourceforge.nekohtml#nekohtml;1.9.16!nekohtml.jar (2ms)
[SUCCESSFUL ] xerces#xercesImpl;2.9.1!xercesImpl.jar (14ms)
[SUCCESSFUL ] xml-apis#xml-apis;1.3.04!xml-apis.jar (3ms)
[SUCCESSFUL ] xml-resolver#xml-resolver;1.2!xml-resolver.jar (2ms)
Source: (StackOverflow)
I'm building a Grape API alongside Sinatra. So far I've been mounting them in separate routes like this:
run Rack::URLMap.new("/" => Frontend::Server.new,
"/api" => API::Server.new)
Where the "/api" is served by a Grape app and "/" by a Sinatra app. But I wanted to use subdomains to separate those concerns instead of the actual "sub-URL". Any clues on how to do this?
Thanks in advance for the help.
Source: (StackOverflow)
I am writing my first automation script in groovy and I've hit a roadblock.
While making use of the AntBuilder class to run sshexec() I run into the following error:
: Problem: failed to create task or type sshexec
Cause: the class org.apache.tools.ant.taskdefs.optional.ssh.SSHExec was not found.
This looks like one of Ant's optional components.
Action: Check that the appropriate optional JAR exists in
-ANT_HOME\lib
-the IDE Ant configuration dialogs
Do not panic, this is a common problem.
The commonest cause is a missing JAR.
This is not a bug; it is a configuration problem
So far the best solution I've found for this is to use
Grape.grab(group : "com.jcraft", module : "jsch", classLoader : this.class.classLoader.rootLoader)
Grape.grab(group:"ant", module:"ant-jsch", classLoader:this.class.classLoader.rootLoader)
in order to load the required modules.
However, I would like to eliminate the lag time of Grape downloading the jars from the remote Maven repository.
Is there a way to download and save modules for future use, perhaps in the JAVA_PATH or something to that effect?
Source: (StackOverflow)
Question
I've been messing with ruby, grape, grape-entity, and activerecord. Everything is going swimmingly however I can't see to get the desired result from grape-entity when using the using
keyword for a expose
item.
My goal is to basically resolve all my activerecord
associations, and then return the resulting JSON. This way I have a complete object for presentation for my configurations API method.
If you need more information, please ask i'll happily provide anything and everything.
Notes: I am using rackup as my server, i'm not using rails at all.
Classes
console_game.rb
class ConsoleGame < ActiveRecord::Base
self.table_name = 'console_game'
self.primary_key = :id
has_many :configurations, :class_name => 'Configuration'
class Entity < Grape::Entity
expose :id
expose :value, :as => :console_game
end
end
cloud_user.rb
class CloudUser < ActiveRecord::Base
self.primary_key = :username
has_many :configurations, :class_name => 'Configuration'
has_many :favorites, :class_name => 'Favorite', :foreign_key => :username
class Entity < Grape::Entity
expose :username, :email, :first_name, :last_name
end
end
device.rb
class Device < ActiveRecord::Base
self.table_name = 'device'
self.primary_key = :id
has_many :configurations, :class_name => 'Configuration'
class Entity < Grape::Entity
expose :id
expose :name, :as => :device
end
end
console_system.rb
class ConsoleSystem < ActiveRecord::Base
self.table_name = 'console_system'
self.primary_key = :id
has_many :configurations, :class_name => 'Configuration'
class Entity < Grape::Entity
expose :id
expose :value, :as => :console_system
end
end
configuration.rb
class Configuration < ActiveRecord::Base
self.table_name = 'configuration'
self.primary_key = :id
belongs_to :console_system, :class_name => 'ConsoleSystem', primary_key: :id, foreign_key: :system_id
belongs_to :cloud_user, :class_name => 'CloudUser', primary_key: :username, foreign_key: :creator
belongs_to :device, :class_name => 'Device', primary_key: :id, foreign_key: :device_id
belongs_to :console_game, :class_name => 'ConsoleGame', primary_key: :id, foreign_key: :console_game_id
scope :by_system,->(system){
system_ids = ConsoleSystem.where(value: system).pluck(:id)
where(system_id: system_ids)
}
scope :by_user,->(user){
user_ids = CloudUser.where(username: user).pluck(:username)
where(creator: user_ids)
}
scope :by_device,->(device){
device_ids = Device.where(name: device).pluck(:id)
where(device_id: device_ids)
}
scope :by_game,->(game){
game_ids = ConsoleGame.where(value: game).pluck(:id)
where(console_game_id: game_ids)
}
class Entity < Grape::Entity
expose :id
expose :value
expose :device_id, :as => :device, using: Device::Entity
expose :system_id, :as => :console_system, using: ConsoleSystem::Entity
expose :console_game_id, :as => :console_game, using: ConsoleGame::Entity
expose :creator, :as => :creator, using: CloudUser::Entity
expose :created_date
expose :positive_votes
expose :negative_votes
end
end
Grape API
resource :configuration do
desc "Returns all configurations."
get do
configs = Configuration.includes(:device, :console_system, :cloud_user, :console_game)
present :data, configs, :with => Configuration::Entity
present :status, "Success"
end
end
Error
NoMethodError at /configuration
undefined method `id' for 4:Fixnum
Ruby /Library/Ruby/Gems/2.0.0/gems/grape-entity-0.4.2/lib/grape_entity/entity.rb: in delegate_attribute, line 465
Web GET localhost/configuration
Removing :using to get it to "work"
configuration.rb
class Entity < Grape::Entity
expose :id
expose :value
expose :device_id, :as => :device#, using: Device::Entity
expose :system_id, :as => :console_system#, using: ConsoleSystem::Entity
expose :console_game_id, :as => :console_game#, using: ConsoleGame::Entity
expose :creator, :as => :creator#, using: CloudUser::Entity
expose :created_date
expose :positive_votes
expose :negative_votes
end
JSON Result
{
data: [
{
id: 1,
value: "configuration data 1 example",
device: 4,
console_system: 1,
console_game: 1,
creator: "manster",
created_date: null,
positive_votes: 0,
negative_votes: 0
},
{
id: 2,
value: "configuration data 2 example",
device: 4,
console_system: null,
console_game: 2,
creator: "Zombieguy",
created_date: null,
positive_votes: 0,
negative_votes: 0
},
{
id: 3,
value: "configuration data 3 example",
device: 4,
console_system: null,
console_game: 3,
creator: "Justin13692",
created_date: null,
positive_votes: 0,
negative_votes: 0
}
],
status: "Success"
}
Desired Result
{
data: [
{
id: 1,
value: "configuration data 1 example",
device: {
id: 4,
device: "XIM Edge"
},
console_system: {
id: 1,
console_system: "Xbox 360"
}
console_game: {
id: 1,
console_game: "Gears of War 3"
},
creator: {
username: "manster",
email: null,
first_name: null,
last_name: null
},
created_date: null,
positive_votes: 0,
negative_votes: 0
},
{
id: 2,
value: "configuration data 2 example",
device: {
id: 4,
device: "XIM Edge"
},
console_system: null,
console_game: {
id: 2,
console_game: "Battlefield 3"
},
creator: {
username: "Zombieguy",
email: null,
first_name: null,
last_name: null
},
created_date: null,
positive_votes: 0,
negative_votes: 0
},
{
id: 3,
value: "configuration data 3 example",
device: {
id: 4,
device: "XIM Edge"
},
console_system: null,
console_game: {
id: 3,
console_game: "Call of Duty: Modern Warfare 3"
},
creator: {
username: "Justin13692",
email: null,
first_name: null,
last_name: null
},
created_date: null,
positive_votes: 0,
negative_votes: 0
}
],
status: "Success"
}
Source: (StackOverflow)
First:
I'm using grape for building my API (Rails 4). When someone is sending an invalid JSON body (e.g. forgot the last }
), the following error is raised:
ActionDispatch::ParamsParser::ParseError (795: unexpected token at '{"foobar": 1234
')
I tried it with grapes rescue_from :all
option, but this doesn't work. Inside the stacktrace, I don't see the grape gem involved. It seems that this error is thrown from actionpack:
.gems/gems/actionpack-4.1.4/lib/action_dispatch/middleware/params_parser.rb:53:in `rescue in parse_formatted_parameters'
.gems/gems/actionpack-4.1.4/lib/action_dispatch/middleware/params_parser.rb:32:in `parse_formatted_parameters'
.gems/gems/actionpack-4.1.4/lib/action_dispatch/middleware/params_parser.rb:23:in `call'
But what would be the best way to catch those errors, return a 400: Bad Request
errors, and include the unexpected token at '{"foobar": 1234
message inside the json response?
Second:
I tried to test this with RSpec, but didn't have any luck on sending a raw request with an invalid JSON. I tried it with
post "/my_route", '{some invalid json'
but this doesn't throw the error from above. I thought since Rails 4, the second parameter, passed as a string, is treated like the raw body?
Source: (StackOverflow)
I am trying to start a GroovyFX project within IntelliJ 12.
However, I have not been able to get IntelliJ to compile and run the following simple script (for reproducing the problem in the simplest manner possible):
@Grab(group='org.codehaus.groovyfx', module='groovyfx', version='0.3.1')
import groovyx.javafx.GroovyFX
println GroovyFX.class.name
I used IntelliJ's support for Grape's Grab to add groovyfx as a dependency of my module (the jar is shown under "External Libraries" and the editor does not complain that the class is missing after that!) but still, when I run the script, it throws an error:
Groovyc: unable to resolve class groovyx.javafx.GroovyFX
I was able to get this script working in the GroovyConsole without much problem and as expected....
I tried grabbing another randomly chosen dependency (turned out to be a Spring library) and it worked straight out:
@Grab(group='org.springframework', module='spring', version='2.5.6')
import org.springframework.jdbc.core.JdbcTemplate
println JdbcTemplate.class.name
I can see no good reason why the Spring library should work, but not the GroovyFX library!!!!
I even double checked that the GroovyFx library had been actually downloaded, and it is there where it should be (under {user.home}/.groovy/grapes/{group}/{module}/jars/)
What can cause this weird and extremely frustrating problem??
Source: (StackOverflow)
For my rails app I set up an API with gem Grape. I add a test post method that the code sleeps 10 seconds and returns {'status'=>'success'}. Everything works except that the API call seems to block all other requests sent to the server. Any other request will not be executed until this sleep 10 seconds api finishes. Any GET request from front end interface will be delayed. And if I simulate two api calls, it takes the second call 20 seconds (10 seconds for waiting the first one finishes) to finish. Please give advise on this.
The api.rb file looks like this:
module ProjectName
module MyErrorFormatter
def self.call message, backtrace, options, env
{ "status" => "Fail", "error_message" => message }.to_json
end
end
class API < Grape::API
format :json
default_format :json
prefix 'api'
cascade false
error_formatter :json, MyErrorFormatter
helpers APIHelpers
before do
authenticate!
end
post do
if params[:action].present?
p_url = format_url(params)
redirect "/api/#{params[:action]}?key=#{params[:key]}#{p_url}"
end
end
post 'test' do
sleep(10)
{'status'=>'success'}
end
end
end
I am using Rails 4.2.0
Source: (StackOverflow)
I am using Grape and Rails to create a REST API. I have the basic architecture in place and I am looking for places to 'clean' things up. One of those places is the error handling/processing.
I am currently rescuing errors in the root.rb (GRAPE::API base class) file for the whole API. I format them and then send the error back via rack_response. Everything works find but the root.rb file is getting a bit bloated with all the errors being rescued and some of them have special parsing that needs to be done. I was wondering if anyone has developed a good strategy for error handling so that it can be moved out into it's own module and leave the root.rb (GRAPE::API base class) fairly lean.
I would really like to create a error processing module and define methods for each type of error, for example...
module API
module ErrorHandler
def record_not_found
rack_response API::Utils::ApiErrors.new({type: e.class.name, message: 'Record not found'}).to_json, 404
end
end
end
Then in the root.rb file do something like this
module API
class Root < Grape::API
prefix 'api'
format :json
helpers API::ErrorHandler
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found # Use the helper method as the handler for this error
end
end
Has anyone done something like this? I have been trying various flavors of the above strategy but I can't seem to get anything work.
Source: (StackOverflow)
I am using grape
gem for API
and grape-entity
to generate responses.
Simple show/get
request is responding fine like returning only data from ActiveRecord Object
. Fine
When i try to include data from has_many
relation it return all the data related to that object. Fine
But when I represent
data like
post = Post.first
data = V1::Entities::PostEntities.represent(post, only: [:id, { comments: [:id, :body] }])
data.as_json
It should return something like this as per documentation:
{
id: 1,
comments: [{
id: 1,
body: 'example'
}]
}
But it returns:
{
id: 1,
comments: [{
id: 1,
user_id: 1,
body: 'example',
created_at: 'some_timestamp',
updated_at: 'also_some_timestamp',
is_deleted: 0,
}]
}
My PostEntities
contains:
module V1
module Entities
class PostEntities < Grape::Entity
expose :id
expose :comments, with: V1::Entities::CommentEntities
end
end
end
My CommentEntities
contains:
module V1
module Entities
class CommentEntities < Grape::Entity
expose :id
expose :user_id
expose :body
expose :created_at
expose :updated_at
expose :is_deleted
end
end
end
there is something wrong with represent
method. i am not getting what the issue is?
Source: (StackOverflow)
I have a working rails application with grape-gem working as an end point for some APIs in the application.
I need to get the remote ip for the requester and return it back in the response.
I could do that on regular controllers using
request.remote_ip
however, in grape calls, the 'request' is not a defined variable.
how can I get access to the remote ip on grape?
Source: (StackOverflow)
When running a script that is using grape system to @Grab a dependency in the ibiblio repo, it fails till I manually call grape resolve
from the command line. After that, it's in the local cache and the script runs fine.
Is there some other annotation that I need to use to get it to work the first time from the script? It feels kludgy to tell users to first "grape resolve" and then @Grab works.
This is the script, grabbing the jedis jar for redis:
#!/usr/bin/env groovy
@Grab('redis.clients:jedis:2.0.0')
import redis.clients.jedis.*
Jedis redis = new Jedis("localhost")
Which fails with this exception if I have a clean ~/.groovy/grapes cache:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
General error during conversion: Error grabbing Grapes -- [unresolved dependency: redis.clients#jedis;2.0.0: ibiblio: unable to get resource for redis/clients#jedis;2.0.0: res=/redis/clients/jedis/2.0.0/jedis-2.0.0.pom: java.net.MalformedURLException: no protocol: /redis/clients/jedis/2.0.0/jedis-2.0.0.pom]
It only runs once I execute grape resolve
manually from the command line:
grape -V resolve redis.clients jedis 2.0.0
(part of the output shows it's downloading from ibiblio):
...
ibiblio: found md file for redis.clients#jedis;2.0.0
=> http://repo1.maven.org/maven2/redis/clients/jedis/2.0.0/jedis-2.0.0.pom (2.0.0)
downloading http://repo1.maven.org/maven2/redis/clients/jedis/2.0.0/jedis-2.0.0.pom ...
ibiblio: downloading http://repo1.maven.org/maven2/redis/clients/jedis/2.0.0/jedis-2.0.0.pom
ibiblio: downloading http://repo1.maven.org/maven2/redis/clients/jedis/2.0.0/jedis-2.0.0.pom.sha1
sha1 OK for http://repo1.maven.org/maven2/redis/clients/jedis/2.0.0/jedis-2.0.0.pom
[SUCCESSFUL ] redis.clients#jedis;2.0.0!jedis.pom(pom.original) (1184ms)
...
After it's in the local cache, the script works fine with @Grab.
I have not manually added a ~/.groovy/grapeConfig.xml file so it's using the default one that comes with groovy. I'm using groovy 1.8:
groovy -v
Groovy Version: 1.8.0 JVM: 1.6.0_24
I tried adding this manually above the grab:
@GrabResolver(name='ibiblio', m2Compatible='true', root='http://repo1.maven.org/maven2/')
but that didn't help. Am I missing something?
Source: (StackOverflow)
I have a small prototype subclass of Grape::API
as a rack service, and am using Grape::Entity
to present my application's internal objects.
I like the Grape::Entity
DSL, but am having trouble finding out how I should go beyond the default JSON representation, which is too lightweight for our purposes. I have been asked to produce output in "jsend or similar" format: http://labs.omniti.com/labs/jsend
I am not at all sure what nature of change is most in keeping with the Grape framework (I'd like a path-of-least-resistance here). Should I create a custom Grape formatter (I have no idea how to do this), new rack middleware (I have done this in order to log API ins/outs via SysLog - but formatting seems bad as I'd need to parse the body back from JSON to add container level), or change away from Grape::Entity
to e.g. RABL?
Example code ("app.rb")
require "grape"
require "grape-entity"
class Thing
def initialize llama_name
@llama_name = llama_name
end
attr_reader :llama_name
end
class ThingPresenter < Grape::Entity
expose :llama_name
end
class MainService < Grape::API
prefix 'api'
version 'v2'
format :json
rescue_from :all
resource :thing do
get do
thing = Thing.new 'Henry'
present thing, :with => ThingPresenter
end
end
end
Rackup file ("config.ru")
require File.join(File.dirname(__FILE__), "app")
run MainService
I start it up:
rackup -p 8090
And call it:
curl http://127.0.0.1:8090/api/v2/thing
{"llama_name":"Henry"}
What I'd like to see:
curl http://127.0.0.1:8090/api/v2/thing
{"status":"success","data":{"llama_name":"Henry"}}
Obviously I could just do something like
resource :thing do
get do
thing = Thing.new 'Henry'
{ :status => "success", :data => present( thing, :with => ThingPresenter ) }
end
end
in every route - but that doesn't seem very DRY. I'm looking for something cleaner, and less open to cut&paste errors when this API becomes larger and maintained by the whole team
Weirdly, when I tried { :status => "success", :data => present( thing, :with => ThingPresenter ) }
using grape 0.3.2
, I could not get it to work. The API returned just the value from present
- there is more going on here than I initially thought.
Source: (StackOverflow)