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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e1491c2bf3745ed6129b38b129f867e3e45c411c
4
- data.tar.gz: a9117f49800abfef2b3c80c4078e6ca2679db14f
3
+ metadata.gz: 05417621a790e6818011d19f83a9307b77e12522
4
+ data.tar.gz: b1685e7ade99c0fb3f5577892599604c5c3fc590
5
5
  SHA512:
6
- metadata.gz: ae1fce84b54cdc4d868b087f5c6d1550d08d9498f174214096feca50772da3da9f00c79b8784dbc8257158e810bda35c471b35b1f5cdcc99d5572cfd77263a6b
7
- data.tar.gz: bf442cd044a7cdcbe29b75e9a4448043e73d8c78ba43671388768ee26ff0782ae02cd2487d02673ffca81f6c9b39ee1467ee02cd595391c694a83aa2ef6fe91c
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.call(:reps, 'S000033').objects.first.office_locations.district.first
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.call(:reps) { |r| r.address = 'vermont' }.objects.representatives.first
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 provides an easy interface to the Phone Your Rep API,
45
- # converting the data payloads into Plain Old Ruby Objects.
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.uri # => 'https://phone-your-rep.herokuapp.com/api/beta/reps?address=vermont'
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
- yield resource if block_given?
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
@@ -1,4 +1,3 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module PYR
@@ -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; end
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
@@ -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
- # Read the lat param
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
@@ -8,8 +8,8 @@ module PYR
8
8
  attr_reader :reps
9
9
 
10
10
  # Set the 'reps' param value
11
- def reps=(value)
12
- @reps = Param.new(:reps, value)
11
+ def reps=(boolean)
12
+ @reps = Param.new(:reps, boolean)
13
13
  params << @reps
14
14
  end
15
15
  end
@@ -28,7 +28,7 @@ module PYR
28
28
  @controller ||= self.class.to_s.split('::').last.tableize
29
29
  end
30
30
 
31
- #
31
+ # Send a request to the API for the object.
32
32
  def call
33
33
  PYR.call self
34
34
  end
data/lib/pyr/version.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+
3
4
  module PYR
4
- VERSION = '0.2.9' # :nodoc:
5
+ VERSION = '0.3.0' # :nodoc:
5
6
  end
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.2.9
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