Objective: Use grape Shared Params from a helper module, without having to add the syntax helpers Helper::Module on every mounted API.
Example code that works:
# /app/api/v1/helpers.rb
module V1
module Helpers
extend Grape::API::Helpers
params :requires_authentication_params do
requires :user_email, type: String
requires :authentication_token, type: String
end
end
end
# /app/api/api.rb
class API < Grape::API
format :json
version 'v1', using: :path
mount V1::A
mount V1::B
end
# /app/api/v1/a.rb
module V1
class A < Grape::API
helpers V1::Helpers
desc 'SampleA'
params do
use :requires_authentication_params
end
get 'sample_a/url' do
#...
end
end
end
# /app/api/v1/B.rb
module V1
class B < Grape::API
helpers V1::Helpers
desc 'SampleB'
params do
use :requires_authentication_params
end
get 'sample_b/url' do
#...
end
end
end
The problem arise when I try to move the helpers V1::Helpers call from A and B to the API class that mounts them, throwing the exception:
block (2 levels) in use': Params :requires_authentication_params not found! (RuntimeError)
As an interesting note, the module does get included, because if I add any instance method to the class V1::Helpers I can use them inside A and B.
So the question, What would be the best solution to DRY this and follow best practices?
What if you include V1::Helpers on API and then make A and B inherit from API? E.g:
# /app/api/api.rb
class API < Grape::API
include V1::Helpers
format :json
version 'v1', using: :path
mount V1::A
mount V1::B
end
class A < API
# ...
end
class B < API
# ...
end
Related
I'm using Rails 6 with Grape as API. I'm pretty new in Grape and I'm trying to learn how to add new endpoint using Grape. The idea is to get Index endpoint which is nested in v1/users/index
Here is my structure:
app/
controllers/
api/
root.rb - API::Root
v1/
base.rb - API::V1::Base
users/
base.rb - API::V1::Users::Base
index.rb - API::V1::Users::Index
api/root.rb
module API
class Root < Grape::API
default_format :json
prefix :api
# exception handling
include Rescuers
# helpers
helpers ::API::Helpers::ParamsHelper
# core API modules
mount V1::Base
end
end
api/v1/base.rb:
module API
module V1
class Base < Root
version 'v1', using: :path
content_type :json, 'application/vnd.api+json'
# mount resource modules
mount V1::Users::Base
end
end
end
api/v1/users/base.rb:
module API
module V1
module Users
class Base < Grape::API
version 'v1', using: :path
content_type :json, 'application/vnd.api+json'
# mount resource modules
mount Users::Index
end
end
end
end
api/v1/users/index.rb:
module API
module V1
module Users
class Index < Grape::API
desc 'Test'
get do
head 200
end
end
end
end
end
Here are my routes:
Rails.application.routes.draw do
# API
scope :api do
mount API::Root, at: '/'
end
end
I want to have this index.rb in my routes as GET v1/users/index but when I type rake routes I don't see it. This should not do anything, I want to understand what is the core requirements when it comes to creation endpoint with Grape.
I'm using grape for restful service. As I know, :resource will define a path in url. For example:
module Sample
module V1
module Order
class GetCheckInListApi < ApplicationApi
resource :check_in_list do
get root: :data do
# business code here
end
end
end
end
end
end
The url for example, will be: localhost:8000/api/v1/check_in_list. I want the url should be: localhost:8000/api/v1/check_in/list. How can I do in Grape ?
Thanks
Does the resource has to be a :check_in_list? You could change it to :chect_in and add a /list route:
class GetCheckInListApi < ApplicationApi
resource :check_in do
get '/list' do
# business code here
end
end
end
I am using grape redtful-api. I am Unable to inherit common_params in Grape. I defined common
_params in class API1 and called it in API2 throws the error. How can I change the code to make this work?
module Example
class API1 < Grape::API
version 'v1'
format :json
prefix :api
resource :exc1 do
common_params = proc do
requires :param1
requires :param2
end
params(&common_params)
get :params_by_pair do
p1 = params[:param1]
p2 = params[:param2]
response = "https://www.example1.com/#{p1}_#{p2}"
end
end
end
end
module Example
class API2 < API1
version 'v1', using: :header, vendor: 'twitter'
format :json
prefix :api
resource :exc2 do
params(&common_params)
get :params_by_pair do
p1 = params[:param1]
p2 = params[:param2]
response = "https://www.example2.com/#{p1}_#{p2}"
end
end
end
end
The issue doesn't have much to do with Grape but rather the way variables' scope works in Ruby. common_params is just a local, it won't survive the end of the scope. You could make it work by using a class instance variable or similar but let's not go there. The way you're supposed to share helpers across different grapes is through a dedicated module.
module Example
module SharedHelpers
extend Grape::API::Helpers
params :common_params do
requires :param1
requires :param2
end
end
end
And now in the different grapes you need to "include" the module and use the helper.
module Example
class API1 < Grape::API
helpers SharedHelpers # !!!
version 'v1'
format :json
prefix :api
resource :exc1 do
params do
use :common_params # !!!
end
get :params_by_pair do
...
end
end
end
end
To use the helpers in the API2 grape, use the same technique.
I'm using grape gem; ref https://github.com/intridea/grape.
Could you show me how to build named path like "twitter_api_v1_statuses_path" ?
My code is as follows
module Twitter
class API < Grape::API
version 'v1', using: :header, vendor: 'twitter'
format :json
prefix :api
resource :statuses do
desc "Return a public timeline."
get :public_timeline do
Status.limit(20)
end
end
end
I'm assuming that you want an URL like this http://yourdomain.com/api/v1/statuses/public_timeline. In this scenario, you have only one problem in your API class and it's related to the versioning strategy you've chosen. The :header strategy search for the API version in a specific header and that's not what you're looking for. Change it to :path.
module Twitter
class API < Grape::API
version 'v1', using: :path, vendor: 'twitter'
format :json
prefix :api
resource :statuses do
desc "Return a public timeline."
get :public_timeline do
Status.limit(20)
end
end
end
end
I'm trying to implement api versioning, almost the same as I've done here . but i don't seem to get module/folder structure right in rails app, because I get error messages like V1 is not a module /app/api/v1/xml_responses/device.rb:3:in '<module:API>'
Directory structure
/app
/api
- api.rb
/v1
-base.rb
/xml_responces
- device.rb
api.rb
require 'v1/base.rb'
module API
class Base < Grape::API
mount API::V1 => '/v1/'
end
end
v1/base.rb
module API
module V1
class ApiV1 < Grape::API
require 'builder'
helpers DeviceMethods
prefix 'api'
version 'v1', using: :header
end
end
end
V1/xml_responses/device.rb
module API
module V1
module XMLResponses::Device
def self.do_something
#do_something
end
end
end
end
Routes.rb
mount API::Base => '/'
I can't figure out what i'm doing wrong! could you please help me?
I was having similar problems, but then stumbled on this great post that helped me get things to work, and had more complete information than I found elsewhere. See http://funonrails.com/2014/03/building-restful-api-using-grape-in-rails/
Looking at your code, this looks funny:
module XMLResponses::Device
def self.do_something
Do you mean to do something like this?
module API
module V1
module XMLResponses
class Device < Grape::API
resource :device do
get do { Device.all } # Or whatever
end
end
end
end
end
Make sure that you have this line in application.rb
config.paths.add "app/api", glob: "**/*.rb"
config.autoload_paths += Dir["#{Rails.root}/app/api/*"]
As suggested at grape wiki here.