Grape 如何設定共用的 headers?


#1

各位鐵路男孩女孩大家好。
最近在使用 Rails + Grape,碰到一個情境:


  desc "測試" do
      headers token: {
          description: '憑證',
          required: false
        }
       ### 這個 header 宣告幾乎每個 action 都需要用到
       ### 總不能每個 action 的 params 前面都宣告一次吧?
       ### 我想一定有方式可以抽出來,但是找了一堆資料都沒有看到範例
       ### 其實還想要有的 action 可以複寫這個 header 需求
       ### 因為並不是每個 action 的 token 都是 required false
    end

    params do
        optional :hello, type: String
    end
    get do
      result
    end

那個 header 在 desc 之下,我也覺得怪怪的,沒找到更好看的寫法。
對了,補充一下,這種宣告我是得跨 resource 的,所以可能得抽到更上層去放?

https://github.com/ruby-grape/grape#header <= 這個 header 好像也不是我需要的那種
https://github.com/ruby-grape/grape#headers
http://stackoverflow.com/questions/40088637/how-to-handle-before-filter-for-specific-action-in-grape
https://github.com/ruby-grape/grape/issues/1371


#3

高級貨,用 Proc builder 即可 … 這是我曾經使用過類似的 code 就是,問題和你一樣,重複定義很蠢之類的

def self.make_proc(desc)
  return eval(%Q%Proc.new do
    headers token: {
      description: '#{desc}',
      required: false
    }
  end%)
end

#使用1

desc "測試" , &make_proc('yoooo')

#使用2
@@yooo = make_proc('yoooo')
desc "測試" , &@@yooo

#不高興你可以寫個全包的,類似

def self.build_desc(title , desc)
  proc = eval(%Q%Proc.new do
    headers token: {
      description: '#{desc}',
      required: false
    }
  end%)
  desc title , &proc
end

#使用

build_desc('測試' , 'yooo') #取代掉原本的 desc

這是動態語言的基本招式之一的 metaprogramming,Ruby 用起來特別順而已 X"D,在 Ruby 中所有的 do … end 或是簡寫 {…} 其實都是 Proc,所以自己做一個 builder ,產出後用 & 餵進去,部分詳情可見

注意一下安全,防止動態產生(塞入值都必須過濾過或是信任且靜態的),還有測試一下改 lambda 有時候會好點(以 return 的中斷點而言),不過這邊要測試過就是,以上


#4

Metaprogramming 呀!

強者公司老大是指點了這個 gem:


不過這個跨 resource 不知道是否有問題。
我本來以為 Grape 有 best practice,只是我沒有找到文件,看起來是沒有呀 … 有點難過。

不知道能否用 namespace 來繞開:


題外話,Swagger UI gem 好像無法正確處理 Array params,例如:

optional :guys, type: Array do 
  optional :name, type: String
  optional :email, type: String
end

#5

我套 before 看看 …

desc:


#6

我沒有用 Swagger UI 的 gem 哩,前端大概都手刻就是,Array 應該有,不過你要給正確的 entity
倒是你想讓 doc 呈現正確的話…可以整個複寫掉啦 X"DD


#7

感謝!

我再上 Grape Entity 試試看。


#8

我最後是改成這樣子做:

app/api/api.rb

def my_headers
  {
    key1: {
      description: 'hello',
      required: true
    },
    key2: {
      description: 'hello',
      required: false
    }
  }
end

# define my_headers outside of API class

class API < Grape::API
  version 'v1', using: :param, parameter: 'v', vendor: 'Larvata'
  content_type :json, 'application/json'

  # some codes ...

app/api/home.rb

class Home < API

 resources :home do

    desc "Home Page", { headers: my_headers }
    get do
      # some codes ...

jz_headers 如果放在 Helpers 裡面,在 desc 一直讀不到 …


#9

O~ 當然,因為 helper 是在後面區段用的(action 段,類似 get / post …),但前面定義區段應該是外層的 code 才是,所以你要把 builder 都寫在外部才行