opennorth-represent 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.simplecov +4 -0
  5. data/.travis.yml +3 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +48 -0
  9. data/Rakefile +16 -0
  10. data/VERSION +1 -0
  11. data/features/README.md.feature +44 -0
  12. data/features/step_definitions/.gitkeep +0 -0
  13. data/features/support/.gitkeep +0 -0
  14. data/features/support/env.rb +1 -0
  15. data/lib/opennorth/represent.rb +43 -0
  16. data/lib/opennorth/represent/models/office.rb +11 -0
  17. data/lib/opennorth/represent/models/offices.rb +17 -0
  18. data/lib/opennorth/represent/models/postal_code.rb +20 -0
  19. data/lib/opennorth/represent/models/postal_codes.rb +13 -0
  20. data/lib/opennorth/represent/models/representative.rb +38 -0
  21. data/lib/opennorth/represent/models/representatives.rb +17 -0
  22. data/lib/opennorth/represent/requests/get_postal_code.rb +37 -0
  23. data/opennorth-represent.gemspec +28 -0
  24. data/spec/opennorth/represent/models/office_spec.rb +16 -0
  25. data/spec/opennorth/represent/models/offices_spec.rb +26 -0
  26. data/spec/opennorth/represent/models/postal_code_spec.rb +15 -0
  27. data/spec/opennorth/represent/models/postal_codes_spec.rb +30 -0
  28. data/spec/opennorth/represent/models/representative_spec.rb +74 -0
  29. data/spec/opennorth/represent/models/representatives_spec.rb +26 -0
  30. data/spec/opennorth/represent/requests/get_postal_code_spec.rb +16 -0
  31. data/spec/opennorth/represent_spec.rb +7 -0
  32. data/spec/spec_helper.rb +18 -0
  33. data/spec/support/.gitkeep +0 -0
  34. data/spec/support/composed_of_matcher.rb +6 -0
  35. data/spec/support/formats/postal_code_response.rb +9 -0
  36. data/spec/support/formats_matcher.rb +11 -0
  37. data/spec/support/shared_examples/collection_spec.rb +3 -0
  38. data/spec/support/shared_examples/model_specs.rb +6 -0
  39. data/spec/support/shared_examples/optional_model_attributes_include.rb +10 -0
  40. data/spec/support/shared_examples/request_specs.rb +8 -0
  41. data/spec/support/shared_examples/required_model_attributes_include.rb +10 -0
  42. metadata +218 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 628b78a5a9274c6d83d470ebf10737778dbe5020
4
+ data.tar.gz: 17c453cc23a538214b17bb94ca878d4efbc76f0b
5
+ SHA512:
6
+ metadata.gz: 2057d5c2740344ad8743b9ff51e28e83ac4b24e65a75dea4c6036ffefc371d48ec16bbee0b3b576005978eba021ca2c1e6ad1e69574f41a67dfdd4016c7d288d
7
+ data.tar.gz: fb1a797aa5c814b407395770a80344c52b0985479c3310714d41bea169068e62a1780f8315d21f8f4edccdede7e3d27e5f5e692e6c085afaa7d4928a255196f8
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,4 @@
1
+ SimpleCov.command_name(ENV['FOG_MOCK'] == "true" ? "mock" : "real")
2
+ SimpleCov.start do
3
+ add_filter "spec/"
4
+ end
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in opennorth-represent.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Caleb Buxton
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,48 @@
1
+ # Opennorth::Represent
2
+
3
+ Ruby Client for [represent.opennorth.ca's](http://represent.opennorth.ca) API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'opennorth-represent'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install opennorth-represent
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ require 'opennorth/represent'
23
+
24
+ service = Opennorth::Represent.new
25
+
26
+ postal_code = service.postal_codes.get("V6H2V4") # or your own postal code
27
+
28
+ member_of_parliament = postal_code.representatives.where(elected_office: "MP").first
29
+ hill_office = member_of_parliament.offices.where(type: "legislature").first
30
+
31
+ puts "To: #{member_of_parliament.honorific_prefix} #{member_of_parliament.name}"
32
+ puts "#{hill_office.postal}"
33
+ puts
34
+ puts "Dear, #{member_of_parliament.name}"
35
+ puts
36
+ puts "My message goes here"
37
+ puts
38
+ puts "Yours truly,"
39
+ puts "A constituent"
40
+ ```
41
+
42
+ ## Contributing
43
+
44
+ 1. Fork it
45
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
46
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
47
+ 4. Push to the branch (`git push origin my-new-feature`)
48
+ 5. Create new Pull Request
@@ -0,0 +1,16 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :mock
7
+
8
+ task :mock do
9
+ ENV['FOG_MOCK'] = "true"
10
+ Rake::Task[:spec].invoke
11
+ end
12
+
13
+ task :real do
14
+ ENV['FOG_MOCK'] = "false"
15
+ Rake::Task[:spec].invoke
16
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,44 @@
1
+ Feature: The public interface documented in the README
2
+
3
+ @disable-bundler
4
+ Scenario: First installation using Bundler
5
+ Given a file named "Gemfile" with:
6
+ """
7
+ gem "opennorth-represent", path: "../../"
8
+ """
9
+ And a file named "example.rb" with:
10
+ """
11
+ require 'opennorth/represent'
12
+
13
+ service = Opennorth::Represent.new
14
+
15
+ postal_code = service.postal_codes.get("V6H2V4") # or your own postal code
16
+
17
+ member_of_parliament = postal_code.representatives.where(elected_office: "MP").first
18
+ hill_office = member_of_parliament.offices.where(type: "legislature").first
19
+
20
+ puts "To: #{member_of_parliament.honorific_prefix} #{member_of_parliament.name}"
21
+ puts "#{hill_office.postal}"
22
+ puts
23
+ puts "Dear, #{member_of_parliament.name}"
24
+ puts
25
+ puts "My message goes here"
26
+ puts
27
+ puts "Yours truly,"
28
+ puts "A constituent"
29
+ """
30
+ And I run `bundle install > /dev/null`
31
+ When I successfully run `bundle exec ruby example.rb` for up to 6 seconds
32
+ Then the output should contain:
33
+ """
34
+ To: Hon. Hedy Fry
35
+ House of Commons
36
+ Ottawa On K1A 0A6
37
+
38
+ Dear, Hedy Fry
39
+
40
+ My message goes here
41
+
42
+ Yours truly,
43
+ A constituent
44
+ """
File without changes
File without changes
@@ -0,0 +1 @@
1
+ require 'aruba/cucumber'
@@ -0,0 +1,43 @@
1
+ require "fog"
2
+
3
+ module Opennorth
4
+ class Represent < Fog::Service
5
+ # Your code goes here...
6
+ VERSION = File.read(File.join(File.dirname(__FILE__),"..","..","VERSION"))
7
+
8
+ BASE_URL = "http://represent.opennorth.ca".freeze
9
+
10
+ request_path "opennorth/represent/requests"
11
+ request :get_postal_code
12
+
13
+ model_path 'opennorth/represent/models'
14
+ collection :postal_codes
15
+ model :postal_code
16
+
17
+ class Real
18
+ def initialize(options={})
19
+ @connection = Fog::Connection.new(BASE_URL,false,connection_options)
20
+ end
21
+
22
+ def request(options={})
23
+ connection.request(options)
24
+ end
25
+
26
+ private
27
+ attr_reader :connection
28
+
29
+ def connection_options
30
+ options = {}
31
+ options.merge!(proxy: ENV["FOG_PROXY"]) if ENV["FOG_PROXY"]
32
+ options
33
+ end
34
+
35
+ end
36
+
37
+ class Mock
38
+ def initialize(options={})
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,11 @@
1
+ module Opennorth
2
+ class Represent
3
+ class Office < Fog::Model
4
+
5
+ attribute :type, type: :string
6
+ attribute :fax, type: :string
7
+ attribute :postal, type: :string
8
+ attribute :tel, type: :string
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ require 'opennorth/represent/models/office'
2
+
3
+ module Opennorth
4
+ class Represent
5
+ class Offices < Fog::Collection
6
+ model Opennorth::Represent::Office
7
+
8
+ def where(attribute_value_map)
9
+ select do |rep|
10
+ attribute_value_map.all? do |(attribute, value)|
11
+ rep.send(attribute) == value
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ require 'opennorth/represent/models/representatives'
2
+
3
+ module Opennorth
4
+ class Represent
5
+ class PostalCode < Fog::Model
6
+ identity :code, type: :string
7
+ attribute :province, type: :string
8
+ attribute :city, type: :string
9
+
10
+ attribute :representatives, type: :array, aliases: %w(representatives_centroid)
11
+
12
+ def representatives=(representative_set)
13
+ attributes[:representatives] ||= Opennorth::Represent::Representatives.new(service: service)
14
+
15
+ self.representatives.clear
16
+ self.representatives.load(representative_set)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ require 'opennorth/represent/models/postal_code'
2
+
3
+ module Opennorth
4
+ class Represent
5
+ class PostalCodes < Fog::Collection
6
+ model Opennorth::Represent::PostalCode
7
+
8
+ def get(postal_code)
9
+ new.merge_attributes(service.get_postal_code(postal_code).body)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,38 @@
1
+ require 'opennorth/represent/models/offices'
2
+
3
+ module Opennorth
4
+ class Represent
5
+ class Representative < Fog::Model
6
+
7
+ attribute :name, type: :string
8
+ attribute :district_name, type: :string
9
+ attribute :elected_office, type: :string
10
+ attribute :source_url, type: :string
11
+
12
+ attribute :offices, type: :array
13
+
14
+ attribute :extra
15
+
16
+ def validate!
17
+ requires :name, :district_name, :elected_office, :source_url
18
+ end
19
+
20
+ def offices
21
+ attributes.fetch(:offices) { attributes[:offices] = Opennorth::Represent::Offices.new(service: service).load([]) }
22
+ end
23
+
24
+ def offices=(new_offices)
25
+ self.offices.clear
26
+ self.offices.load(new_offices)
27
+ end
28
+
29
+ def honorific_prefix
30
+ self.extra["honorific_prefix"]
31
+ end
32
+
33
+ def preferred_language
34
+ self.extra["preferred_language"]
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,17 @@
1
+ require 'opennorth/represent/models/representative'
2
+
3
+ module Opennorth
4
+ class Represent
5
+ class Representatives < Fog::Collection
6
+ model Opennorth::Represent::Representative
7
+
8
+ def where(attribute_value_map)
9
+ select do |rep|
10
+ attribute_value_map.all? do |(attribute, value)|
11
+ rep.send(attribute) == value
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ module Opennorth
2
+ class Represent
3
+ POSTAL_CODES_PATH = "/postcodes".freeze
4
+
5
+ class Real
6
+ def get_postal_code(postal_code)
7
+ response = request(path: postal_code_path(postal_code),
8
+ method: :get)
9
+
10
+ response.body = JSON::parse(response.body)
11
+ response
12
+ end
13
+
14
+ private
15
+ def postal_code_path(postal_code)
16
+ POSTAL_CODES_PATH + "/" + postal_code + "/"
17
+ end
18
+ end
19
+
20
+ class Mock
21
+ def get_postal_code(postal_code)
22
+ Excon::Response.new.tap do |response|
23
+ response.status = 200
24
+ response.body = JSON::parse(data)
25
+ end
26
+ end
27
+
28
+ private
29
+ def data
30
+ File.open(__FILE__).read.split(/^__END__/,2).last
31
+ end
32
+ end
33
+ end
34
+ end
35
+ __END__
36
+
37
+ {"province": "BC", "city": "Vancouver", "boundaries_centroid": [{"url": "/boundaries/federal-electoral-districts/59029/", "boundary_set_name": "Federal electoral district", "external_id": "59029", "name": "Vancouver Centre", "related": {"boundary_set_url": "/boundary-sets/federal-electoral-districts/"}}, {"url": "/boundaries/census-divisions/5915/", "boundary_set_name": "Census division", "external_id": "5915", "name": "Greater Vancouver", "related": {"boundary_set_url": "/boundary-sets/census-divisions/"}}, {"url": "/boundaries/census-subdivisions/5915022/", "boundary_set_name": "Census subdivision", "external_id": "5915022", "name": "Vancouver", "related": {"boundary_set_url": "/boundary-sets/census-subdivisions/"}}, {"url": "/boundaries/british-columbia-electoral-districts/vancouver-fairview/", "boundary_set_name": "British Columbia electoral district", "external_id": "VFA", "name": "Vancouver-Fairview", "related": {"boundary_set_url": "/boundary-sets/british-columbia-electoral-districts/"}}], "code": "V6H2V4", "centroid": {"type": "Point", "coordinates": [-123.135993431, 49.26297987]}, "representatives_centroid": [{"first_name": "George", "last_name": "Affleck", "name": "George Affleck", "elected_office": "Councillor", "url": "http://vancouver.ca/your-government/george-affleck.aspx", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/census-subdivisions/5915022/", "representative_set_url": "/representative-sets/vancouver-city-council/"}, "source_url": "http://vancouver.ca/your-government/george-affleck.aspx", "offices": [], "representative_set_name": "Vancouver City Council", "party_name": "", "district_name": "", "email": "clraffleck@vancouver.ca", "personal_url": "", "photo_url": "http://vancouver.ca/images/cov/feature/councillor-2012-affleck.jpg"}, {"first_name": "Elizabeth", "last_name": "Ball", "name": "Elizabeth Ball", "elected_office": "Councillor", "url": "http://vancouver.ca/your-government/elizabeth-ball.aspx", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/census-subdivisions/5915022/", "representative_set_url": "/representative-sets/vancouver-city-council/"}, "source_url": "http://vancouver.ca/your-government/elizabeth-ball.aspx", "offices": [], "representative_set_name": "Vancouver City Council", "party_name": "", "district_name": "", "email": "clrball@vancouver.ca", "personal_url": "", "photo_url": "http://vancouver.ca/images/cov/feature/councillor-2012-ball.jpg"}, {"first_name": "Adriane", "last_name": "Carr", "name": "Adriane Carr", "elected_office": "Councillor", "url": "http://vancouver.ca/your-government/adriane-carr.aspx", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/census-subdivisions/5915022/", "representative_set_url": "/representative-sets/vancouver-city-council/"}, "source_url": "http://vancouver.ca/your-government/adriane-carr.aspx", "offices": [], "representative_set_name": "Vancouver City Council", "party_name": "", "district_name": "", "email": "clrcarr@vancouver.ca", "personal_url": "", "photo_url": "http://vancouver.ca/images/cov/feature/councillor-2012-carr.jpg"}, {"first_name": "Heather", "last_name": "Deal", "name": "Heather Deal", "elected_office": "Councillor", "url": "http://vancouver.ca/your-government/heather-deal.aspx", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/census-subdivisions/5915022/", "representative_set_url": "/representative-sets/vancouver-city-council/"}, "source_url": "http://vancouver.ca/your-government/heather-deal.aspx", "offices": [], "representative_set_name": "Vancouver City Council", "party_name": "", "district_name": "", "email": "clrdeal@vancouver.ca", "personal_url": "", "photo_url": "http://vancouver.ca/images/cov/feature/councillor-2012-deal.jpg"}, {"first_name": "Kerry", "last_name": "Jang", "name": "Kerry Jang", "elected_office": "Councillor", "url": "http://vancouver.ca/your-government/kerry-jang.aspx", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/census-subdivisions/5915022/", "representative_set_url": "/representative-sets/vancouver-city-council/"}, "source_url": "http://vancouver.ca/your-government/kerry-jang.aspx", "offices": [], "representative_set_name": "Vancouver City Council", "party_name": "", "district_name": "", "email": "clrjang@vancouver.ca", "personal_url": "", "photo_url": "http://vancouver.ca/images/cov/feature/councillor-2012-jang.jpg"}, {"first_name": "Raymond", "last_name": "Louie", "name": "Raymond Louie", "elected_office": "Councillor", "url": "http://vancouver.ca/your-government/raymond-louie.aspx", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/census-subdivisions/5915022/", "representative_set_url": "/representative-sets/vancouver-city-council/"}, "source_url": "http://vancouver.ca/your-government/raymond-louie.aspx", "offices": [], "representative_set_name": "Vancouver City Council", "party_name": "", "district_name": "", "email": "clrlouie@vancouver.ca", "personal_url": "", "photo_url": "http://vancouver.ca/images/cov/feature/councillor-2012-louie.jpg"}, {"first_name": "Geoff", "last_name": "Meggs", "name": "Geoff Meggs", "elected_office": "Councillor", "url": "http://vancouver.ca/your-government/geoff-meggs.aspx", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/census-subdivisions/5915022/", "representative_set_url": "/representative-sets/vancouver-city-council/"}, "source_url": "http://vancouver.ca/your-government/geoff-meggs.aspx", "offices": [], "representative_set_name": "Vancouver City Council", "party_name": "", "district_name": "", "email": "clrmeggs@vancouver.ca", "personal_url": "", "photo_url": "http://vancouver.ca/images/cov/feature/councillor-2012-meggs.jpg"}, {"first_name": "Andrea", "last_name": "Reimer", "name": "Andrea Reimer", "elected_office": "Councillor", "url": "http://vancouver.ca/your-government/andrea-reimer.aspx", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/census-subdivisions/5915022/", "representative_set_url": "/representative-sets/vancouver-city-council/"}, "source_url": "http://vancouver.ca/your-government/andrea-reimer.aspx", "offices": [], "representative_set_name": "Vancouver City Council", "party_name": "", "district_name": "", "email": "clrreimer@vancouver.ca", "personal_url": "", "photo_url": "http://vancouver.ca/images/cov/feature/councillor-2012-reimer.jpg"}, {"first_name": "Tim", "last_name": "Stevenson", "name": "Tim Stevenson", "elected_office": "Councillor", "url": "http://vancouver.ca/your-government/tim-stevenson.aspx", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/census-subdivisions/5915022/", "representative_set_url": "/representative-sets/vancouver-city-council/"}, "source_url": "http://vancouver.ca/your-government/tim-stevenson.aspx", "offices": [], "representative_set_name": "Vancouver City Council", "party_name": "", "district_name": "", "email": "clrstevenson@vancouver.ca", "personal_url": "", "photo_url": "http://vancouver.ca/images/cov/feature/councillor-2012-stevenson.jpg"}, {"first_name": "Tony", "last_name": "Tang", "name": "Tony Tang", "elected_office": "Councillor", "url": "http://vancouver.ca/your-government/tony-tang.aspx", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/census-subdivisions/5915022/", "representative_set_url": "/representative-sets/vancouver-city-council/"}, "source_url": "http://vancouver.ca/your-government/tony-tang.aspx", "offices": [], "representative_set_name": "Vancouver City Council", "party_name": "", "district_name": "", "email": "clrtang@vancouver.ca", "personal_url": "", "photo_url": "http://vancouver.ca/images/cov/feature/councillor-2012-tang.jpg"}, {"first_name": "Gregor", "last_name": "Robertson", "name": "Gregor Robertson", "elected_office": "Mayor", "url": "http://vancouver.ca/your-government/mayor-gregor-robertson.aspx", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/census-subdivisions/5915022/", "representative_set_url": "/representative-sets/vancouver-city-council/"}, "source_url": "http://vancouver.ca/your-government/mayor-gregor-robertson.aspx", "offices": [], "representative_set_name": "Vancouver City Council", "party_name": "", "district_name": "", "email": "gregor.robertson@vancouver.ca", "personal_url": "", "photo_url": "http://vancouver.ca/images/cov/feature/mayor-2012-robertson.PNG"}, {"first_name": "George", "last_name": "Heyman", "name": "George Heyman", "elected_office": "MLA", "url": "http://www.leg.bc.ca/mla/40thparl/heyman-George.htm", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/british-columbia-electoral-districts/vancouver-fairview/", "representative_set_url": "/representative-sets/bc-legislature/"}, "source_url": "http://www.leg.bc.ca/mla/3-1-6.htm", "offices": [{"tel": "1-250-387-3655", "fax": "1-250-387-4680", "postal": "Room 201\nParliament Buildings\nVictoria BC V8V 1X4", "type": "legislature"}, {"tel": "1-604-775-2453", "fax": "1-604-660-6821", "postal": "642 West Broadway\nVancouver BC V5Z 1G1", "type": "constituency"}], "representative_set_name": "Legislative Assembly of British Columbia", "party_name": "New Democratic Party of BC", "district_name": "Vancouver-Fairview", "email": "george.heyman.mla@leg.bc.ca", "personal_url": "", "photo_url": "http://www.leg.bc.ca/mla/40thparl/images/members_lrg/heyman-George.jpg"}, {"first_name": "Hedy", "last_name": "Fry", "name": "Hedy Fry", "elected_office": "MP", "url": "http://www.parl.gc.ca/MembersOfParliament/ProfileMP.aspx?Key=170551&Language=E", "gender": "", "extra": {"honorific_prefix": "Hon.", "preferred_language": "English"}, "related": {"boundary_url": "/boundaries/federal-electoral-districts/59029/", "representative_set_url": "/representative-sets/house-of-commons/"}, "source_url": "http://www.parl.gc.ca/MembersOfParliament/MainMPsCompleteList.aspx?TimePeriod=Current&Language=E", "offices": [{"type": "legislature", "fax": "1-613-995-0056", "postal": "House of Commons\nOttawa ON K1A 0A6", "tel": "1-613-992-3213"}, {"type": "constituency", "fax": "1-604-666-0114", "postal": "1030 Denman St, Suite 106\nVancouver BC V6G 2M6", "tel": "1-604-666-0135"}], "representative_set_name": "House of Commons", "party_name": "Liberal", "district_name": "Vancouver Centre", "email": "hedy.fry@parl.gc.ca", "personal_url": "http://www.hedyfry.com/", "photo_url": "http://www.parl.gc.ca/MembersOfParliament/Images/OfficialMPPhotos/41/FryHedy__Lib.jpg"}], "boundaries_concordance": []}
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "opennorth-represent"
7
+ spec.version = File.read(File.join(File.dirname(__FILE__),"VERSION"))
8
+ spec.authors = ["Caleb Buxton"]
9
+ spec.email = ["me@cpb.ca"]
10
+ spec.description = %q{Ruby Client for represent.opennorth.ca's API}
11
+ spec.summary = %q{Ruby Client for represent.opennorth.ca's API}
12
+ spec.homepage = "https://github.com/cpb/opennorth-represent"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "fog", "~> 1.20"
21
+ spec.add_development_dependency "aruba"
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "rspec", "~> 3.0.0.beta1"
25
+ spec.add_development_dependency "rspec-collection_matchers"
26
+ spec.add_development_dependency "pry"
27
+ spec.add_development_dependency "simplecov"
28
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+ require 'opennorth/represent/models/office'
3
+
4
+ describe Opennorth::Represent::Office, type: :model do
5
+ let(:service) { Opennorth::Represent.new({}) }
6
+
7
+ let(:required_model_attributes) { {} }
8
+ let(:optional_model_attributes) {{
9
+ "type" => "legislature",
10
+ "fax" => "1-613-941-6900",
11
+ "postal" => "House of Commons\nOttawa ON K1A 0A6",
12
+ "tel" => "1-613-992-4211"
13
+ }}
14
+
15
+ it_behaves_like "optional model attributes include", %w(type fax postal tel)
16
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'Opennorth/represent/models/offices'
3
+
4
+ describe Opennorth::Represent::Offices, type: :collection do
5
+ let(:service) { Opennorth::Represent.new({}) }
6
+
7
+ let(:sample_set) { service.get_postal_code("V6H2V4").body["representatives_centroid"].last["offices"] }
8
+
9
+
10
+ context "loaded with sample data" do
11
+
12
+ let(:loaded_collection) { described_collection.load(sample_set) }
13
+
14
+ describe "#where" do
15
+ subject { loaded_collection.where(type: "legislature") }
16
+
17
+ it "should return a collection" do
18
+ expect(subject).to have(1).item
19
+ end
20
+
21
+ it "should contain only matches" do
22
+ expect(subject).to be_all {|rep| rep.type == "legislature"}
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require 'opennorth/represent/models/postal_code'
3
+ require 'opennorth/represent/models/representative'
4
+
5
+ describe Opennorth::Represent::PostalCode, type: :model do
6
+ let(:service) { Opennorth::Represent.new({}) }
7
+
8
+ describe "#representatives" do
9
+ subject { service.postal_codes.get("V6H2V4").representatives }
10
+
11
+ it "should be composed of Representatives" do
12
+ expect(subject).to be_composed_of(Opennorth::Represent::Representative)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ require 'opennorth/represent/models/postal_codes'
3
+
4
+ describe Opennorth::Represent::PostalCodes, type: :collection do
5
+ let(:service) { Opennorth::Represent.new({}) }
6
+
7
+ describe "#get" do
8
+ subject { described_collection.get("V6H2V4") }
9
+
10
+ it "should have a the code we asked to get" do
11
+ expect(subject.code).to eql("V6H2V4")
12
+ end
13
+
14
+ it "should have the code as the id" do
15
+ expect(subject.identity).to eql("V6H2V4")
16
+ end
17
+
18
+ it "should have a province" do
19
+ expect(subject.province).to eql("BC")
20
+ end
21
+
22
+ it "should have a city" do
23
+ expect(subject.city).to eql("Vancouver")
24
+ end
25
+
26
+ it "should have representatives" do
27
+ expect(subject.representatives).to have(13).items
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+ require 'opennorth/represent/models/representative'
3
+
4
+ describe Opennorth::Represent::Representative, type: :model do
5
+ let(:service) { Opennorth::Represent.new({}) }
6
+ let(:required_model_attributes) {{
7
+ "name" => "Stephen Harper",
8
+ "district_name" => "Calgary Southwest",
9
+ "elected_office" => "MP",
10
+ "source_url" => "http://badnews.ca"
11
+ }}
12
+
13
+ it_behaves_like "required model attributes include", %w(name district_name elected_office source_url)
14
+
15
+ let(:optional_model_attributes) {{
16
+ "offices" => [
17
+ {
18
+ "type" => "legislature",
19
+ "fax" => "1-613-941-6900",
20
+ "postal" => "House of Commons\nOttawa ON K1A 0A6",
21
+ "tel" => "1-613-992-4211"
22
+ },
23
+ {
24
+ "type" => "constituency",
25
+ "fax" => "1-403-253-8203",
26
+ "postal" => "1600 - 90th Avenue SW, Suite A-203\nCalgary AB T2V 5A8",
27
+ "tel" => "1-403-253-7990"
28
+ }
29
+ ],
30
+ "extra" => {
31
+ "honorific_prefix" => "Right Hon.",
32
+ "preferred_language" => "English"
33
+ }
34
+ }}
35
+
36
+ describe "optionally" do
37
+ it "may have a first_name"
38
+ it "may have a last_name"
39
+ it "may have a party_name"
40
+ it "may have an email"
41
+ it "may have a url"
42
+ it "may have a photo_url"
43
+ it "may have a personal_url"
44
+ it "may have a district_id"
45
+ it "may have a geneder"
46
+
47
+ it "may have offices" do
48
+ expect(subject.offices).to have(2).items
49
+
50
+ expect(described_class.new(model_options.reject {|k,_| k == 'offices'}).offices).to be_empty
51
+ end
52
+ end
53
+
54
+ describe "#offices" do
55
+
56
+ subject { record.offices }
57
+
58
+ it "should be composed of Offices" do
59
+ expect(subject).to be_composed_of(Opennorth::Represent::Office)
60
+ end
61
+ end
62
+
63
+ describe "#honorific_prefix" do
64
+ it "should be retrieved from the extra" do
65
+ expect(record.honorific_prefix).to eql("Right Hon.")
66
+ end
67
+ end
68
+
69
+ describe "#preferred_language" do
70
+ it "should be retrieved from the extra" do
71
+ expect(record.preferred_language).to eql("English")
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'opennorth/represent/models/representatives'
3
+
4
+ describe Opennorth::Represent::Representatives, type: :collection do
5
+ let(:service) { Opennorth::Represent.new({}) }
6
+
7
+ let(:sample_set) { service.get_postal_code("V6H2V4").body["representatives_centroid"] }
8
+
9
+
10
+ context "loaded with sample data" do
11
+
12
+ let(:loaded_collection) { described_collection.load(sample_set) }
13
+
14
+ describe "#where" do
15
+ subject { loaded_collection.where(elected_office: "MP") }
16
+
17
+ it "should return a collection" do
18
+ expect(subject).to have(1).item
19
+ end
20
+
21
+ it "should contain only matches" do
22
+ expect(subject).to be_all {|rep| rep.elected_office == "MP"}
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Opennorth::Represent, "#get_postal_code", type: :request do
4
+ let(:service_options) {{}}
5
+ context "success" do
6
+ subject { described_request("V6H2V4") }
7
+
8
+ it "should be status 200" do
9
+ expect(subject.status).to eql(200)
10
+ end
11
+
12
+ it "should be formatted as a postal code response" do
13
+ expect(subject.body).to be_formatted_like(POSTAL_CODE_RESPONSE)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Opennorth::Represent do
4
+ it 'should have a version number' do
5
+ expect(Opennorth::Represent::VERSION).to_not be_nil
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'opennorth/represent'
3
+ require 'pry'
4
+
5
+ require 'rspec/collection_matchers'
6
+
7
+ require 'simplecov'
8
+
9
+ Dir[File.join(File.dirname(__FILE__),"support","**","*.rb")].each { |f| require f }
10
+
11
+ RSpec.configure do |c|
12
+ c.before do
13
+ if ENV['FOG_MOCK'] == "true"
14
+ Fog.mock!
15
+ Fog::Mock.reset
16
+ end
17
+ end
18
+ end
File without changes
@@ -0,0 +1,6 @@
1
+ RSpec::Matchers.define :be_composed_of do |expected_class|
2
+ match do |actual|
3
+ expect(actual).to_not be_empty
4
+ actual.all? {|item| item.is_a?(expected_class) }
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ POSTAL_CODE_RESPONSE = {
2
+ "province" => String,
3
+ "city" => String,
4
+ "boundaries_centroid" => Array,
5
+ "code" => String,
6
+ "centroid" => Hash,
7
+ "representatives_centroid" => Array,
8
+ "boundaries_concordance" => Array
9
+ }
@@ -0,0 +1,11 @@
1
+ require 'fog/schema/data_validator'
2
+ require File.join(File.dirname(Gem::Specification.find_by_name("fog").load_paths.first),"tests","helpers","formats_helper")
3
+
4
+ Dir[File.join(File.dirname(__FILE__),"formats","**","*.rb")].each { |f| require f }
5
+
6
+ RSpec::Matchers.define :be_formatted_like do |expected|
7
+ match do |actual|
8
+ @validator = Fog::Schema::DataValidator.new
9
+ @validator.validate(actual, expected, {})
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ shared_examples_for type: :collection do |context|
2
+ let(:described_collection) { described_class.new(service: service) }
3
+ end
@@ -0,0 +1,6 @@
1
+ shared_examples_for type: :model do |context|
2
+ let(:model_options) { optional_model_attributes.merge(required_model_attributes.merge(service: service)) }
3
+
4
+ let(:record) { described_class.new(model_options) }
5
+ subject { record }
6
+ end
@@ -0,0 +1,10 @@
1
+ shared_examples_for "optional model attributes include" do |set_of_attributes|
2
+ set_of_attributes.each do |attribute|
3
+ it attribute do
4
+ expect(record.send(attribute)).to eql(optional_model_attributes[attribute])
5
+
6
+ sans_attribute = model_options.reject {|k,_| k == attribute}
7
+ expect(described_class.new(sans_attribute).send(attribute)).to be_nil
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ shared_examples_for type: :request do |context|
2
+ let(:request_name) { context.metadata[:example_group][:description_args].last.sub('#','').to_sym }
3
+ let(:service) { described_class.new(service_options) }
4
+
5
+ def described_request(*args)
6
+ service.send(request_name,*args)
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ shared_examples_for "required model attributes include" do |set_of_attributes|
2
+ set_of_attributes.each do |attribute|
3
+ it attribute do
4
+ sans_attribute = model_options.reject {|k,_| k == attribute}
5
+ expect do
6
+ described_class.new(sans_attribute).validate!
7
+ end.to raise_error(ArgumentError, /#{attribute} is required/)
8
+ end
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,218 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: opennorth-represent
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Caleb Buxton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fog
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.20'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.20'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aruba
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 3.0.0.beta1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 3.0.0.beta1
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-collection_matchers
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Ruby Client for represent.opennorth.ca's API
126
+ email:
127
+ - me@cpb.ca
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - .gitignore
133
+ - .rspec
134
+ - .simplecov
135
+ - .travis.yml
136
+ - Gemfile
137
+ - LICENSE.txt
138
+ - README.md
139
+ - Rakefile
140
+ - VERSION
141
+ - features/README.md.feature
142
+ - features/step_definitions/.gitkeep
143
+ - features/support/.gitkeep
144
+ - features/support/env.rb
145
+ - lib/opennorth/represent.rb
146
+ - lib/opennorth/represent/models/office.rb
147
+ - lib/opennorth/represent/models/offices.rb
148
+ - lib/opennorth/represent/models/postal_code.rb
149
+ - lib/opennorth/represent/models/postal_codes.rb
150
+ - lib/opennorth/represent/models/representative.rb
151
+ - lib/opennorth/represent/models/representatives.rb
152
+ - lib/opennorth/represent/requests/get_postal_code.rb
153
+ - opennorth-represent.gemspec
154
+ - spec/opennorth/represent/models/office_spec.rb
155
+ - spec/opennorth/represent/models/offices_spec.rb
156
+ - spec/opennorth/represent/models/postal_code_spec.rb
157
+ - spec/opennorth/represent/models/postal_codes_spec.rb
158
+ - spec/opennorth/represent/models/representative_spec.rb
159
+ - spec/opennorth/represent/models/representatives_spec.rb
160
+ - spec/opennorth/represent/requests/get_postal_code_spec.rb
161
+ - spec/opennorth/represent_spec.rb
162
+ - spec/spec_helper.rb
163
+ - spec/support/.gitkeep
164
+ - spec/support/composed_of_matcher.rb
165
+ - spec/support/formats/postal_code_response.rb
166
+ - spec/support/formats_matcher.rb
167
+ - spec/support/shared_examples/collection_spec.rb
168
+ - spec/support/shared_examples/model_specs.rb
169
+ - spec/support/shared_examples/optional_model_attributes_include.rb
170
+ - spec/support/shared_examples/request_specs.rb
171
+ - spec/support/shared_examples/required_model_attributes_include.rb
172
+ homepage: https://github.com/cpb/opennorth-represent
173
+ licenses:
174
+ - MIT
175
+ metadata: {}
176
+ post_install_message:
177
+ rdoc_options: []
178
+ require_paths:
179
+ - lib
180
+ required_ruby_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - '>='
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ required_rubygems_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ requirements: []
191
+ rubyforge_project:
192
+ rubygems_version: 2.0.3
193
+ signing_key:
194
+ specification_version: 4
195
+ summary: Ruby Client for represent.opennorth.ca's API
196
+ test_files:
197
+ - features/README.md.feature
198
+ - features/step_definitions/.gitkeep
199
+ - features/support/.gitkeep
200
+ - features/support/env.rb
201
+ - spec/opennorth/represent/models/office_spec.rb
202
+ - spec/opennorth/represent/models/offices_spec.rb
203
+ - spec/opennorth/represent/models/postal_code_spec.rb
204
+ - spec/opennorth/represent/models/postal_codes_spec.rb
205
+ - spec/opennorth/represent/models/representative_spec.rb
206
+ - spec/opennorth/represent/models/representatives_spec.rb
207
+ - spec/opennorth/represent/requests/get_postal_code_spec.rb
208
+ - spec/opennorth/represent_spec.rb
209
+ - spec/spec_helper.rb
210
+ - spec/support/.gitkeep
211
+ - spec/support/composed_of_matcher.rb
212
+ - spec/support/formats/postal_code_response.rb
213
+ - spec/support/formats_matcher.rb
214
+ - spec/support/shared_examples/collection_spec.rb
215
+ - spec/support/shared_examples/model_specs.rb
216
+ - spec/support/shared_examples/optional_model_attributes_include.rb
217
+ - spec/support/shared_examples/request_specs.rb
218
+ - spec/support/shared_examples/required_model_attributes_include.rb