google-civic-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ecf478592957b5fc9111b2f913dbc780eeae1fc9
4
+ data.tar.gz: d6ad081f1789c5b78160b765ed184be3c6de9ad1
5
+ SHA512:
6
+ metadata.gz: 348df3a75d235aa9fb9090364b8f9d350801fa1511a6559a3f56d1510c16a8e10f624bc3a1c45a6ff2686f5f93166f120798ed51ed2e9e1a89a9622d3448c1e2
7
+ data.tar.gz: 38a8a77b5263029ad0821ad7dbf63baaf266a69374c82e62166cd916ce8efa1525fda257f68898c8f98f43b2b6f93d37bc25433b69b24618bd89fb10f263d6fc
@@ -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
@@ -0,0 +1,6 @@
1
+ script: "bundle exec rspec spec"
2
+
3
+ language: ruby
4
+
5
+ rvm:
6
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in google-civic-api-ruby.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Adam Cuppy
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,28 @@
1
+ # Google::Civic
2
+ [![Build Status](https://travis-ci.org/CodingZeal/google-civic-ruby.svg?branch=master)](https://travis-ci.org/CodingZeal/google-civic-ruby) [![Code Climate](https://codeclimate.com/github/CodingZeal/google-civic-ruby.png)](https://codeclimate.com/github/CodingZeal/google-civic-ruby)
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ gem 'google-civic-ruby'
9
+
10
+ And then execute:
11
+
12
+ $ bundle
13
+
14
+ Or install it yourself as:
15
+
16
+ $ gem install google-civic-ruby
17
+
18
+ ## Usage
19
+
20
+
21
+
22
+ ## Contributing
23
+
24
+ 1. Fork it ( http://github.com/<my-github-username>/google-civic-api-ruby/fork )
25
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
26
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
27
+ 4. Push to the branch (`git push origin my-new-feature`)
28
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -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
+ require 'google-civic/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "google-civic-ruby"
8
+ spec.version = Google::Civic::VERSION
9
+ spec.authors = ["Coding ZEAL", "Adam Cuppy"]
10
+ spec.email = ["adam@codingzeal.com"]
11
+ spec.summary = %q{Ruby wrapper for the Google Civic API}
12
+ spec.homepage = "https://github.com/CodingZeal/google-civic-ruby"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.test_files = spec.files.grep(%r{^(spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_dependency "multi_json", "~> 1.10"
20
+ spec.add_dependency "hashie", "~> 3.0"
21
+ spec.add_dependency "faraday", "~> 0.9"
22
+ spec.add_dependency "faraday_middleware", "~> 0.9"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rspec", "~> 2.14"
26
+ spec.add_development_dependency "pry"
27
+ spec.add_development_dependency "webmock", "~> 1.18"
28
+ end
@@ -0,0 +1,9 @@
1
+ require 'google-civic/version'
2
+ require 'google-civic/election'
3
+ require 'google-civic/elections'
4
+ # require 'google-civic/address'
5
+ # require 'google-civic/voter_info'
6
+ require 'google-civic/client'
7
+ require 'google-civic/router'
8
+ require 'google-civic/requester'
9
+ require "google-civic/connection"
@@ -0,0 +1,34 @@
1
+ module Google
2
+ module Civic
3
+ class Client
4
+ def initialize(api_key, connection)
5
+ @api_key = api_key
6
+ @connection = connection
7
+ end
8
+
9
+ def elections(zipcode)
10
+ Elections.for_zipcode(zipcode, self)
11
+ end
12
+
13
+ def voter_info(address)
14
+ VoterInfo.for_address(address, self)
15
+ end
16
+
17
+ def request(*args)
18
+ @request ||= {}
19
+ @request[args] ||= Requester.new(connection, { key: api_key }).request(*args)
20
+ end
21
+
22
+ private
23
+
24
+ def connection
25
+ @connection or raise "Connection not established"
26
+ end
27
+
28
+ def api_key
29
+ @api_key or raise "No Google API key defined"
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,42 @@
1
+ require "faraday"
2
+ require "faraday_middleware"
3
+
4
+ module Google
5
+ module Civic
6
+ class Connection
7
+ attr_writer :base_url
8
+
9
+ def initialize(params={})
10
+ @base_url = params.delete(:base_url)
11
+ establish!
12
+ end
13
+
14
+ def get(*args, &block)
15
+ resource.get(*args, &block)
16
+ end
17
+
18
+ def post(*args, &block)
19
+ resource.post(*args, &block)
20
+ end
21
+
22
+ private
23
+
24
+ def establish!
25
+ @resource = Faraday.new(base_url) do |builder|
26
+ builder.request :json
27
+ builder.request :url_encoded
28
+ builder.use FaradayMiddleware::ParseJson
29
+ builder.adapter Faraday.default_adapter
30
+ end
31
+ end
32
+
33
+ def resource
34
+ @resource or raise "Connection not established"
35
+ end
36
+
37
+ def base_url
38
+ @base_url or ""
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,14 @@
1
+ require "multi_json"
2
+ require "hashie"
3
+
4
+ module Google
5
+ module Civic
6
+ class Election < Hashie::Dash
7
+ include Hashie::Extensions::Dash::IndifferentAccess
8
+
9
+ property :id, required: true
10
+ property :name, required: true
11
+ property :electionDay, required: true
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,34 @@
1
+ require "multi_json"
2
+
3
+ module Google
4
+ module Civic
5
+ module Elections
6
+
7
+ class InvalidZipcode < Exception; end
8
+
9
+ class << self
10
+
11
+ def for_zipcode(zipcode, client)
12
+ raise InvalidZipcode if not zipcode?(zipcode)
13
+ elections_from_response collection(zipcode, client)
14
+ end
15
+
16
+ private
17
+
18
+ def elections_from_response(response)
19
+ response.body.fetch("elections").map do |election|
20
+ Election.new(election)
21
+ end
22
+ end
23
+
24
+ def collection(zipcode, client)
25
+ client.request(:elections, zipcode: zipcode)
26
+ end
27
+
28
+ def zipcode?(zipcode)
29
+ zipcode =~ /\A\d{5}(?:[-\s]\d{4})?\z/
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ module Google
2
+ module Civic
3
+ class Requester
4
+ include Router
5
+
6
+ def initialize(connection, request_params={})
7
+ @connection = connection
8
+ @connection.base_url = BASE_URL
9
+ @request_params = request_params
10
+ end
11
+
12
+ def request(kind, params={})
13
+ @connection.send method_for(kind) do |request|
14
+ request.url path_for(kind), @request_params.merge(params)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ module Google
2
+ module Civic
3
+ module Router
4
+
5
+ BASE_URL = "https://www.googleapis.com"
6
+ BASE_PATH = "/civicinfo/v1"
7
+ ROUTES = {
8
+ elections: {
9
+ method: :get,
10
+ path: "/elections",
11
+ klass: Election
12
+ }
13
+ }
14
+
15
+ private
16
+
17
+ def route_map_for(kind)
18
+ ROUTES.fetch(kind)
19
+ end
20
+
21
+ def method_for(kind)
22
+ route_map_for(kind).fetch(:method)
23
+ end
24
+
25
+ def path_for(kind)
26
+ [BASE_PATH, route_map_for(kind).fetch(:path)].join('')
27
+ end
28
+
29
+ def klass_for(kind)
30
+ route_map_for(kind).fetch(:klass)
31
+ end
32
+ alias :class_for :klass_for
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,5 @@
1
+ module Google
2
+ module Civic
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ module Google
4
+ module Civic
5
+ describe Client do
6
+ include_context "a connection to the client"
7
+
8
+ describe "#request" do
9
+ subject { client.request(request_type, request_params) }
10
+ let(:zipcode) { "12345" }
11
+ let(:request_type) { :elections }
12
+ let(:request_params) { Hash[ zipcode: zipcode ] }
13
+
14
+ it { expect(subject).to be_a_kind_of Faraday::Response }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+ require "multi_json"
3
+
4
+ module Google::Civic
5
+ describe Election do
6
+ subject { Election.new(response) }
7
+ let(:response) { MultiJson.load(load_fixture("elections"))["elections"][0] }
8
+
9
+ its(:id) { should_not be_nil }
10
+ its(:name) { should_not be_nil }
11
+ its(:electionDay) { should_not be_nil }
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+
3
+ module Google
4
+ module Civic
5
+ describe Elections do
6
+ include_context "a connection to the client"
7
+
8
+ describe ".for_zipcode" do
9
+ subject { Elections.for_zipcode(zipcode, client) }
10
+
11
+ context "with an invalid zipcode" do
12
+ let(:zipcode) { "1234567890" }
13
+ it { expect { subject }.to raise_error(Elections::InvalidZipcode) }
14
+ end
15
+
16
+ context "with a valid 9 digit zipcode" do
17
+ let(:zipcode) { "12345-1234" }
18
+ it { expect { subject }.not_to raise_error }
19
+ end
20
+
21
+ context "with a valid 5 digit zipcode" do
22
+ let(:zipcode) { "12345" }
23
+ it { expect(subject).to have(3).record }
24
+ it { expect(subject.first).to be_a_kind_of Election }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ module Google
4
+ module Civic
5
+ describe Requester do
6
+ it "includes the Router" do
7
+ expect(described_class.ancestors).to include Router
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+ require 'rspec/autorun'
4
+ require 'pry'
5
+ require 'webmock/rspec'
6
+
7
+ PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')).freeze
8
+ $LOAD_PATH << File.join(PROJECT_ROOT, 'lib')
9
+ Dir[File.join(PROJECT_ROOT, 'spec/support/**/*.rb')].each { |file| require(file) }
10
+
11
+ WebMock.disable_net_connect!(allow_localhost: true)
12
+
13
+ RSpec.configure do |config|
14
+ config.include Fixtures
15
+ config.include Requests
16
+ end
17
+
18
+ require 'google-civic'
@@ -0,0 +1,20 @@
1
+ {
2
+ "kind": "civicinfo#electionsqueryresponse",
3
+ "elections": [
4
+ {
5
+ "id": "2000",
6
+ "name": "VIP Test Election",
7
+ "electionDay": "2013-06-06"
8
+ },
9
+ {
10
+ "id": "2124",
11
+ "name": "Rhode Island 2012 Primary Election",
12
+ "electionDay": "2012-09-11"
13
+ },
14
+ {
15
+ "id": "2126",
16
+ "name": "Delaware 2012 Primary Election",
17
+ "electionDay": "2012-09-11"
18
+ }
19
+ ]
20
+ }