Rails: how to make url with multi slash in Grape - ruby-on-rails

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

Related

Unable to autoload constant API Controller in Rails 4 model in module

I'm trying to create an api controller for a model defined in a module
Model class:
module Reports
class Report < ActiveRecord::Base
end
end
Api controller:
class API::V2::ReportsController < API::V2::BaseController
end
Route:
namespace :api, defaults: { format: :json } do
namespace :v2 do
resources :reports
end
end
The error I get when try to call api/v2/reports is:
LoadError (Unable to autoload constant Report, expected /.../app/models/reports/report.rb to define it):
Is there a way to solve this, making the api controller look for Reports::Report instead of Report?
Your controller needs to include Reports somehow:
module Api
module V2
module Reports
class Report < API::V2::BaseController
your controller actions
end
end
end
end
Apart from that, I think it will be confusing if you use Reports::Report?

Grape: dynamic prefix?

I have api set up like this:
class Dashboard < Api
def self.inherited(subclass)
super
subclass.instance_eval do
prefix 'dashboard'
#...
end
end
def self.company_id(path)
':company_id' + path
end
helpers do
def current_company
#current_company ||= Company.find(params[:company_id]) if params[:company_id]
end
end
end
Problem: I inherit class Employee from Dashboard, and what I want to achieve: resource, which inherits from Dashboard, should be accessed by it's namespace '/dashboard/companies/:company_id/employees', with current_company working correct.
I feel tiring each time to provide full route instead of namespace convenience:
get 'companies/:company_id/employees'
#...
end
But this won't give result needed:
namespace :companies do
namespace :employees do
...
end
end
From what I undertand, you're looking for dynamic namespace, isn't it? You can define dynamic namespaces using a string instead of just a symbol. In the given string, each :something part indicates a parameter, same thing as what you may be used to in Rails or Sinatra routes syntax. In the endpoints, you'll then be able to access params[:something] as you usually do.
For instance, in your case, you might use something like this :
namespace 'companies/:company_id' do
namespace :employees do
get do
# Will respond with the available params (containing :company_id)
body params
end
end
end

Inheritance is not working in grape

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.

Rails Grape, DRY Helpers call for shared params

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

Rails Grape api versioning module structure

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.

Resources