Skip to content

Instantly share code, notes, and snippets.

@AMHOL
Last active May 16, 2016 13:31
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save AMHOL/f0e38ce140f5b340f7fc to your computer and use it in GitHub Desktop.
Save AMHOL/f0e38ce140f5b340f7fc to your computer and use it in GitHub Desktop.
# gem install rom rom-http rom-repository inflecto
require 'rom'
require 'rom/memory'
require 'rom-http'
require 'rom-repository'
require 'json'
require 'uri'
require 'inflecto'
require 'net/http'
module Transformer
extend Transproc::Registry
import :map_array, from: Transproc::ArrayTransformations
import :hash_recursion, from: Transproc::Recursion
import :map_keys, from: Transproc::HashTransformations
import :underscore, from: Inflecto
import :to_symbol, from: Transproc::Coercions
module_function
def transform_tuples(tuples)
t(:map_array, t(:hash_recursion, t(:map_keys, t(:underscore) >> t(:to_symbol))))[tuples]
end
end
class RequestHandler
def call(dataset)
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), req|
req[header.to_s] = value
end
http.request(request)
end
end
class ResponseHandler
def call(response, dataset)
Transformer[:transform_tuples][
Array([JSON.parse(response.body)]).flatten
]
end
end
class Users < ROM::Relation[:http]
dataset :users
use :view
use :key_inference
def primary_key
:id
end
view(:base, [:id, :name, :username, :email, :address, :phone, :website, :company]) do
self
end
def by_id(id)
with_path(id.to_s)
end
end
class Posts < ROM::Relation[:http]
dataset :posts
use :view
use :key_inference
def primary_key
:id
end
view(:base, [:id, :user_id, :title, :body]) { self }
def by_id(id)
with_path(id.to_s)
end
def for_users(users)
user_ids = users.map { |p| p[:id] }
select { |post| user_ids.include?(post[:user_id]) }
end
end
class Comments < ROM::Relation[:http]
dataset :comments
use :view
use :key_inference
def primary_key
:id
end
view(:base, [:id, :post_id, :name, :email, :body]) { self }
def by_id(id)
with_path(id.to_s)
end
def for_posts(posts)
post_ids = posts.map { |p| p[:id] }
select { |comment| post_ids.include?(comment[:post_id]) }
end
end
rom = ROM::Environment.new
rom.setup(:http, {
uri: 'http://jsonplaceholder.typicode.com',
headers: {
Accept: 'application/json'
},
request_handler: RequestHandler.new,
response_handler: ResponseHandler.new
})
rom.register_relation(Users)
rom.register_relation(Posts)
rom.register_relation(Comments)
class UserRepository < ROM::Repository::Base
relations :users, :posts, :comments
def by_id(id)
users.by_id(id)
end
def with_posts(id)
users.by_id(id).combine_children(many: posts.for_users)
end
def with_posts_and_comments(id)
users.by_id(id).combine_children(many: posts.combine_children(many: comments))
end
end
class PostRepository < ROM::Repository::Base
relations :posts, :comments
def by_id(id)
posts.by_id(id)
end
def with_comments(id)
posts.by_id(id).combine_children(many: comments)
end
end
container = rom.finalize.env
user_repo = UserRepository.new(container)
post_repo = PostRepository.new(container)
# post_repo.with_comments(1).to_a
user_repo.with_posts_and_comments(1).first
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment