pyr 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -2
- data/lib/pyr.rb +61 -56
- data/lib/pyr/geo_findable.rb +78 -0
- data/lib/pyr/parser.rb +0 -1
- data/lib/pyr/resources/office_locations.rb +27 -1
- data/lib/pyr/resources/reps.rb +1 -66
- data/lib/pyr/resources/zctas.rb +2 -2
- data/lib/pyr/response_object.rb +1 -1
- data/lib/pyr/version.rb +2 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05417621a790e6818011d19f83a9307b77e12522
|
4
|
+
data.tar.gz: b1685e7ade99c0fb3f5577892599604c5c3fc590
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0938235b38f8b3c0a02255086e39a244fc63704164b3910bee275234ec945e17ee1cbe1aa8ba981a38ebf76321934f5725dc21ff8b8647f78aef2d6513ec25a3'
|
7
|
+
data.tar.gz: 8b9396fcb11c3bf5d6ef45ec2c2233314d67b333614d92abd7db4485a69df29f6e431da5f1aa6539773323e9170055cdaae941e30fac50fc029dbfac1e43fec9
|
data/README.md
CHANGED
@@ -66,6 +66,8 @@ reps.first.office_locations.first.phone
|
|
66
66
|
### Querying the full index and narrowing with scopes
|
67
67
|
```ruby
|
68
68
|
response = PYR.call :reps
|
69
|
+
# is equivalent to
|
70
|
+
response = PYR.reps
|
69
71
|
|
70
72
|
reps = response.objects
|
71
73
|
|
@@ -96,7 +98,7 @@ bernie = PYR.call(:reps, 'S000033').objects.first
|
|
96
98
|
|
97
99
|
### Querying by Object
|
98
100
|
```ruby
|
99
|
-
office = PYR.
|
101
|
+
office = PYR.reps('S000033').objects.first.office_locations.district.first
|
100
102
|
=> #<PYR::OfficeLocation id: 1, city: "Burlington", rep: "https://phone-your-rep.herokuapp.com/api/beta/reps/S000033", active: true, office_id: "S000033-burlington", bioguide_id: "S000033", office_type: "district", distance: nil, building: "", address: "1 Church St.", suite: "3rd Floor", city: "Burlington", state: "VT", zip: "05401", phone: "802-862-0697", fax: "802-860-6370", hours: "", latitude: 44.4802081, longitude: -73.2130702, v_card_link: "https://phone-your-rep.herokuapp.com/v_cards/S000033-burlington", downloads: 14, qr_code_link: "https://s3.amazonaws.com/phone-your-rep-images/S000033_burlington.png">
|
101
103
|
|
102
104
|
# Pass in the object itself as the param to PYR.call
|
@@ -110,7 +112,7 @@ office.office_id == office.call.objects.first.office_id
|
|
110
112
|
|
111
113
|
### Querying by Phone Your Rep URI
|
112
114
|
```ruby
|
113
|
-
rep = PYR.
|
115
|
+
rep = PYR.reps { |r| r.address = 'vermont' }.objects.representatives.first
|
114
116
|
|
115
117
|
uri = rep.district.self
|
116
118
|
=> "https://phone-your-rep.herokuapp.com/api/beta/districts/5000"
|
data/lib/pyr.rb
CHANGED
@@ -23,6 +23,7 @@
|
|
23
23
|
require 'faraday'
|
24
24
|
require 'faraday_middleware'
|
25
25
|
|
26
|
+
require 'pyr/geo_findable'
|
26
27
|
require 'pyr/param'
|
27
28
|
require 'pyr/parser'
|
28
29
|
require 'pyr/resource'
|
@@ -41,66 +42,15 @@ require 'pyr/response_objects/zcta'
|
|
41
42
|
require 'pyr/request'
|
42
43
|
require 'pyr/version'
|
43
44
|
|
44
|
-
# PYR
|
45
|
-
# converting the data payloads into
|
46
|
-
# There is one class method on the PYR module, ::call.
|
47
|
-
#
|
48
|
-
# The method takes two arguments: :resource and :id. The resource
|
49
|
-
# is the API resource, or controller name, that you want to
|
50
|
-
# query. The name must be in plural form. The options are 'reps',
|
51
|
-
# 'office_locations', 'states', 'districts', and 'zctas' (Zip Code
|
52
|
-
# Tabulation Areas).
|
53
|
-
#
|
54
|
-
# The :id is the primary key id of a particular object. Each
|
55
|
-
# resource has its own data attribute as ID.
|
56
|
-
#
|
57
|
-
# ids = {
|
58
|
-
# reps: :bioguide_id,
|
59
|
-
# office_locations: :office_id,
|
60
|
-
# states: :state_code,
|
61
|
-
# districts: :full_code,
|
62
|
-
# zctas: :zcta
|
63
|
-
# }
|
64
|
-
#
|
65
|
-
# The ::call method takes a block, to which it yields an object
|
66
|
-
# inherited from the PYR::Resource class. You can then pass params to
|
67
|
-
# the PYR::Resource object. The particular descendant of PYR::Resource,
|
68
|
-
# and therefore the available params, depends on the resource/controller
|
69
|
-
# that you are querying.
|
70
|
-
#
|
71
|
-
# The return value of ::call is an instance of the PYR::Response class.
|
72
|
-
# You can call these methods on the object:
|
73
|
-
#
|
74
|
-
# #objects => A collection, similar to an ActiveRecord Relation, of
|
75
|
-
# objects descended from the PYR::ResponseObject superclass,
|
76
|
-
# which have getter methods for each data attribute.
|
77
|
-
# The objects may be nested inside other PYR::ResponseObjects,
|
78
|
-
# e.g. a :rep has_one :state and has_many :office_locations.
|
79
|
-
# The collection can be iterated over, and can be queried
|
80
|
-
# similarly to how you would query in ActiveRecord, using the
|
81
|
-
# #where method, which can take hash syntax for checking equality
|
82
|
-
# of discreet attributes, or block syntax if you need to do
|
83
|
-
# more complex comparisons. Some scopes are also available
|
84
|
-
# depending on the resource, e.g. `reps.democratic.senators`
|
85
|
-
#
|
86
|
-
# #uri => The URI that the request was sent to.
|
87
|
-
#
|
88
|
-
# #body => The raw JSON data response
|
89
|
-
#
|
90
|
-
# #code => The HTTP status code e.g. 200
|
91
|
-
#
|
92
|
-
# #message => The HTTP status message e.g. 'OK'
|
93
|
-
#
|
94
|
-
# #controller => The API controller that was hit e.g. :reps, :zctas etc...
|
95
|
-
#
|
96
|
-
# #headers => A hash containing the HTTP response headers
|
45
|
+
# PYR wraps the Phone Your Rep API in an easy interface,
|
46
|
+
# converting the data payloads into Ruby objects.
|
97
47
|
#
|
98
48
|
# ==== Examples
|
99
49
|
#
|
100
50
|
# response = PYR.call(:reps) { |r| r.address = 'vermont' }
|
101
51
|
#
|
102
52
|
# response.body # => { ... }
|
103
|
-
# response.
|
53
|
+
# response.path # => 'reps?address=vermont'
|
104
54
|
# reps = response.objects
|
105
55
|
# reps.count # => 3
|
106
56
|
# reps.independent.senators.first.official_full # => "Bernard Sanders"
|
@@ -111,6 +61,26 @@ require 'pyr/version'
|
|
111
61
|
# independent_senators = response.objects.independent.senators
|
112
62
|
# vt_fav_son = independent_senators.where { |r| r.state.abbr == 'VT' }.first
|
113
63
|
# vt_fav_son.official_full # => "Bernard Sanders"
|
64
|
+
# vt_fav_son.bioguide_id # => "S000033"
|
65
|
+
#
|
66
|
+
# response = PYR.call :reps, 'S000033'
|
67
|
+
#
|
68
|
+
# response.objects.first.official_full # => "Bernard Sanders"
|
69
|
+
#
|
70
|
+
# PYR.reps('S000033').objects.first.official_full # => "Bernard Sanders"
|
71
|
+
#
|
72
|
+
# Any of the following resources can be passed as the first argument to `PYR.call`,
|
73
|
+
# or called as a class method directly to the PYR module, as in the above example.
|
74
|
+
# Both options yield a resource to the block for setting params.
|
75
|
+
# :reps, :office_locations, :states, :districts, :zctas
|
76
|
+
#
|
77
|
+
# So
|
78
|
+
#
|
79
|
+
# PYR.call(:reps) { |r| r.address = 'vermont' }
|
80
|
+
#
|
81
|
+
# Is equivalent to
|
82
|
+
#
|
83
|
+
# PYR.reps { |r| r.address = 'vermont' }
|
114
84
|
module PYR
|
115
85
|
# The base URI for all requests
|
116
86
|
API_BASE_URI = 'https://phone-your-rep.herokuapp.com/api/beta/'
|
@@ -151,16 +121,51 @@ module PYR
|
|
151
121
|
#
|
152
122
|
# or, perhaps most commonly, a resource name (String or Symbol) with
|
153
123
|
# optional ID(String).
|
154
|
-
def self.call(resource, id = nil)
|
124
|
+
def self.call(resource, id = nil, &config_block)
|
155
125
|
if resource.is_a?(ResponseObject)
|
156
126
|
request_object = { response_object: resource }
|
157
127
|
elsif resource.to_s.include? API_BASE_URI
|
158
128
|
request_object = { uri: resource }
|
159
129
|
else
|
160
130
|
resource = Request.build(resource, id)
|
161
|
-
|
131
|
+
config_block.call resource if block_given?
|
162
132
|
request_object = { resource: resource }
|
163
133
|
end
|
164
134
|
Response.new request_object
|
165
135
|
end
|
136
|
+
|
137
|
+
# Call the :reps resource.
|
138
|
+
#
|
139
|
+
# PYR.reps { |r| r.address = '123 Main St, USA 12345' }
|
140
|
+
def self.reps(id = nil, &config_block)
|
141
|
+
call(:reps, id, &config_block)
|
142
|
+
end
|
143
|
+
|
144
|
+
# Call the :office_locations resource.
|
145
|
+
#
|
146
|
+
# PYR.office_locations { |r| r.address = '123 Main St, USA 12345' }
|
147
|
+
def self.office_locations(id=nil, &config_block)
|
148
|
+
call(:office_locations, id, &config_block)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Call the :zctas resource.
|
152
|
+
#
|
153
|
+
# PYR.zctas('90026') { |r| r.reps = true }
|
154
|
+
def self.zctas(id = nil, &config_block)
|
155
|
+
call(:zctas, id, &config_block)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Call the :states resource.
|
159
|
+
#
|
160
|
+
# PYR.states '50'
|
161
|
+
def self.states(id = nil, &config_block)
|
162
|
+
call(:states, id, &config_block)
|
163
|
+
end
|
164
|
+
|
165
|
+
# Call the :districts resource.
|
166
|
+
#
|
167
|
+
# PYR.districts '5000'
|
168
|
+
def self.districts(id = nil, &config_block)
|
169
|
+
call(:districts, id, &config_block)
|
170
|
+
end
|
166
171
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PYR
|
4
|
+
# Shared params for resources that can be looked up by location.
|
5
|
+
module GeoFindable
|
6
|
+
# Read the lat param
|
7
|
+
attr_reader :lat
|
8
|
+
# Read the long param
|
9
|
+
attr_reader :long
|
10
|
+
# Read the address param
|
11
|
+
attr_reader :address
|
12
|
+
# Read the generate param
|
13
|
+
attr_reader :generate
|
14
|
+
|
15
|
+
# Set the lat param : float
|
16
|
+
# Needs to be accompanied by :long.
|
17
|
+
#
|
18
|
+
# Usage:
|
19
|
+
# PYR.call :reps do |r|
|
20
|
+
# r.lat = 45.0
|
21
|
+
# r.long = -70.0
|
22
|
+
# end
|
23
|
+
# Resulting URI
|
24
|
+
# 'https://phone-your-rep.herokuapp.com/api/beta/reps?lat=45.0&long=-45.0'
|
25
|
+
def lat=(float)
|
26
|
+
@lat = Param.new(:lat, float)
|
27
|
+
params << @lat
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set the long param : float
|
31
|
+
# Needs to be accompanied by :lat.
|
32
|
+
#
|
33
|
+
# Usage:
|
34
|
+
# PYR.call :reps do |r|
|
35
|
+
# r.lat = 45.0
|
36
|
+
# r.long = -70.0
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# Resulting URI
|
40
|
+
# 'https://phone-your-rep.herokuapp.com/api/beta/reps?lat=45.0&long=-45.0'
|
41
|
+
def long=(float)
|
42
|
+
@long = Param.new(:long, float)
|
43
|
+
params << @long
|
44
|
+
end
|
45
|
+
|
46
|
+
# Set the address param : string
|
47
|
+
# :lat and :long take precedence
|
48
|
+
#
|
49
|
+
# Usage:
|
50
|
+
# PYR.call(:reps) { |r| r.address = '123 Main St., USA'}
|
51
|
+
#
|
52
|
+
# Resulting URI:
|
53
|
+
# 'https://phone-your-rep.herokuapp.com/api/beta/reps?lat=45.0&long=-45.0'
|
54
|
+
def address=(string)
|
55
|
+
@address = Param.new(:address, string)
|
56
|
+
params << @address
|
57
|
+
end
|
58
|
+
|
59
|
+
# Set the generate param : boolean
|
60
|
+
#
|
61
|
+
# By default making a call to the full index will return a cached
|
62
|
+
# JSON file. The cached file is updated regularly (usually every day).
|
63
|
+
# However, if you want to generate a fresh response directly from the
|
64
|
+
# database, you can set :generate to true. The response will be much
|
65
|
+
# slower, and in most cases will never be necessary. Has no effect
|
66
|
+
# when used with either :address or :lat/:long
|
67
|
+
#
|
68
|
+
# Usage:
|
69
|
+
# PYR.call(:reps) { |r| r.generate = true }
|
70
|
+
#
|
71
|
+
# Resulting URI:
|
72
|
+
# 'https://phone-your-rep.herokuapp.com/api/beta/reps?generate=true'
|
73
|
+
def generate=(boolean)
|
74
|
+
@generate = Param.new(:generate, boolean)
|
75
|
+
params << @generate
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/pyr/parser.rb
CHANGED
@@ -4,6 +4,32 @@ module PYR
|
|
4
4
|
class Resource
|
5
5
|
# Request object for sending requests to the /office_locations
|
6
6
|
# resource of the API
|
7
|
-
class OfficeLocations < Resource
|
7
|
+
class OfficeLocations < Resource
|
8
|
+
include GeoFindable
|
9
|
+
|
10
|
+
# Read the radius param
|
11
|
+
attr_reader :radius
|
12
|
+
|
13
|
+
# Set the radius param : integer
|
14
|
+
# Needs to be accompanied by :address or :lat & :long.
|
15
|
+
# When doing a geo search for office_locations the API returns
|
16
|
+
# a set that is sorted by distance to the request location.
|
17
|
+
# The radius param narrows down the geo search for office_locations to
|
18
|
+
# only those within the specified radius in miles.
|
19
|
+
# Without specifying the radius, the method will return all
|
20
|
+
# 1,900 - 2,000 active office_locations for Congress sorted by distance,
|
21
|
+
# which is seldom what you want.
|
22
|
+
#
|
23
|
+
# Usage:
|
24
|
+
# PYR.office_locations do |r|
|
25
|
+
# r.lat = 45.0
|
26
|
+
# r.long = -70.0
|
27
|
+
# r.radius = 100
|
28
|
+
# end
|
29
|
+
def radius=(integer)
|
30
|
+
@radius = Param.new(:radius, integer)
|
31
|
+
params << @radius
|
32
|
+
end
|
33
|
+
end
|
8
34
|
end
|
9
35
|
end
|
data/lib/pyr/resources/reps.rb
CHANGED
@@ -4,72 +4,7 @@ module PYR
|
|
4
4
|
class Resource
|
5
5
|
# Resource object for sending requests to the /reps resource of the API
|
6
6
|
class Reps < Resource
|
7
|
-
|
8
|
-
attr_reader :lat
|
9
|
-
# Read the long param
|
10
|
-
attr_reader :long
|
11
|
-
# Read the address param
|
12
|
-
attr_reader :address
|
13
|
-
# Read the generate param
|
14
|
-
attr_reader :generate
|
15
|
-
|
16
|
-
# Set the lat param : float
|
17
|
-
# Needs to be accompanied by :long.
|
18
|
-
#
|
19
|
-
# Usage:
|
20
|
-
# PYR.call :reps do |r|
|
21
|
-
# r.lat = 45.0
|
22
|
-
# r.long = -70.0
|
23
|
-
# end
|
24
|
-
def lat=(float)
|
25
|
-
@lat = Param.new(:lat, float)
|
26
|
-
params << @lat
|
27
|
-
end
|
28
|
-
|
29
|
-
# Set the long param : float
|
30
|
-
# Needs to be accompanied by :lat.
|
31
|
-
#
|
32
|
-
# Usage:
|
33
|
-
# PYR.call :reps do |r|
|
34
|
-
# r.lat = 45.0
|
35
|
-
# r.long = -70.0
|
36
|
-
# end
|
37
|
-
#
|
38
|
-
# Resulting URI: 'https://phone-your-rep.herokuapp.com/api/beta/reps?lat=45.0&long=-45.0'
|
39
|
-
def long=(float)
|
40
|
-
@long = Param.new(:long, float)
|
41
|
-
params << @long
|
42
|
-
end
|
43
|
-
|
44
|
-
# Set the address param : string
|
45
|
-
# :lat and :long take precedence
|
46
|
-
#
|
47
|
-
# Usage:
|
48
|
-
# PYR.call(:reps) { |r| r.address = '123 Main St., USA'}
|
49
|
-
#
|
50
|
-
# Resulting URI: 'https://phone-your-rep.herokuapp.com/api/beta/reps?lat=45.0&long=-45.0'
|
51
|
-
def address=(string)
|
52
|
-
@address = Param.new(:address, string)
|
53
|
-
params << @address
|
54
|
-
end
|
55
|
-
|
56
|
-
# Set the generate param : boolean
|
57
|
-
#
|
58
|
-
# By default making a call to the full :reps index will return a cached
|
59
|
-
# JSON file. The cached file is updated regularly (usually every day).
|
60
|
-
# However, if you want to generate a fresh response directly from the
|
61
|
-
# database, you can set :generate to true. The response will be much
|
62
|
-
# slower, and in most cases will never be necessary. Has no effect
|
63
|
-
# when used with either :address or :lat/:long
|
64
|
-
#
|
65
|
-
# Usage:
|
66
|
-
# PYR.call(:reps) { |r| r.generate = true }
|
67
|
-
#
|
68
|
-
# Resulting URI: 'https://phone-your-rep.herokuapp.com/api/beta/reps?generate=true'
|
69
|
-
def generate=(boolean)
|
70
|
-
@generate = Param.new(:generate, boolean)
|
71
|
-
params << @generate
|
72
|
-
end
|
7
|
+
include GeoFindable
|
73
8
|
end
|
74
9
|
end
|
75
10
|
end
|
data/lib/pyr/resources/zctas.rb
CHANGED
data/lib/pyr/response_object.rb
CHANGED
data/lib/pyr/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pyr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- M. Simon Borg
|
@@ -86,6 +86,7 @@ files:
|
|
86
86
|
- bin/console
|
87
87
|
- bin/setup
|
88
88
|
- lib/pyr.rb
|
89
|
+
- lib/pyr/geo_findable.rb
|
89
90
|
- lib/pyr/param.rb
|
90
91
|
- lib/pyr/parser.rb
|
91
92
|
- lib/pyr/request.rb
|