2

我正在尝试为基本的 REST CRUD 设置 rom-http 关系,但我发现文档对于初学者来说非常稀缺,而且在深入研究时有点过于复杂。到目前为止我尝试过的是:

rom = ROM.container(:http, uri: 'http://localhost:8000', handlers: :json) do |conf|
  conf.relation(:users) do
    schema(:users) do
    end
  end
end

这会查询 URI http://localhost:8000/users,但是如何配置前缀、参数和相关资源?

我想要完成的是能够使用我们拥有的 URI,例如http ://localhost:8000/users/1/posts?start=0&size=10

  • 全局前缀 ( api)
  • 版本前缀 ( v1, 可能是全局前缀的一部分)
  • 父资源 ( users/1)
  • 子资源 ( posts)
  • 查询参数(如果可以像这样链接,则可以加分.offset(0).limit(10)

当前的实现是否可以做到这一点?该文档可以使用更深入的示例,而不会强迫新手深入研究架构 - 这无疑是出色的,但对于来自 ActiveRecord 的易用性(和陷阱)的人来说是复杂的。:-)

4

1 回答 1

2

抱歉,还没有人回复这个问题,目前内置的 json 处理程序有点坏,它会手动构建 uri 当它应该从数据集中使用它时,你可以用类似下面的东西来实现你想要的:

注意:我只是调用.dataset.uri来显示将要查询的 URI 示例,因为我没有在本地运行的兼容 API。

注意:除了使用库之外,您可能还想使用自定义适配器。

require 'bundler/inline'

gemfile(true) do
  gem 'rom'
  gem 'rom-http'
end

class MyJSONRequest
  def self.call(dataset)
    uri = dataset.uri
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true if uri.scheme.eql?('https')

    request_class = Net::HTTP.const_get(ROM::Inflector.classify(dataset.request_method))

    request = request_class.new(uri.request_uri)

    dataset.headers.each_with_object(request) do |(header, value), request|
      request[header.to_s] = value
    end

    http.request(request)
  end
end

class MyJSONResponse
  # Handle JSON responses
  #
  # @param [Net::HTTP::Response] response
  # @param [Dataset] dataset
  #
  # @return [Array<Hash>]
  #
  # @api public
  def self.call(response, dataset)
    Array([JSON.parse(response.body, symbolize_names: true)]).flatten(1)
  end
end

ROM::HTTP::Handlers.register(
  :my_json,
  request: MyJSONRequest,
  response: MyJSONResponse
)

rom = ROM.container(:http, uri: 'http://localhost:8000/api', handlers: :my_json) do |conf|
  conf.relation(:users) do
    schema('v1/users') do
      attribute :id, ROM::Types::Integer.meta(
        primary_key: true
      )
      attribute :name, ROM::Types::String
    end

    def by_id(id)
      append_path(id)
    end

    def offset(offset)
      add_params(start: offset)
    end

    def limit(limit)
      add_params(size: limit)
    end
  end

  conf.relation(:posts) do
    schema('v1/posts') do
      attribute :id, ROM::Types::Integer.meta(
        primary_key: true
      )
      attribute :name, ROM::Types::String
    end

    def by_user(user_id)
      with_options(
        base_path: 'v1/users',
        path: "#{user_id}/posts"
      )
    end
  end
end

users = rom.relations[:users]
posts = rom.relations[:posts]

users.offset(0).limit(10).dataset.uri
# => #<URI::HTTP http://localhost:8000/api/v1/users?start=0&size=10>

posts.by_user(1).dataset.uri
# => #<URI::HTTP http://localhost:8000/api/v1/users/1/posts>

此外,对于嵌套资源,ROM 可以自动查询这些资源,请查看下面的(过时的)示例部分以了解其工作原理。

于 2019-07-09T03:28:47.740 回答