Настройка отношения rom-http для REST CRUD - PullRequest
1 голос
/ 16 мая 2019

Я пытаюсь установить отношение rom-http для базового REST CRUD, но нахожу документацию довольно скудной для новичка и слишком сложной при копании. Пока я пробовал это:

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. : -)

1 Ответ

1 голос
/ 09 июля 2019

Извините, что никто еще не ответил на этот вопрос, текущий встроенный обработчик 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>

Кроме того, для вложенных ресурсов ПЗУ может запрашивать их автоматически, проверьте приведенные ниже (устаревшие) примеры разделов, чтобы увидеть, как это работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...