pyr 0.2.9 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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