Skip to content

Instantly share code, notes, and snippets.

@dsisnero
Forked from AMHOL/rom-http-repo-aggregate.rb
Created March 15, 2017 20:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dsisnero/6b7be9b795b86ac347eaed0d5592dd2a to your computer and use it in GitHub Desktop.
Save dsisnero/6b7be9b795b86ac347eaed0d5592dd2a to your computer and use it in GitHub Desktop.
require 'bundler/inline'
require 'json'
require 'uri'
require 'net/http'
gemfile(true) do
gem 'inflecto'
gem 'rom', github: 'rom-rb/rom'
gem 'rom-support', github: 'rom-rb/rom-support'
gem 'rom-http', github: 'rom-rb/rom-http'
gem 'rom-repository', github: 'rom-rb/rom-repository'
end
class RequestHandler
def call(dataset)
uri = URI(dataset.uri)
uri.path = dataset.absolute_path
uri.query = URI.encode_www_form(dataset.params)
http = Net::HTTP.new(uri.host, uri.port)
request_klass = Net::HTTP.const_get(Inflecto.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
end
class ResponseHandler
def call(response, dataset)
Array([JSON.parse(response.body, symbolize_names: true)]).flatten
end
end
class Users < ROM::Relation[:http]
schema(:users) do
attribute :id, ROM::Types::Int.meta(primary_key: true)
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
def by_id(id)
with_path(id.to_s)
end
end
class Posts < ROM::Relation[:http]
schema(:posts) do
attribute :id, ROM::Types::Int.meta(primary_key: true)
attribute :userId, ROM::Types::Int.meta(alias: :user_id)
attribute :title, ROM::Types::String
attribute :body, ROM::Types::String
end
def by_id(id)
with_path(id.to_s)
end
def for_user(user)
with_options(
base_path: 'users',
path: "#{user.first[:id]}/posts"
)
end
end
class UserRepository < ROM::Repository[:users]
relations :posts
def find(id)
users.by_id(id).first
end
def find_with_posts(user_id)
users.by_id(user_id).combine_children(many: posts.for_user).first
end
end
configuration = ROM::Configuration.new(:http, {
uri: 'http://jsonplaceholder.typicode.com',
headers: {
Accept: 'application/json'
},
request_handler: RequestHandler.new,
response_handler: ResponseHandler.new
})
configuration.register_relation(Users)
configuration.register_relation(Posts)
container = ROM.container(configuration)
UserRepository.new(container).find_with_posts(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment