Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document creating an adapter more thoroughly #41

Open
thedrow opened this issue Sep 6, 2016 · 6 comments
Open

Document creating an adapter more thoroughly #41

thedrow opened this issue Sep 6, 2016 · 6 comments
Labels

Comments

@thedrow
Copy link

thedrow commented Sep 6, 2016

I have the following adapter code:

require 'rom'
require 'rom-http'

module ROM
  module RestfullClientAdapter
    class Dataset < ROM::HTTP::Dataset
      default_request_handler -> (dataset) do
        puts "begin request"
      end

      default_response_handler -> (response, dataset) do
        puts "end request"
      end

      def response_transformer(response)

      end
    end

    class Gateway < ROM::HTTP::Gateway; end

    class Relation < ROM::HTTP::Relation
      adapter :restfull_client

    end

    module Commands
      class Create < ROM::HTTP::Commands::Create
        adapter :restfull_client
      end

      class Update < ROM::HTTP::Commands::Update
        adapter :restfull_client
      end

      class Delete < ROM::HTTP::Commands::Delete
        adapter :restfull_client
      end
    end
  end
end

ROM.register_adapter(:restfull_client, ROM::RestfullClientAdapter)

and I'm getting to following exception:

KeyError: key not found: :base
/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-2.0.0/lib/rom/plugins/relation/view.rb:35:in `fetch'
/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-2.0.0/lib/rom/plugins/relation/view.rb:35:in `attributes'
/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-repository-0.3.1/lib/rom/repository/relation_proxy.rb:212:in `method_missing'
/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-repository-0.3.1/lib/rom/repository/relation_proxy.rb:132:in `to_ast'
/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-repository-0.3.1/lib/rom/repository.rb:203:in `compile_command'
/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-repository-0.3.1/lib/rom/repository.rb:138:in `block in command'
/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:133:in `block in fetch_or_store'
/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:122:in `fetch'
/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:132:in `fetch_or_store'
/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-repository-0.3.1/lib/rom/repository.rb:137:in `command'
/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-repository-0.3.1/lib/rom/repository/class_interface.rb:116:in `block in define_command_method'
./spec/rom_restful_client_adapter_spec.rb:15:in `block (2 levels) in <top (required)>'
-e:1:in `load'
-e:1:in `<main>'

After digging a bit it seems I need to set the option base to be an instance but I'm not sure of which class.
So I did:

    class Relation < ROM::HTTP::Relation
      adapter :restfull_client

      option :base, self
    end

and now I get:

/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-support-2.0.0/lib/rom/support/options.rb:49:in `initialize': undefined method `fetch' for ROM::RestfullClientAdapter::Relation:Class (NoMethodError)
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-support-2.0.0/lib/rom/support/options.rb:164:in `new'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-support-2.0.0/lib/rom/support/options.rb:164:in `option'
    from /Volumes/fiverr_dev/restfull-client/lib/rom_adapter.rb:25:in `<class:Relation>'
    from /Volumes/fiverr_dev/restfull-client/lib/rom_adapter.rb:22:in `<module:RestfullClientAdapter>'
    from /Volumes/fiverr_dev/restfull-client/lib/rom_adapter.rb:5:in `<module:ROM>'
    from /Volumes/fiverr_dev/restfull-client/lib/rom_adapter.rb:4:in `<top (required)>'
    from /Volumes/fiverr_dev/restfull-client/spec/support/models.rb:2:in `require'
    from /Volumes/fiverr_dev/restfull-client/spec/support/models.rb:2:in `<top (required)>'
    from /Volumes/fiverr_dev/restfull-client/spec/spec_helper.rb:6:in `load'
    from /Volumes/fiverr_dev/restfull-client/spec/spec_helper.rb:6:in `block in <top (required)>'
    from /Volumes/fiverr_dev/restfull-client/spec/spec_helper.rb:6:in `each'
    from /Volumes/fiverr_dev/restfull-client/spec/spec_helper.rb:6:in `<top (required)>'
    from /Users/omer.katz/.rvm/rubies/ruby-2.2.2/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /Users/omer.katz/.rvm/rubies/ruby-2.2.2/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration.rb:1394:in `block in requires='
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration.rb:1394:in `each'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration.rb:1394:in `requires='
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration_options.rb:112:in `block in process_options_into'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration_options.rb:111:in `each'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration_options.rb:111:in `process_options_into'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration_options.rb:21:in `configure'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/runner.rb:99:in `setup'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/runner.rb:86:in `run'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/invocations.rb:23:in `call'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/runner.rb:69:in `run'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/runner.rb:45:in `invoke'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/exe/rspec:4:in `<top (required)>'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/bin/rspec:23:in `load'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/bin/rspec:23:in `<top (required)>'
    from -e:1:in `load'
    from -e:1:in `<main>'

After adding fetch to the Relation class I get:

/Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-2.0.0/lib/rom/relation/class_interface.rb:129:in `rescue in []': Failed to find relation class for coercer adapter. Make sure ROM setup was started and the adapter identifier is correct. (ROM::AdapterNotPresentError)
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-2.0.0/lib/rom/relation/class_interface.rb:127:in `[]'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-support-2.0.0/lib/rom/support/options.rb:51:in `initialize'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-support-2.0.0/lib/rom/support/options.rb:164:in `new'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rom-support-2.0.0/lib/rom/support/options.rb:164:in `option'
    from /Volumes/fiverr_dev/restfull-client/lib/rom_adapter.rb:29:in `<class:Relation>'
    from /Volumes/fiverr_dev/restfull-client/lib/rom_adapter.rb:22:in `<module:RestfullClientAdapter>'
    from /Volumes/fiverr_dev/restfull-client/lib/rom_adapter.rb:5:in `<module:ROM>'
    from /Volumes/fiverr_dev/restfull-client/lib/rom_adapter.rb:4:in `<top (required)>'
    from /Volumes/fiverr_dev/restfull-client/spec/support/models.rb:2:in `require'
    from /Volumes/fiverr_dev/restfull-client/spec/support/models.rb:2:in `<top (required)>'
    from /Volumes/fiverr_dev/restfull-client/spec/spec_helper.rb:6:in `load'
    from /Volumes/fiverr_dev/restfull-client/spec/spec_helper.rb:6:in `block in <top (required)>'
    from /Volumes/fiverr_dev/restfull-client/spec/spec_helper.rb:6:in `each'
    from /Volumes/fiverr_dev/restfull-client/spec/spec_helper.rb:6:in `<top (required)>'
    from /Users/omer.katz/.rvm/rubies/ruby-2.2.2/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /Users/omer.katz/.rvm/rubies/ruby-2.2.2/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration.rb:1394:in `block in requires='
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration.rb:1394:in `each'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration.rb:1394:in `requires='
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration_options.rb:112:in `block in process_options_into'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration_options.rb:111:in `each'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration_options.rb:111:in `process_options_into'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/configuration_options.rb:21:in `configure'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/runner.rb:99:in `setup'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/runner.rb:86:in `run'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/invocations.rb:23:in `call'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/runner.rb:69:in `run'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/lib/rspec/core/runner.rb:45:in `invoke'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/gems/rspec-core-3.5.2/exe/rspec:4:in `<top (required)>'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/bin/rspec:23:in `load'
    from /Users/omer.katz/.rvm/gems/ruby-2.2.2@restfull_client/bin/rspec:23:in `<top (required)>'
    from -e:1:in `load'
    from -e:1:in `<main>'

It's really not clear what I should be doing.
Can you guys please help me and also document the process?

@AMHOL
Copy link
Member

AMHOL commented Sep 6, 2016

Sorry, just looked into this and it seems that the dataset no longer infers register_as, you don't need a base view unless you're using rom-repository, try updating your relation to use register_as:

class Users < ROM::Relation[:my_adapter]
  dataset :users
  register_as :users

  def by_id(id)
    with_path(id.to_s)
  end
end

Full example:

require 'json'
require 'uri'
require 'net/http'

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

module ROM
  module MyAdapter
    class Dataset < ROM::HTTP::Dataset
      default_request_handler ->(dataset) do
        uri = URI(dataset.uri)
        uri.path = "/#{dataset.name}/#{dataset.path}"
        uri.query = URI.encode_www_form(dataset.params)

        http = Net::HTTP.new(uri.host, uri.port)
        request_klass = Net::HTTP.const_get(ROM::Inflector.classify(dataset.request_method))

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

        response = http.request(request)
      end

      default_response_handler ->(response, dataset) do
        Array([JSON.parse(response.body)]).flatten
      end
    end

    class Gateway < ROM::HTTP::Gateway; end

    class Relation < ROM::HTTP::Relation
      adapter :my_adapter
    end

    module Commands
      class Create < ROM::HTTP::Commands::Create
        adapter :my_adapter
      end

      class Update < ROM::HTTP::Commands::Update
        adapter :my_adapter
      end

      class Delete < ROM::HTTP::Commands::Delete
        adapter :my_adapter
      end
    end
  end
end

ROM.register_adapter(:my_adapter, ROM::MyAdapter)

configuration = ROM::Configuration.new(:my_adapter, {
  uri: 'http://jsonplaceholder.typicode.com',
  headers: {
    Accept: 'application/json'
  }
})

class Users < ROM::Relation[:my_adapter]
  dataset :users
  register_as :users

  def by_id(id)
    with_path(id.to_s)
  end
end

configuration.register_relation(Users)
container = ROM.container(configuration)

container.relation(:users).by_id(1).to_a

@thedrow
Copy link
Author

thedrow commented Sep 6, 2016

I am using rom-repository.

@AMHOL
Copy link
Member

AMHOL commented Sep 6, 2016

Here's a working example with rom-repository:

require 'json'
require 'uri'
require 'net/http'

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

module ROM
  module MyAdapter
    class Dataset < ROM::HTTP::Dataset
      default_request_handler ->(dataset) do
        uri = URI(dataset.uri)
        uri.path = "/#{dataset.name}/#{dataset.path}"
        uri.query = URI.encode_www_form(dataset.params)

        http = Net::HTTP.new(uri.host, uri.port)
        request_klass = Net::HTTP.const_get(ROM::Inflector.classify(dataset.request_method))

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

        response = http.request(request)
      end

      default_response_handler ->(response, dataset) do
        Array([JSON.parse(response.body, symbolize_names: true)]).flatten
      end
    end

    class Gateway < ROM::HTTP::Gateway; end

    class Relation < ROM::HTTP::Relation
      adapter :my_adapter
    end

    module Commands
      class Create < ROM::HTTP::Commands::Create
        adapter :my_adapter
      end

      class Update < ROM::HTTP::Commands::Update
        adapter :my_adapter
      end

      class Delete < ROM::HTTP::Commands::Delete
        adapter :my_adapter
      end
    end
  end
end

ROM.register_adapter(:my_adapter, ROM::MyAdapter)

configuration = ROM::Configuration.new(:my_adapter, {
  uri: 'http://jsonplaceholder.typicode.com',
  headers: {
    Accept: 'application/json'
  }
})

class Users < ROM::Relation[:my_adapter]
  dataset :users
  register_as :users

  schema do
    attribute :id, ROM::Types::Int
    attribute :name, ROM::Types::String
    attribute :username, ROM::Types::String
    attribute :email, ROM::Types::String
    attribute :phone, ROM::Types::String
    attribute :website, ROM::Types::String
  end

  view(:base, %i(id name username email phone website)) do
    self
  end

  def by_id(id)
    with_path(id.to_s)
  end
end

configuration.register_relation(Users)
container = ROM.container(configuration)

class UserRepository < ROM::Repository[:users]
  def find(id)
    users.by_id(id).one!
  end
end

user_repo = UserRepository.new(container)
user_repo.find(1)
# => #<ROM::Struct[User] id=1 name="Leanne Graham" username="Bret" email="[email protected]" phone="1-770-736-8031 x56442" website="hildegard.org">

@AMHOL
Copy link
Member

AMHOL commented Jan 28, 2017

Closing due to inactivity

@AMHOL AMHOL closed this as completed Jan 28, 2017
@thedrow
Copy link
Author

thedrow commented Jan 30, 2017

Why are you closing this issue? Has the documentation been updated and extended?

@AMHOL
Copy link
Member

AMHOL commented Feb 3, 2017

Fair point

@AMHOL AMHOL reopened this Feb 3, 2017
@solnic solnic transferred this issue from rom-rb/rom-http Apr 28, 2019
@solnic solnic transferred this issue from rom-rb/rom-rb.org Jan 27, 2020
@solnic solnic added the docsite label Jan 27, 2020
@AMHOL AMHOL changed the title Document creating an adapter more throughoutly Document creating an adapter more thoroughly Oct 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants