Grape API:以编程方式创建端点

时间:2017-11-17 16:55:34

标签: ruby-on-rails grape-api

我有非常基本的CRUD端点,这些端点在我的资源中反复重复。

目前我有一个Rails生成器,可以帮助我更快地生成我的API端点。

明显的缺点是每当我对模板进行更改时,我都需要更新一堆文件。

由于我的某些端点有一个非常清晰的模式,我想知道是否有办法动态生成它们。

类似于调用desc,params等方法...:

def delete(target)
  klass = target.camelize.constantize
  entity = V1::Entities.const_defined?(target.camelize) ? V1::Entities.get_const(target.camelize) : nil
  desc "Delete a #{target}", {
   http_codes: [
    { code: 204, message: "#{target} deleted successfully", model: entity},
    { code: 401, message: 'Unauthorized', model: Entities::ApiError },
    { code: 403, message: 'Forbidden', model: Entities::ApiError },
    { code: 404, message: 'Not Found', model: Entities::ApiError },
   ]
  }
  params do
   requires :id, type: Integer, documentation: entity.documentation[:id]
  end
  route_param :id do
   delete do 
    resource = klass.find_by(id: params[:id])
    must_have_record!(resource)
    authenticate! and authorize!("#{target.upcase}_DELETE".to_sym, resource)
    if resource.destroy
     present resource, with: entity
    else 
     destroy_error!
    end
   end
  end
 end

我知道上面的内容不起作用,没有意义。这只是一个例子来说明我的想法。

1 个答案:

答案 0 :(得分:0)

我能够以编程方式创建一个端点,方法是将以下静态方法添加到我的Base<葡萄:API。重要的是不要使用已经存在的Grape :: API类调用静态方法(例如get,post,delete,patch,put,...):

#######################################################################################
### AUTOMAGICALLY GENERATES AN API TO DESTROY A RESOURCE
#######################################################################################
def self.destroy(model)
  model_entity = model.const_defined?("Entity") ? model::Entity : nil
  resource model.to_s.underscore.pluralize do
    desc "Delete a #{model.to_s.downcase}", {
      http_codes: [
        { code: 204, message: "#{model.to_s.downcase} deleted successfully", model: model_entity },
        { code: 401, message: "Unauthorized", model: Entities::ApiError  },
        { code: 403, message: "Forbidden", model: Entities::ApiError },
        { code: 404, message: "Not Found", model: Entities::ApiError },
      ]
    }
    params do
      requires :id, type: Integer, documentation: model_entity && model_entity.documentation[:id] ? model_entity.documentation[:id] : { type: "Integer",  desc: "" }
    end
    route_param :id do
      delete do 
        resource = model.find_by(id: params[:id])
        must_have_record!(resource)
        authenticate! and authorize!(:"#{model.to_s.upcase}_DELETE", resource)
        if resource.destroy
          present resource, with: model_entity
        else 
          destroy_error!
        end
      end
    end
  end
end