瞎扯淡 设计一个足够自动生成 RESTful 接口的 Model

vincenting · 2015年11月15日 · 最后由 jasl 回复于 2015年11月16日 · 3334 次阅读

最近在整理一些 rest 设计的文档,参考了以下文档:

  1. Postgreset - Routing
  2. Design Beautiful REST + JSON APIs
  3. Best Practices for Designing a Pragmatic RESTful API

然后抱着造轮子的态度,前段时间实现了一个类似 postgreset 的简易版原型,最近准备在 Sequel 的 Model 基础上进行拓展,目前得到了如下的一个使用 demo:

models/salesman.rb

class Salesman < Sequel::Model(:crm_resources_salesmen)
  include Restfy::Model

 # sequel 中的定义 model 关系的方法
  one_to_many :logs
  one_to_many :tasks
  one_to_many :houses
  one_to_many :contacts
 # 拓展 created_at 和 updated_at
  use_timestamp :createdTimestamp, :updatedTimestamp

 # JSON 字段支持,方便部分非重要字段拓展而不需要每次都修改数据库
  dynamic_fields :details do
    field :sex, type: 'string', required: true, default: 'unknown',
      enums: %w(male female unknown)

    validate_for_sex do |sex|

    end
  end

  # 每个字段的验证,这里考虑引入 helper 机制
  validate_for_name do |name|
    raise Error.new if !name || name.empty?
  end

end

resources/salesman.rb

resource Salesman do
  # 允许哪些操作,包括 单个查询 :get 单个更新 :update 条件查询 :query 创建 :create 批量更新 :patch
  allow_method :update, :get, :query, :create
 # 每个或者多个操作允许哪些字段操作、不允许哪些, 默认 create 是不允许操作 :id 字段的
  exclude_fields_for [:get, :query], :tenantId
  exclude_fields_for_update :tenantId, :groupId
  include_fields_for_create :id

  # 对应的请求操作的权限验证,数据库中的字段满足的条件
  authenticate_for(:update, :create) do |req|
    where(id: req.current_salesman_id)
  end

  authenticate_for(:query, :get) do |req|
    where(tenantId: req.current_tenant_id)
  end

  # 创建时从请求中默认写入哪些数据
  do_before_create(req) do
    self[:tenantId] = req.current_tenant_id
  end
end

目前还在闷头 coding = =。。。为什么不直接用 postgrest:

  1. Route 不支持简单的联表查询,会给客户端造成过多的请求负担;
  2. Haskell 开发,遇到问题摊手,而且不太易于拓展新的 uri 参数,或者自定义返回格式。

目前想到的就是这么多点,不知道有没有遗漏目前。

updated: 在 @jasl 的建议/提醒下,将表现层的代码单独提取。

Route 不支持简单的联表查询,会给客户端造成过多的请求负担;

这一点 postgrest 建议新建一个 view 来解决

不建议在模型层做表现层的事情

#3 楼 @jasl 好~我去尝试下在 sinatra 里面通过 Delegator 新建一个关键字 resource,来管理资源对应的表现层的东西。

#4 楼 @vincenting 因为 API 上线之后,产品还要迭代,就要考虑 API 外观的稳定性,可能会涉及到做兼容处理,甚至多版本 API 的情况

需要 登录 后方可回复, 如果你还没有账号请 注册新账号