grape入門

1.Grape是運行在rack或與rails/sinatra配合使用的一種restful風格的ruby微框架,經過提供簡單的DSL(領域特定語言)簡化APIs開發.它內置支持mutiple formats(),subdomain/prefix restriction, versioning等通用約束(ruby約束高於配置).詳見http://intridea.github.io/grape/.git

2.安裝Grapegithub

gem install grape

或者編輯Gemfile.json

gem "grape"

而後api

bundle install

 

3.基礎用法ruby

Grape APIs和Rack應用繼承自Grape::API.restful

下面展現一段用Grape寫的簡單的twitter API:app

module Twitter
  class API < Grape::API
    version 'v1', using: :header, vendor: 'twitter'
    format :json 
    prefix :api

    helpers do
      def current_user
        @current_user ||= User.authorize!(env)
      end

      def authenticate!
        error!('401 Unauthorized', 401) unless current_user
      end
    end

    resource :statuses do
      desc "Return a public timeline."
      get :public_timeline do
        Status.limit(20)
      end

      desc "Return a personal timeline."
      get :home_timeline do
        authenticate!
        current_user.statuses.limit(20)
      end

      desc "Return a status."
      params do
        requires :id, type: Integer, desc: "Status id."
      end
      route_param :id do
        get do
          Status.find(params[:id])
        end
      end

      desc "Create a status."
      params do
        requires :status, type: String, desc: "Your status."
      end
      post do
        authenticate!
        Status.create!({
          user: current_user,
          text: params[:status]
        })
      end

      desc "Update a status."
      params do
        requires :id, type: String, desc: "Status ID."
        requires :status, type: String, desc: "Your status."
      end
      put ':id' do
        authenticate!
        current_user.statuses.find(params[:id]).update({
          user: current_user,
          text: params[:status]
        })
      end

      desc "Delete a status."
      params do
        requires :id, type: String, desc: "Status ID."
      end
      delete ':id' do
        authenticate!
        current_user.statuses.find(params[:id]).destroy
      end
    end
  end
end

關於上面代碼的簡單解釋:框架

將API文件放在/app/api文件下,而且修改/config/application.rb文件:less

config.paths.add "app/api", glob: "**/*.rb"
config.autoload_paths += Dir["#{Rails.root}/app/api/*"]

而且修改路由文件/config/routes.rb:dom

mount   Twitter::API  => '/'

 

3.調用API

使用mount方法:

class Twitter::API < Grape::API
  mount Twitter::APIv1
  mount Twitter::APIv2
end
class Twitter::API < Grape::API
  mount Twitter::APIv1 => '/v1'
end

4.爲API添加描述

desc "Returns your public timeline." do
  detail 'more details'
  params  API::Entities::Status.documentation
  success API::Entities::Entity
  failure [[401, 'Unauthorized', "Entities::Error"]]
  named 'My named route'
  headers [XAuthToken: {
             description: 'Valdates your identity',
             required: true
           },
           XOptionalHeader: {
             description: 'Not really needed',
            required: false
           }
          ]
end
get :public_timeline do
  Status.limit(20)
end

details:更加詳細的描述

params:直接從實體定義參數

success:實體對象的默認使用路由

failure:請求失敗返回的http代碼

(====續=====)

參數認證和約束

(1).在block中定義設置參數的約束項:

params do
  requires :id, type: Integer  
  optional :text, type: String, regexp: /^[a-z]+$/  #text全是小寫字母
  group :media do #參數嵌套;與[:id]協同
    requires :url
  end
end
put ':id' do
  # params[:id] is an Integer
end

(2).命名空間認證和約束

容許定義參數以及在命名空間內部使用各類方法,命名空間就是一個sandbox,叫作module;採用這種模塊化機制能夠有效限定做用域;

namespace :statuses do
  params do
    requires :user_id, type: Integer, desc: "A user ID."
  end
  namespace ":user_id" do
    desc "Retrieve a user's status."
    params do
      requires :status_id, type: Integer, desc: "A status ID."
    end
    get ":status_id" do
      User.find(params[:user_id]).statuses.find(params[:status_id]) #經過 :user_id獲取:status_id;
    end
  end
end

(3)用戶認證

class AlphaNumeric < Grape::Validations::Validator
  def validate_param!(attr_name, params)
    unless params[attr_name] =~ /^[[:alnum:]]+$/  #[:alnum]  posix字符類字母數字類
      throw :error, status: 400, message: "#{attr_name}: must consist of alpha-numeric characters"
    end
  end
end
params do
  requires :text, alpha_numeric: true  #也可這樣約束類型
end
class Length < Grape::Validations::SingleOptionValidator
  def validate_param!(attr_name, params)
    unless params[attr_name].length <= @option
      throw :error, status: 400, message: "#{attr_name}: must be at the most #{@option} characters long"
    end
  end
end
params do
  requires :text, length: 140
end

請求頭

get do
  error!('Unauthorized', 401) unless headers['Secret-Password'] == 'swordfish'
end

get do
  error!('Unauthorized', 401) unless env['HTTP_SECRET_PASSWORD'] == 'swordfish'
end
header "X-Robots-Tag", "noindex"

路由

 

get ':id', requirements: { id: /[0-9]*/ } do  #Regexp 條件過濾
  Status.find(params[:id])
end

namespace :outer, requirements: { id: /[0-9]*/ } do
  get :id do
  end

  get ":id/edit" do
  end
end
module StatusHelpers
  def user_info(user)
    "#{user} has statused #{user.statuses} status(s)"
  end
end

class API < Grape::API
  # define helpers with a block
  helpers do
    def current_user
      User.find(params[:user_id])
    end
  end

  # or mix in a module
  helpers StatusHelpers

  get 'info' do
    # helpers available in your endpoint and filters
    user_info(current_user)
  end
end
相關文章
相關標籤/搜索