Настройка отношения rom-http для REST CRUD

Я пытаюсь установить отношение 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.:-)

0 ответов

Извините, что никто еще не ответил на это, текущий встроенный обработчик 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 может запрашивать их автоматически, проверьте разделы (устаревшие) примеров ниже, чтобы увидеть, как это работает.

Другие вопросы по тегам