-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathresource_proxy.rb
More file actions
122 lines (104 loc) · 3.53 KB
/
resource_proxy.rb
File metadata and controls
122 lines (104 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#---
# Excerpted from "Metaprogramming Ruby 2",
# published by The Pragmatic Bookshelf.
# Copyrights apply to this code. It may not be used to create training material,
# courses, books, articles, and the like. Contact us if you are in doubt.
# We make no guarantees that this code is fit for any purpose.
# Visit http://www.pragmaticprogrammer.com/titles/ppmetr2 for more book information.
#---
class Ghee
# ResourceProxy lets us create a virtual
# proxy for any API resource, utilizing
# method_missing to handle passing
# messages to the real object
#
class ResourceProxy
# Undefine methods that might get in the way
instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval|instance_variable_get|object_id|respond_to/ }
include Ghee::CUD
# Make connection and path_prefix readable
attr_reader :connection, :path_prefix, :params
# Expose pagination data
attr_reader :current_page, :total, :pagination
# Instantiates proxy with the connection
# and path_prefix
#
# connection - Ghee::Connection object
# path_prefix - String
#
def initialize(connection, path_prefix, params = {})
params = {} if !params.is_a?Hash
@connection, @path_prefix, @params = connection, URI.escape(path_prefix), params
end
# Method_missing takes any message passed
# to the ResourceProxy and sends it to the
# real object
#
# message - Message object
# args* - Arguements passed
#
# ...
def method_missing(message, *args, &block)
subject.send(message, *args, &block)
end
# Subject is the response body parsed
# as json
#
# Returns json
#
def subject
@subject ||= connection.get(path_prefix){|req| req.params.merge!params }.body
end
# Paginate is a helper method to handle
# request pagination to the github api
#
# options - Hash containing pagination params
# eg;
# :per_page => 100, :page => 1
#
# Returns self
#
def paginate(options)
@current_page = options.fetch(:page) {raise ArgumentError, ":page parameter required"}
per_page = options.delete(:per_page) || 30
response = connection.get do |req|
req.url path_prefix, :per_page => per_page, :page => current_page
req.params.merge! params
end
if @subject.nil?
@subject = response.body
else
@subject = @subject.concat response.body
end
parse_link_header response.headers.delete("link")
return self
end
def all
return self if pagination && next_page.nil?
self.paginate :per_page => 100, :page => next_page || 1
self.all
end
# Generate first_page, last_page, next_page, prev_page convienence methods
%w{ next prev first last }.each do |term|
define_method "#{term}_page" do
pagination ? pagination[term.to_sym] ? pagination[term.to_sym][:page] : nil : nil
end
end
private
def parse_link_header(header)
return @total = subject.size, @pagination = {} if header.nil?
require 'cgi'
pattern = /<(.*)>;\s+rel="(.*)"/
matches = {}
header.split(',').each do |m|
match = pattern.match m
uri = URI.parse(match[1])
uri_params = CGI.parse(uri.query)
page = uri_params["page"].first.to_i
per_page = uri_params["per_page"] ? uri_params["per_page"].first.to_i : 30
matches[match[2].to_sym] = {:link => match[1], :page => page, :per_page => per_page}
end
@pagination = matches
end
end
end