opennorth-represent 0.1.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.
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