pupa 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 76ad0723fbc3d2027fbb020536b0afe3a0bc148e
4
- data.tar.gz: f7b89d4988aa3b244dffc777860028d12a427aa5
3
+ metadata.gz: f3539ca0b77fc4b2174c42857990638713dac180
4
+ data.tar.gz: c5a18a0390ac9a3a48e0ba868ac1dd627af0db08
5
5
  SHA512:
6
- metadata.gz: f9d15fc0fb4ce9f25217bef3df9843375d353e16b95fa2f051a61026fd2a70fc659bf59fec5bf3d2b851c0eb7e3e476c28a271213b4f0e4cbfe321ada1632d1a
7
- data.tar.gz: d2ad9277a81eaaae9c64f847608116d3164c499cbf8a06db8acb0fd0400743522ca1061e32deda9b6ac02e6888e515aac6b643d28e4efcb2bb40ea9e2e2f47d4
6
+ metadata.gz: c93da2b8ff26107c28e02e51b8ea2ec999b5e086cc8564e0af6062a58af7fe3b71429e20d26eefc57471313da578699218a4098cd35ca94eed831340f63beef1
7
+ data.tar.gz: 2444a4491a3c0b499f4dd40c4b188a72644fc4fddec941471816747bb2e694bd5b96c7d550fe4dd98ed6c477b358ade25b25cf17c3a329ca8733929f6041252c
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in the gemspec
4
4
  gemspec
5
+
6
+ gem 'faraday_middleware', git: 'https://github.com/lostisland/faraday_middleware.git'
data/PERFORMANCE.md CHANGED
@@ -1,6 +1,4 @@
1
- # Pupa.rb: A Data Scraping Framework
2
-
3
- ## Performance
1
+ # Pupa.rb: Performance
4
2
 
5
3
  Pupa.rb offers several ways to significantly improve performance.
6
4
 
@@ -8,13 +6,13 @@ In an example case, reducing disk I/O and skipping validation as described below
8
6
 
9
7
  The `import` action's performance is currently limited by the database when a dependency graph is used to determine the evaluation order. If a dependency graph cannot be used because you don't know a related object's ID, [several optimizations](https://github.com/opennorth/pupa-ruby/issues/12) can be implemented to improve performance.
10
8
 
11
- ### Reducing HTTP requests
9
+ ## Reducing HTTP requests
12
10
 
13
11
  HTTP requests consume the most time. To avoid repeat HTTP requests while developing a scraper, cache all HTTP responses. Pupa.rb will by default use a `web_cache` directory in the same directory as your script. You can change the directory by setting the `--cache_dir` switch on the command line, for example:
14
12
 
15
13
  ruby cat.rb --cache_dir /tmp/my_cache_dir
16
14
 
17
- ### Parallelizing HTTP requests
15
+ ## Parallelizing HTTP requests
18
16
 
19
17
  To enable parallel requests, use the `typhoeus` gem. Unless you are using an old version of Typhoeus (< 0.5), both Faraday and Typhoeus define a Faraday adapter, but you must use the one defined by Typhoeus, like so:
20
18
 
@@ -58,11 +56,11 @@ responses.each do |response|
58
56
  end
59
57
  ```
60
58
 
61
- ### Reducing disk I/O
59
+ ## Reducing disk I/O
62
60
 
63
61
  After HTTP requests, disk I/O is the slowest operation. Two types of files are written to disk: HTTP responses are written to the cache directory, and JSON documents are written to the output directory. Writing to memory is much faster than writing to disk.
64
62
 
65
- #### RAM file systems
63
+ ### RAM file systems
66
64
 
67
65
  A simple solution is to create a file system in RAM, like `tmpfs` on Linux for example, and to use it as your `output_dir` and `cache_dir`. On OS X, you must create a RAM disk. To create a 128MB RAM disk, for example, run:
68
66
 
@@ -80,7 +78,7 @@ Once you are done with the RAM disk, release the memory:
80
78
 
81
79
  Using a RAM disk will significantly improve performance; however, the data will be lost between reboots unless you move the data to a hard disk. Using Memcached (for caching) and Redis (for storage) is moderately faster than using a RAM disk, and Redis will not lose your output data between reboots.
82
80
 
83
- #### Memcached
81
+ ### Memcached
84
82
 
85
83
  You may cache HTTP responses in [Memcached](http://memcached.org/). First, require the `dalli` gem. Then:
86
84
 
@@ -88,7 +86,7 @@ You may cache HTTP responses in [Memcached](http://memcached.org/). First, requi
88
86
 
89
87
  The data in Memcached will be lost between reboots.
90
88
 
91
- #### Redis
89
+ ### Redis
92
90
 
93
91
  You may dump JSON documents in [Redis](http://redis.io/). First, require the `redis-store` gem. Then:
94
92
 
@@ -102,17 +100,17 @@ Requiring the `hiredis` gem will slightly improve performance.
102
100
 
103
101
  Note that Pupa.rb flushes the Redis database before scraping. If you use Redis, **DO NOT** share a Redis database with Pupa.rb and other applications. You can select a different database than the default `0` for use with Pupa.rb by passing an argument like `redis://localhost:6379/15`, where `15` is the database number.
104
102
 
105
- ### Skipping validation
103
+ ## Skipping validation
106
104
 
107
105
  The `json-schema` gem is slow compared to, for example, [JSV](https://github.com/garycourt/JSV). Setting the `--no-validate` switch and running JSON Schema validations separately can further reduce a scraper's running time.
108
106
 
109
107
  The [pupa-validate](https://npmjs.org/package/pupa-validate) npm package can be used to validate JSON documents using the faster JSV. In an example case, using JSV instead of the `json-schema` gem reduced by half the time to validate 10,000 documents.
110
108
 
111
- ### Ruby version
109
+ ## Ruby version
112
110
 
113
111
  Pupa.rb requires Ruby 2.x. If you have already made all the above optimizations, you may notice a significant improvement by using Ruby 2.1, which has better garbage collection than Ruby 2.0.
114
112
 
115
- ### Profiling
113
+ ## Profiling
116
114
 
117
115
  You can profile your code using [perftools.rb](https://github.com/tmm1/perftools.rb). First, install the gem:
118
116
 
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Pupa.rb: A Data Scraping Framework
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/pupa.svg)](http://badge.fury.io/rb/pupa)
3
4
  [![Build Status](https://secure.travis-ci.org/opennorth/pupa-ruby.png)](http://travis-ci.org/opennorth/pupa-ruby)
4
5
  [![Dependency Status](https://gemnasium.com/opennorth/pupa-ruby.png)](https://gemnasium.com/opennorth/pupa-ruby)
5
6
  [![Coverage Status](https://coveralls.io/repos/opennorth/pupa-ruby/badge.png?branch=master)](https://coveralls.io/r/opennorth/pupa-ruby)
@@ -9,27 +10,9 @@ Pupa.rb is a Ruby 2.x fork of Sunlight Labs' [Pupa](https://github.com/opencivic
9
10
 
10
11
  gem install pupa
11
12
 
12
- ## What it tries to solve
13
-
14
- Pupa.rb's goal is to make scraping less painful by solving common problems:
15
-
16
- * If you are updating a database by scraping a website, you can either delete and recreate records, or you can merge the scraped records with the saved records. Pupa.rb offers a simple way to merge records, by using an object's stable properties for identification.
17
- * If you are scraping a source that references other sources – for example, a committee that references its members – you may want to link the source to its references with foreign keys. Pupa.rb will use whatever identifying information you scrape – for example, the members' names – to fill in the foreign keys for you.
18
- * Data sources may use different formats in different contexts. Pupa.rb makes it easy to [select scraping methods](https://github.com/opennorth/pupa-ruby#scraping-method-selection) according to criteria, like the year of publication for example.
19
- * By splitting the scrape (extract) and import (load) steps, it's easier for you and volunteers to start a scraper without any interaction with a database.
20
-
21
- In short, Pupa.rb lets you spend more time on the tasks that are unique to your use case, and less time on common tasks like caching, merging and storing data. It also provides helpful features like:
22
-
23
- * Logging, to make debugging and monitoring a scraper easier
24
- * [Automatic response parsing](https://github.com/opennorth/pupa-ruby#automatic-response-parsing) of JSON, XML and HTML
25
- * Option parsing, to control your scraper from the command-line
26
- * Object validation, using [JSON Schema](http://json-schema.org/)
27
-
28
- Pupa.rb is extensible, so that you can add your own models, parsers, helpers, actions, etc. It also offers several ways to [improve your scraper's performance](https://github.com/opennorth/pupa-ruby#performance).
29
-
30
13
  ## Usage
31
14
 
32
- You can use Pupa.rb to author scrapers that create people, organizations, memberships and posts according to the [Popolo](http://popoloproject.com/) open government data specification. If you need to scrape other types of data, you can also use your own models with Pupa.rb.
15
+ You can scrape any sort of data with Pupa.rb using your own models. You can also use Pupa.rb to scrape people, organizations, memberships and posts according to the [Popolo](http://popoloproject.com/) open government data specification. This gem is up-to-date with Popolo's 2014-05-09 version, but omits the Motion, VoteEvent, Count, Vote and Area classes.
33
16
 
34
17
  The [cat.rb](http://opennorth.github.io/pupa-ruby/docs/cat.html) example shows you how to:
35
18
 
@@ -69,21 +52,21 @@ The [organization.rb](http://opennorth.github.io/pupa-ruby/docs/organization.htm
69
52
 
70
53
  JSON parsing is enabled by default. To enable automatic parsing of HTML and XML, require the `nokogiri` and `multi_xml` gems.
71
54
 
72
- ## [OpenCivicData](http://opencivicdata.org/) compatibility
73
-
74
- Both Pupa.rb and Sunlight Labs' [Pupa](https://github.com/opencivicdata/pupa) implement models for people, organizations and memberships from the [Popolo](http://popoloproject.com/) open government data specification. Pupa.rb lets you use your own classes, but Pupa only supports a fixed set of classes. A consequence of Pupa.rb's flexibility is that the value of the `_type` property for `Person`, `Organization` and `Membership` objects differs between Pupa.rb and Pupa. Pupa.rb has namespaced types like `pupa/person` – to allow Ruby to load the `Person` class in the `Pupa` module – whereas Pupa has unnamespaced types like `person`.
55
+ ### Automatic response decompression
75
56
 
76
- To save objects to MongoDB with unnamespaced types like Sunlight Labs' Pupa – in order to benefit from other tools in the [OpenCivicData](http://opencivicdata.org/) stack – add this line to the top of your script:
57
+ Until [Faraday Middleware](https://github.com/lostisland/faraday_middleware) releases its next version (> 0.9.1), you must use the gem from its git repository to automatically decompress responses:
77
58
 
78
59
  ```ruby
79
- require 'pupa/refinements/opencivicdata'
60
+ gem 'faraday_middleware', git: 'https://github.com/lostisland/faraday_middleware.git'
80
61
  ```
81
62
 
82
- It is not currently possible to run the `scrape` action with one of Pupa.rb and Pupa, and to then run the `import` action with the other. Both actions must be run by the same library.
63
+ ## Performance
64
+
65
+ Pupa.rb offers several ways to significantly improve performance. [Read the documentation.](https://github.com/opennorth/pupa-ruby/blob/master/PERFORMANCE.md#readme)
83
66
 
84
67
  ## Integration with ODMs
85
68
 
86
- `Pupa::Model` is incompatible with `Mongoid::Document`. Don't do this:
69
+ `Pupa::Model` is incompatible with `Mongoid::Document`. **Don't do this**:
87
70
 
88
71
  ```ruby
89
72
  class Cat
@@ -92,11 +75,37 @@ class Cat
92
75
  end
93
76
  ```
94
77
 
95
- Instead, have a scraping model that includes `Pupa::Model` and an app model that includes `Mongoid::Document`.
78
+ Instead, have a simple scraping model that includes `Pupa::Model` and an app model that includes `Mongoid::Document` with your app's business logic.
96
79
 
97
- ## Performance
80
+ ## What it tries to solve
98
81
 
99
- Pupa.rb offers several ways to significantly improve performance. [Read the documentation.](https://github.com/opennorth/pupa-ruby/blob/master/PERFORMANCE.md#readme)
82
+ Pupa.rb's goal is to make scraping less painful by solving common problems:
83
+
84
+ * If you are updating a database by scraping a website, you can either delete and recreate records, or you can merge the scraped records with the saved records. Pupa.rb offers a simple way to merge records, by [using an object's stable properties for identification](http://opennorth.github.io/pupa-ruby/docs/cat.html#section-7).
85
+ * If you are scraping a source that references other sources – for example, a committee that references its members – you may want to link the source to its references with foreign keys. Pupa.rb will use whatever identifying information you scrape – for example, the members' names – to [fill in the foreign keys for you](http://opennorth.github.io/pupa-ruby/docs/bill.html#section-4).
86
+ * Data sources may use different formats in different contexts. Pupa.rb makes it easy to [select scraping methods](#scraping-method-selection) according to criteria, like the year of publication [for example](http://opennorth.github.io/pupa-ruby/docs/legislator.html#section-3).
87
+ * By splitting the scrape (extract) and import (load) steps, it's easier for you and volunteers to start a scraper without any interaction with a database.
88
+
89
+ In short, Pupa.rb lets you spend more time on the tasks that are unique to your use case, and less time on common tasks like caching, merging and storing data. It also provides helpful features like:
90
+
91
+ * Logging, to make debugging and monitoring a scraper easier
92
+ * [Automatic response parsing](#automatic-response-parsing) of JSON, XML and HTML
93
+ * [Option parsing](http://opennorth.github.io/pupa-ruby/docs/legislator.html#section-9), to control your scraper from the command-line
94
+ * [Object validation](http://opennorth.github.io/pupa-ruby/docs/cat.html#section-4), using [JSON Schema](http://json-schema.org/)
95
+
96
+ Pupa.rb is extensible, so that you can add your own models, parsers, helpers, actions, etc. It also offers several ways to [improve your scraper's performance](#performance).
97
+
98
+ ## [OpenCivicData](http://opencivicdata.org/) compatibility
99
+
100
+ Both Pupa.rb and Sunlight Labs' [Pupa](https://github.com/opencivicdata/pupa) implement models for people, organizations and memberships from the [Popolo](http://popoloproject.com/) open government data specification. Pupa.rb lets you use your own classes, but Pupa only supports a fixed set of classes. A consequence of Pupa.rb's flexibility is that the value of the `_type` property for `Person`, `Organization` and `Membership` objects differs between Pupa.rb and Pupa. Pupa.rb has namespaced types like `pupa/person` – to allow Ruby to load the `Person` class in the `Pupa` module – whereas Pupa has unnamespaced types like `person`.
101
+
102
+ To save objects to MongoDB with unnamespaced types like Sunlight Labs' Pupa – in order to benefit from other tools in the [OpenCivicData](http://opencivicdata.org/) stack – add this line to the top of your script:
103
+
104
+ ```ruby
105
+ require 'pupa/refinements/opencivicdata'
106
+ ```
107
+
108
+ It is not currently possible to run the `scrape` action with one of Pupa.rb and Pupa, and to then run the `import` action with the other. Both actions must be run by the same library.
100
109
 
101
110
  ## Testing
102
111
 
@@ -0,0 +1,23 @@
1
+ module Pupa
2
+ # A geographic area whose geometry may change over time.
3
+ class Area
4
+ include Model
5
+
6
+ self.schema = 'popolo/area'
7
+
8
+ include Concerns::Timestamps
9
+ include Concerns::Sourceable
10
+
11
+ attr_accessor :name, :identifier, :classification, :parent_id, :geometry
12
+ dump :name, :identifier, :classification, :parent_id, :geometry
13
+
14
+ foreign_key :parent_id
15
+
16
+ # Returns the area's name.
17
+ #
18
+ # @return [String] the area's name
19
+ def to_s
20
+ name
21
+ end
22
+ end
23
+ end
@@ -26,11 +26,23 @@ module Pupa
26
26
  # @param [String] type a type of medium, e.g. "fax" or "email"
27
27
  # @param [String] value a value, e.g. a phone number or email address
28
28
  # @param [String] note a note, e.g. for grouping contact details by physical location
29
- def add_contact_detail(type, value, note: nil)
29
+ # @param [String] label a human-readable label for the contact detail
30
+ # @param [String,Date,Time] valid_from the date from which the contact detail is valid
31
+ # @param [String,Date,Time] valid_until the date from which the contact detail is no longer valid
32
+ def add_contact_detail(type, value, note: nil, label: nil, valid_from: nil, valid_until: nil)
30
33
  data = {type: type, value: value}
31
34
  if note
32
35
  data[:note] = note
33
36
  end
37
+ if label
38
+ data[:label] = label
39
+ end
40
+ if valid_from
41
+ data[:valid_from] = valid_from
42
+ end
43
+ if valid_until
44
+ data[:valid_until] = valid_until
45
+ end
34
46
  if type.present? && value.present?
35
47
  @contact_details << data
36
48
  end
@@ -24,10 +24,16 @@ module Pupa
24
24
  # Adds an alternate or former name.
25
25
  #
26
26
  # @param [String] name an alternate or former name
27
- # @param [Date,Time] start_date the date on which the name was adopted
28
- # @param [Date,Time] end_date the date on which the name was abandoned
27
+ # @param [String,Date,Time] start_date the date on which the name was adopted
28
+ # @param [String,Date,Time] end_date the date on which the name was abandoned
29
29
  # @param [String] note a note, e.g. "Birth name"
30
- def add_name(name, start_date: nil, end_date: nil, note: nil)
30
+ # @param [String] family_name one or more family names
31
+ # @param [String] given_name one or more primary given names
32
+ # @param [String] additional_name one or more secondary given names
33
+ # @param [String] honorific_prefix one or more honorifics preceding a person's name
34
+ # @param [String] honorific_suffix one or more honorifics following a person's name
35
+ # @param [String] patronymic_name one or more patronymic names
36
+ def add_name(name, start_date: nil, end_date: nil, note: nil, family_name: nil, given_name: nil, additional_name: nil, honorific_prefix: nil, honorific_suffix: nil, patronymic_name: nil)
31
37
  data = {name: name}
32
38
  if start_date
33
39
  data[:start_date] = start_date
@@ -38,6 +44,24 @@ module Pupa
38
44
  if note
39
45
  data[:note] = note
40
46
  end
47
+ if family_name
48
+ data[:family_name] = family_name
49
+ end
50
+ if given_name
51
+ data[:given_name] = given_name
52
+ end
53
+ if additional_name
54
+ data[:additional_name] = additional_name
55
+ end
56
+ if honorific_prefix
57
+ data[:honorific_prefix] = honorific_prefix
58
+ end
59
+ if honorific_suffix
60
+ data[:honorific_suffix] = honorific_suffix
61
+ end
62
+ if patronymic_name
63
+ data[:patronymic_name] = patronymic_name
64
+ end
41
65
  if name.present?
42
66
  @other_names << data
43
67
  end
@@ -10,12 +10,10 @@ module Pupa
10
10
  include Concerns::Contactable
11
11
  include Concerns::Linkable
12
12
 
13
- attr_accessor :label, :role, :person_id, :organization_id, :post_id,
14
- :start_date, :end_date
15
- dump :label, :role, :person_id, :organization_id, :post_id,
16
- :start_date, :end_date
13
+ attr_accessor :label, :role, :member, :person_id, :organization_id, :post_id, :on_behalf_of_id, :area_id, :start_date, :end_date
14
+ dump :label, :role, :member, :person_id, :organization_id, :post_id, :on_behalf_of_id, :area_id, :start_date, :end_date
17
15
 
18
- foreign_key :person_id, :organization_id, :post_id
16
+ foreign_key :person_id, :organization_id, :post_id, :on_behalf_of_id, :area_id
19
17
 
20
18
  # Returns the IDs of the parties to the relationship.
21
19
  #
@@ -0,0 +1,23 @@
1
+ module Pupa
2
+ # A formal step to introduce a matter for consideration by an organization.
3
+ class Motion
4
+ include Model
5
+
6
+ self.schema = 'popolo/motion'
7
+
8
+ include Concerns::Timestamps
9
+ include Concerns::Sourceable
10
+
11
+ attr_accessor :organization_id, :legislative_session_id, :creator_id, :text, :classification, :date, :requirement, :result
12
+ dump :organization_id, :legislative_session_id, :creator_id, :text, :classification, :date, :requirement, :result
13
+
14
+ foreign_key :organization_id, :legislative_session_id, :creator_id
15
+
16
+ # Returns the motion's text and organization ID.
17
+ #
18
+ # @return [String] the motion's text and organization ID
19
+ def to_s
20
+ "#{text} in #{organization_id}"
21
+ end
22
+ end
23
+ end
@@ -13,14 +13,12 @@ module Pupa
13
13
  include Concerns::Contactable
14
14
  include Concerns::Linkable
15
15
 
16
- attr_accessor :name, :classification, :parent_id, :parent, :founding_date,
17
- :dissolution_date, :image
18
- dump :name, :classification, :parent_id, :parent, :founding_date,
19
- :dissolution_date, :image
16
+ attr_accessor :name, :classification, :parent_id, :area_id, :founding_date, :dissolution_date, :image, :parent
17
+ dump :name, :classification, :parent_id, :area_id, :founding_date, :dissolution_date, :image, :parent
20
18
 
21
- foreign_key :parent_id
19
+ foreign_key :parent_id, :area_id
22
20
 
23
- foreign_object :parent
21
+ foreign_object :parent # for testing
24
22
 
25
23
  # Returns the name of the organization.
26
24
  #
@@ -12,12 +12,10 @@ module Pupa
12
12
  include Concerns::Contactable
13
13
  include Concerns::Linkable
14
14
 
15
- attr_accessor :name, :family_name, :given_name, :additional_name,
16
- :honorific_prefix, :honorific_suffix, :patronymic_name, :sort_name,
17
- :email, :gender, :birth_date, :death_date, :image, :summary, :biography
18
- dump :name, :family_name, :given_name, :additional_name,
19
- :honorific_prefix, :honorific_suffix, :patronymic_name, :sort_name,
20
- :email, :gender, :birth_date, :death_date, :image, :summary, :biography
15
+ attr_accessor :name, :email, :gender, :birth_date, :death_date, :image, :summary, :biography, :national_identity,
16
+ :family_name, :given_name, :additional_name, :honorific_prefix, :honorific_suffix, :patronymic_name, :sort_name
17
+ dump :name, :email, :gender, :birth_date, :death_date, :image, :summary, :biography, :national_identity,
18
+ :family_name, :given_name, :additional_name, :honorific_prefix, :honorific_suffix, :patronymic_name, :sort_name
21
19
 
22
20
  # Returns the person's name.
23
21
  #
@@ -10,16 +10,16 @@ module Pupa
10
10
  include Concerns::Contactable
11
11
  include Concerns::Linkable
12
12
 
13
- attr_accessor :label, :role, :organization_id, :start_date, :end_date
14
- dump :label, :role, :organization_id, :start_date, :end_date
13
+ attr_accessor :label, :other_label, :role, :organization_id, :area_id, :start_date, :end_date
14
+ dump :label, :other_label, :role, :organization_id, :area_id, :start_date, :end_date
15
15
 
16
- foreign_key :organization_id
16
+ foreign_key :organization_id, :area_id
17
17
 
18
- # Returns the post's label and organization ID.
18
+ # Returns the post's label or role and organization ID.
19
19
  #
20
- # @return [String] the post's label and organization ID
20
+ # @return [String] the post's label or role and organization ID
21
21
  def to_s
22
- "#{label} in #{organization_id}"
22
+ "#{label || role} in #{organization_id}"
23
23
  end
24
24
 
25
25
  # A post should have a unique label within an organization, through it may
@@ -0,0 +1,23 @@
1
+ module Pupa
2
+ # A voter's vote in a vote event.
3
+ class Vote
4
+ include Model
5
+
6
+ self.schema = 'popolo/vote'
7
+
8
+ include Concerns::Timestamps
9
+ include Concerns::Sourceable
10
+
11
+ attr_accessor :vote_event_id, :voter_id, :option, :group_id, :role, :weight, :pair_id
12
+ dump :vote_event_id, :voter_id, :option, :group_id, :role, :weight, :pair_id
13
+
14
+ foreign_key :vote_event_id, :voter_id, :group_id, :pair_id
15
+
16
+ # Returns the vote's option, voter ID and vote event ID.
17
+ #
18
+ # @return [String] the vote's option, voter ID and vote event ID
19
+ def to_s
20
+ "#{option} by #{voter_id} in #{vote_event_id}"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,72 @@
1
+ module Pupa
2
+ # An event at which people's votes are recorded.
3
+ class VoteEvent
4
+ include Model
5
+
6
+ self.schema = 'popolo/vote_event'
7
+
8
+ include Concerns::Timestamps
9
+ include Concerns::Sourceable
10
+
11
+ attr_accessor :identifier, :motion_id, :organization_id, :legislative_session_id, :start_date, :end_date, :result, :group_results, :counts
12
+ dump :identifier, :motion_id, :organization_id, :legislative_session_id, :start_date, :end_date, :result, :group_results, :counts
13
+
14
+ foreign_key :motion_id, :organization_id, :legislative_session_id
15
+
16
+ def initialize(*args)
17
+ @group_results = []
18
+ @counts = []
19
+ super
20
+ end
21
+
22
+ # Returns the vote event's identifier and organization ID.
23
+ #
24
+ # @return [String] the vote event's identifier and organization ID
25
+ def to_s
26
+ "#{identifier} in #{organization_id}"
27
+ end
28
+
29
+ # Sets the group results.
30
+ #
31
+ # @param [Array] group_results a list of group results
32
+ def group_results=(group_results)
33
+ @group_results = symbolize_keys(group_results)
34
+ end
35
+
36
+ # Sets the counts.
37
+ #
38
+ # @param [Array] counts a list of counts
39
+ def counts=(counts)
40
+ @counts = symbolize_keys(counts)
41
+ end
42
+
43
+ # Adds a group result.
44
+ #
45
+ # @param [String] result the result of the vote event within a group of voters
46
+ # @param [String] group a group of voters
47
+ def add_group_result(result, group: nil)
48
+ data = {result: result}
49
+ if group
50
+ data[:group] = group
51
+ end
52
+ if result.present?
53
+ @group_results << data
54
+ end
55
+ end
56
+
57
+ # Adds a count.
58
+ #
59
+ # @param [String] option an option in a vote event
60
+ # @param [String] value the number of votes for an option
61
+ # @param [String] group a group of voters
62
+ def add_count(option, value, group: nil)
63
+ data = {option: option, value: value}
64
+ if group
65
+ data[:group] = group
66
+ end
67
+ if option.present? && value.present?
68
+ @counts << data
69
+ end
70
+ end
71
+ end
72
+ end
@@ -2,11 +2,9 @@ require 'active_support/cache'
2
2
  require 'faraday_middleware'
3
3
  require 'faraday_middleware/response_middleware'
4
4
 
5
- require 'pupa/processor/middleware/gzip'
6
5
  require 'pupa/processor/middleware/logger'
7
6
  require 'pupa/processor/middleware/parse_html'
8
7
  require 'pupa/processor/middleware/parse_json'
9
- require 'pupa/processor/middleware/raise_error'
10
8
  require 'pupa/refinements/faraday'
11
9
  require 'pupa/refinements/faraday_middleware'
12
10
 
@@ -39,7 +37,7 @@ module Pupa
39
37
  Faraday.new do |connection|
40
38
  connection.request :url_encoded
41
39
  connection.use Middleware::Logger, Logger.new('faraday', level: level)
42
- connection.use Middleware::RaiseError # useful for breaking concurrent requests
40
+ connection.use Faraday::Response::RaiseError
43
41
 
44
42
  # @see http://tools.ietf.org/html/rfc4627
45
43
  connection.use Middleware::ParseJson, preserve_raw: true, content_type: /\bjson$/
@@ -56,7 +54,9 @@ module Pupa
56
54
  end
57
55
 
58
56
  # Must come after the parser middlewares.
59
- connection.use Middleware::Gzip
57
+ if FaradayMiddleware.const_defined?(:Gzip)
58
+ connection.use FaradayMiddleware::Gzip
59
+ end
60
60
 
61
61
  if cache_dir
62
62
  connection.response :caching do
data/lib/pupa/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Pupa
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.8"
3
3
  end
data/lib/pupa.rb CHANGED
@@ -26,10 +26,14 @@ require 'pupa/models/foreign_object'
26
26
  require 'pupa/models/model'
27
27
  require 'pupa/models/contact_detail_list'
28
28
  require 'pupa/models/identifier_list'
29
+ require 'pupa/models/area'
29
30
  require 'pupa/models/membership'
31
+ require 'pupa/models/motion'
30
32
  require 'pupa/models/organization'
31
33
  require 'pupa/models/person'
32
34
  require 'pupa/models/post'
35
+ require 'pupa/models/vote'
36
+ require 'pupa/models/vote_event'
33
37
 
34
38
  module Pupa
35
39
  end
@@ -0,0 +1,54 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "id": "http://popoloproject.com/schemas/area.json#",
4
+ "title": "Area",
5
+ "description": "A geographic area whose geometry may change over time",
6
+ "type": "object",
7
+ "properties": {
8
+ "id": {
9
+ "description": "The area's unique identifier",
10
+ "type": ["string", "null"]
11
+ },
12
+ "name": {
13
+ "description": "A primary name",
14
+ "type": ["string", "null"]
15
+ },
16
+ "identifier": {
17
+ "description": "An issued identifier",
18
+ "type": ["string", "null"]
19
+ },
20
+ "classification": {
21
+ "description": "An area category, e.g. city",
22
+ "type": ["string", "null"]
23
+ },
24
+ "parent_id": {
25
+ "description": "The ID of the area that contains this area",
26
+ "type": ["string", "null"]
27
+ },
28
+ "parent": {
29
+ "description": "The area that contains this area",
30
+ "$ref": "http://popoloproject.com/schemas/area.json#"
31
+ },
32
+ "geometry": {
33
+ "description": "A geometry",
34
+ "type": ["object", "null"]
35
+ },
36
+ "created_at": {
37
+ "description": "The time at which the resource was created",
38
+ "type": ["string", "null"],
39
+ "format": "date-time"
40
+ },
41
+ "updated_at": {
42
+ "description": "The time at which the resource was last modified",
43
+ "type": ["string", "null"],
44
+ "format": "date-time"
45
+ },
46
+ "sources": {
47
+ "description": "URLs to documents from which the area is derived",
48
+ "type": "array",
49
+ "items": {
50
+ "$ref": "http://popoloproject.com/schemas/link.json#"
51
+ }
52
+ }
53
+ }
54
+ }
@@ -28,7 +28,7 @@
28
28
  "type": ["string", "null"],
29
29
  "pattern": "^[0-9]{4}(-[0-9]{2}){0,2}$"
30
30
  },
31
- "valid_through": {
31
+ "valid_until": {
32
32
  "description": "The date from which the contact detail is no longer valid",
33
33
  "type": ["string", "null"],
34
34
  "pattern": "^[0-9]{4}(-[0-9]{2}){0,2}$"
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "id": "http://popoloproject.com/schemas/count.json#",
4
+ "title": "Count",
5
+ "description": "The number of votes for an option in a vote event",
6
+ "type": "object",
7
+ "properties": {
8
+ "option": {
9
+ "description": "An option in a vote event",
10
+ "type": "string",
11
+ "required": true
12
+ },
13
+ "value": {
14
+ "description": "The number of votes for an option",
15
+ "type": "integer",
16
+ "required": true
17
+ },
18
+ "group_id": {
19
+ "description": "The ID of a group of voters",
20
+ "type": ["string", "null"]
21
+ },
22
+ "group": {
23
+ "description": "A group of voters",
24
+ "type": ["object", "null"]
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "id": "http://popoloproject.com/schemas/group_result.json#",
4
+ "title": "Group result",
5
+ "description": "A result of a vote event within a group of voters",
6
+ "type": "object",
7
+ "properties": {
8
+ "group_id": {
9
+ "description": "The ID of a group of voters",
10
+ "type": ["string", "null"]
11
+ },
12
+ "group": {
13
+ "description": "A group of voters",
14
+ "type": ["object", "null"]
15
+ },
16
+ "result": {
17
+ "description": "The result of the vote event within a group of voters",
18
+ "type": "string",
19
+ "required": true
20
+ }
21
+ }
22
+ }
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "member": {
21
21
  "description": "The person or organization that is a member of the organization",
22
- "type": ["object"]
22
+ "type": ["object", "null"]
23
23
  },
24
24
  "person_id": {
25
25
  "description": "The ID of the person who is a member of the organization",
@@ -0,0 +1,82 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "id": "http://popoloproject.com/schemas/motion.json#",
4
+ "title": "Motion",
5
+ "description": "A formal step to introduce a matter for consideration by an organization",
6
+ "type": "object",
7
+ "properties": {
8
+ "id": {
9
+ "description": "The motion's unique identifier",
10
+ "type": ["string", "null"]
11
+ },
12
+ "organization_id": {
13
+ "description": "The ID of the organization in which the motion is proposed",
14
+ "type": ["string", "null"]
15
+ },
16
+ "organization": {
17
+ "description": "The organization in which the motion is proposed",
18
+ "$ref": "http://popoloproject.com/schemas/organization.json#"
19
+ },
20
+ "legislative_session_id": {
21
+ "description": "The ID of the legislative session in which the motion is proposed",
22
+ "type": ["string", "null"]
23
+ },
24
+ "legislative_session": {
25
+ "description": "The legislative session in which the motion is proposed",
26
+ "type": ["object", "null"]
27
+ },
28
+ "creator_id": {
29
+ "description": "The ID of the person who proposed the motion",
30
+ "type": ["string", "null"]
31
+ },
32
+ "creator": {
33
+ "description": "The person who proposed the motion",
34
+ "$ref": "http://popoloproject.com/schemas/person.json#"
35
+ },
36
+ "text": {
37
+ "description": "The transcript or text of the motion",
38
+ "type": ["string", "null"]
39
+ },
40
+ "classification": {
41
+ "description": "A motion category, e.g. adjournment",
42
+ "type": ["string", "null"]
43
+ },
44
+ "date": {
45
+ "description": "The date on which the motion was proposed",
46
+ "type": ["string", "null"],
47
+ "format": "date-time"
48
+ },
49
+ "requirement": {
50
+ "description": "The requirement for the motion to be adopted",
51
+ "type": ["string", "null"]
52
+ },
53
+ "result": {
54
+ "description": "The result of the motion",
55
+ "type": ["string", "null"]
56
+ },
57
+ "vote_events": {
58
+ "description": "Events at which people vote on the motion",
59
+ "type": "array",
60
+ "items": {
61
+ "$ref": "http://popoloproject.com/schemas/vote_event.json#"
62
+ }
63
+ },
64
+ "created_at": {
65
+ "description": "The time at which the resource was created",
66
+ "type": ["string", "null"],
67
+ "format": "date-time"
68
+ },
69
+ "updated_at": {
70
+ "description": "The time at which the resource was last modified",
71
+ "type": ["string", "null"],
72
+ "format": "date-time"
73
+ },
74
+ "sources": {
75
+ "description": "URLs to documents from which the motion is derived",
76
+ "type": "array",
77
+ "items": {
78
+ "$ref": "http://popoloproject.com/schemas/link.json#"
79
+ }
80
+ }
81
+ }
82
+ }
@@ -77,7 +77,7 @@
77
77
  }
78
78
  },
79
79
  "memberships": {
80
- "description": "The relationships to which the organization is a party",
80
+ "description": "Memberships",
81
81
  "type": "array",
82
82
  "items": {
83
83
  "$ref": "http://popoloproject.com/schemas/membership.json#"
@@ -106,7 +106,7 @@
106
106
  }
107
107
  },
108
108
  "memberships": {
109
- "description": "The relationships to which the person is a party",
109
+ "description": "Memberships",
110
110
  "type": "array",
111
111
  "items": {
112
112
  "$ref": "http://popoloproject.com/schemas/membership.json#"
@@ -0,0 +1,57 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "id": "http://popoloproject.com/schemas/vote.json#",
4
+ "title": "Vote",
5
+ "description": "A voter's vote in a vote event",
6
+ "type": "object",
7
+ "properties": {
8
+ "id": {
9
+ "description": "The vote's unique identifier",
10
+ "type": ["string", "null"]
11
+ },
12
+ "vote_event_id": {
13
+ "description": "The ID of a vote event",
14
+ "type": ["string", "null"]
15
+ },
16
+ "vote_event": {
17
+ "description": "A vote event",
18
+ "$ref": "http://popoloproject.com/schemas/vote_event.json#"
19
+ },
20
+ "voter_id": {
21
+ "description": "The ID of the person or organization that is voting",
22
+ "type": ["string", "null"]
23
+ },
24
+ "voter": {
25
+ "description": "The person or organization that is voting",
26
+ "type": ["object", "null"]
27
+ },
28
+ "option": {
29
+ "description": "The option chosen by the voter, whether actively or passively",
30
+ "type": ["string", "null"]
31
+ },
32
+ "group_id": {
33
+ "description": "The ID of the voter's primary political group",
34
+ "type": ["string", "null"]
35
+ },
36
+ "group": {
37
+ "description": "The voter's primary political group",
38
+ "$ref": "http://popoloproject.com/schemas/organization.json#"
39
+ },
40
+ "role": {
41
+ "description": "The voter's role in the event",
42
+ "type": ["string", "null"]
43
+ },
44
+ "weight": {
45
+ "description": "The weight of the voter's vote",
46
+ "type": ["number", "null"]
47
+ },
48
+ "pair_id": {
49
+ "description": "The ID of the person with whom the voter is paired",
50
+ "type": ["string", "null"]
51
+ },
52
+ "pair": {
53
+ "description": "The person with whom the voter is paired",
54
+ "$ref": "http://popoloproject.com/schemas/person.json#"
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,93 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "id": "http://popoloproject.com/schemas/vote_event.json#",
4
+ "title": "Vote event",
5
+ "description": "An event at which people's votes are recorded",
6
+ "type": "object",
7
+ "properties": {
8
+ "id": {
9
+ "description": "The vote event's unique identifier",
10
+ "type": ["string", "null"]
11
+ },
12
+ "identifier": {
13
+ "description": "An issued identifier",
14
+ "type": ["string", "null"]
15
+ },
16
+ "motion_id": {
17
+ "description": "The ID of the motion being decided",
18
+ "type": ["string", "null"]
19
+ },
20
+ "motion": {
21
+ "description": "The motion being decided",
22
+ "$ref": "http://popoloproject.com/schemas/motion.json#"
23
+ },
24
+ "organization_id": {
25
+ "description": "The ID of the organization whose members are voting",
26
+ "type": ["string", "null"]
27
+ },
28
+ "organization": {
29
+ "description": "The organization whose members are voting",
30
+ "$ref": "http://popoloproject.com/schemas/organization.json#"
31
+ },
32
+ "legislative_session_id": {
33
+ "description": "The ID of the legislative session in which the vote occurs",
34
+ "type": ["string", "null"]
35
+ },
36
+ "legislative_session": {
37
+ "description": "The legislative session in which the vote occurs",
38
+ "type": ["object", "null"]
39
+ },
40
+ "start_date": {
41
+ "description": "The time at which the event begins",
42
+ "type": ["string", "null"],
43
+ "format": "date-time"
44
+ },
45
+ "end_date": {
46
+ "description": "The time at which the event ends",
47
+ "type": ["string", "null"],
48
+ "format": "date-time"
49
+ },
50
+ "result": {
51
+ "description": "The result of the vote event",
52
+ "type": ["string", "null"]
53
+ },
54
+ "group_results": {
55
+ "description": "The result of the vote event within groups of voters",
56
+ "type": "array",
57
+ "items": {
58
+ "$ref": "http://popoloproject.com/schemas/group_result.json#"
59
+ }
60
+ },
61
+ "counts": {
62
+ "description": "The number of votes for options",
63
+ "type": "array",
64
+ "items": {
65
+ "$ref": "http://popoloproject.com/schemas/count.json#"
66
+ }
67
+ },
68
+ "votes": {
69
+ "description": "Voters' votes",
70
+ "type": "array",
71
+ "items": {
72
+ "$ref": "http://popoloproject.com/schemas/vote.json#"
73
+ }
74
+ },
75
+ "created_at": {
76
+ "description": "The time at which the resource was created",
77
+ "type": ["string", "null"],
78
+ "format": "date-time"
79
+ },
80
+ "updated_at": {
81
+ "description": "The time at which the resource was last modified",
82
+ "type": ["string", "null"],
83
+ "format": "date-time"
84
+ },
85
+ "sources": {
86
+ "description": "URLs to documents from which the vote event is derived",
87
+ "type": "array",
88
+ "items": {
89
+ "$ref": "http://popoloproject.com/schemas/link.json#"
90
+ }
91
+ }
92
+ }
93
+ }
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Pupa::Area do
4
+ let :object do
5
+ Pupa::Area.new(name: 'Boston Ward 1')
6
+ end
7
+
8
+ describe '#to_s' do
9
+ it 'should return a human-readable string' do
10
+ object.to_s.should == 'Boston Ward 1'
11
+ end
12
+ end
13
+ end
@@ -31,15 +31,15 @@ describe Pupa::Concerns::Contactable do
31
31
  end
32
32
 
33
33
  it 'should symbolize keys' do
34
- object.contact_details = [{'type' => 'email', 'value' => 'ceo@example.com', 'note' => 'work'}]
35
- object.contact_details.should == [{type: 'email', value: 'ceo@example.com', note: 'work'}]
34
+ object.contact_details = [{'type' => 'email', 'value' => 'ceo@example.com'}]
35
+ object.contact_details.should == [{type: 'email', value: 'ceo@example.com'}]
36
36
  end
37
37
  end
38
38
 
39
39
  describe '#add_contact_detail' do
40
40
  it 'should add a contact detail' do
41
- object.add_contact_detail('email', 'ceo@example.com', note: 'work')
42
- object.contact_details.should == [{type: 'email', value: 'ceo@example.com', note: 'work'}]
41
+ object.add_contact_detail('email', 'ceo@example.com', label: 'Email', note: 'work', valid_from: '2010-01-01', valid_until: '2010-12-31')
42
+ object.contact_details.should == [{type: 'email', value: 'ceo@example.com', label: 'Email', note: 'work', valid_from: '2010-01-01', valid_until: '2010-12-31'}]
43
43
  end
44
44
 
45
45
  it 'should not add a contact detail without a type' do
@@ -14,15 +14,15 @@ describe Pupa::Concerns::Nameable do
14
14
 
15
15
  describe '#other_names' do
16
16
  it 'should symbolize keys' do
17
- object.other_names = [{'name' => 'Mr. Ziggy Q. Public, Esq.', 'start_date' => '1920-01', 'end_date' => '1949-12-31', 'note' => 'Birth name'}]
18
- object.other_names.should == [{name: 'Mr. Ziggy Q. Public, Esq.', start_date: '1920-01', end_date: '1949-12-31', note: 'Birth name'}]
17
+ object.other_names = [{'name' => 'Mr. Ziggy Q. Public, Esq.', 'note' => 'Birth name'}]
18
+ object.other_names.should == [{name: 'Mr. Ziggy Q. Public, Esq.', note: 'Birth name'}]
19
19
  end
20
20
  end
21
21
 
22
22
  describe '#add_name' do
23
23
  it 'should add a name' do
24
- object.add_name('Mr. Ziggy Q. Public, Esq.', start_date: '1920-01', end_date: '1949-12-31', note: 'Birth name')
25
- object.other_names.should == [{name: 'Mr. Ziggy Q. Public, Esq.', start_date: '1920-01', end_date: '1949-12-31', note: 'Birth name'}]
24
+ object.add_name('Mr. Ziggy Q. Public, Esq.', start_date: '1920-01', end_date: '1949-12-31', note: 'Birth name', family_name: 'Public', given_name: 'John', additional_name: 'Quinlan', honorific_prefix: 'Mr.', honorific_suffix: 'Esq.')
25
+ object.other_names.should == [{name: 'Mr. Ziggy Q. Public, Esq.', start_date: '1920-01', end_date: '1949-12-31', note: 'Birth name', family_name: 'Public', given_name: 'John', additional_name: 'Quinlan', honorific_prefix: 'Mr.', honorific_suffix: 'Esq.'}]
26
26
  end
27
27
 
28
28
  it 'should not add a name without a name' do
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Pupa::Motion do
4
+ let :object do
5
+ Pupa::Motion.new(text: 'That the Bill is to be read a second time.', organization_id: 'house-of-commons')
6
+ end
7
+
8
+ describe '#to_s' do
9
+ it 'should return a human-readable string' do
10
+ object.to_s.should == 'That the Bill is to be read a second time. in house-of-commons'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,59 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Pupa::VoteEvent do
4
+ let :object do
5
+ Pupa::VoteEvent.new(identifier: '1', organization_id: 'legislative-council-of-hong-kong')
6
+ end
7
+
8
+ describe '#to_s' do
9
+ it 'should return a human-readable string' do
10
+ object.to_s.should == '1 in legislative-council-of-hong-kong'
11
+ end
12
+ end
13
+
14
+ describe '#group_results' do
15
+ it 'should symbolize keys' do
16
+ object.group_results = [{'result' => 'pass', 'group' => {'name' => 'Functional constituencies'}}]
17
+ object.group_results.should == [{result: 'pass', group: {name: 'Functional constituencies'}}]
18
+ end
19
+ end
20
+
21
+ describe '#add_group_result' do
22
+ it 'should add a group result' do
23
+ object.add_group_result('pass', group: {name: 'Functional constituencies'})
24
+ object.group_results.should == [{result: 'pass', group: {name: 'Functional constituencies'}}]
25
+ end
26
+
27
+ it 'should not add a group result without a result' do
28
+ object.add_group_result(nil)
29
+ object.add_group_result('')
30
+ object.group_results.blank?.should == true
31
+ end
32
+ end
33
+
34
+ describe '#counts' do
35
+ it 'should symbolize keys' do
36
+ object.counts = [{'option' => 'yes', 'value' => 9, 'group' => {'name' => 'Functional constituencies'}}]
37
+ object.counts.should == [{option: 'yes', value: 9, group: {name: 'Functional constituencies'}}]
38
+ end
39
+ end
40
+
41
+ describe '#add_count' do
42
+ it 'should add a count' do
43
+ object.add_count('yes', 9, group: {name: 'Functional constituencies'})
44
+ object.counts.should == [{option: 'yes', value: 9, group: {name: 'Functional constituencies'}}]
45
+ end
46
+
47
+ it 'should not add a contact detail without an option' do
48
+ object.add_count(nil, 9)
49
+ object.add_count('', 9)
50
+ object.counts.blank?.should == true
51
+ end
52
+
53
+ it 'should not add a contact detail without a value' do
54
+ object.add_count('yes', nil)
55
+ object.add_count('yes', '')
56
+ object.counts.blank?.should == true
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Pupa::Vote do
4
+ let :object do
5
+ Pupa::Vote.new(option: 'yes', voter_id: 'john-q-public', vote_event_id: 'vote-42')
6
+ end
7
+
8
+ describe '#to_s' do
9
+ it 'should return a human-readable string' do
10
+ object.to_s.should == 'yes by john-q-public in vote-42'
11
+ end
12
+ end
13
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pupa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Open North
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-14 00:00:00.000000000 Z
11
+ date: 2014-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -295,6 +295,7 @@ files:
295
295
  - lib/pupa.rb
296
296
  - lib/pupa/errors.rb
297
297
  - lib/pupa/logger.rb
298
+ - lib/pupa/models/area.rb
298
299
  - lib/pupa/models/concerns/contactable.rb
299
300
  - lib/pupa/models/concerns/identifiable.rb
300
301
  - lib/pupa/models/concerns/indifferent_access.rb
@@ -307,9 +308,12 @@ files:
307
308
  - lib/pupa/models/identifier_list.rb
308
309
  - lib/pupa/models/membership.rb
309
310
  - lib/pupa/models/model.rb
311
+ - lib/pupa/models/motion.rb
310
312
  - lib/pupa/models/organization.rb
311
313
  - lib/pupa/models/person.rb
312
314
  - lib/pupa/models/post.rb
315
+ - lib/pupa/models/vote.rb
316
+ - lib/pupa/models/vote_event.rb
313
317
  - lib/pupa/processor.rb
314
318
  - lib/pupa/processor/client.rb
315
319
  - lib/pupa/processor/connection.rb
@@ -320,11 +324,9 @@ files:
320
324
  - lib/pupa/processor/document_store/file_store.rb
321
325
  - lib/pupa/processor/document_store/redis_store.rb
322
326
  - lib/pupa/processor/helper.rb
323
- - lib/pupa/processor/middleware/gzip.rb
324
327
  - lib/pupa/processor/middleware/logger.rb
325
328
  - lib/pupa/processor/middleware/parse_html.rb
326
329
  - lib/pupa/processor/middleware/parse_json.rb
327
- - lib/pupa/processor/middleware/raise_error.rb
328
330
  - lib/pupa/processor/yielder.rb
329
331
  - lib/pupa/refinements/faraday.rb
330
332
  - lib/pupa/refinements/faraday_middleware.rb
@@ -333,18 +335,25 @@ files:
333
335
  - lib/pupa/runner.rb
334
336
  - lib/pupa/version.rb
335
337
  - pupa.gemspec
338
+ - schemas/popolo/area.json
336
339
  - schemas/popolo/contact_detail.json
340
+ - schemas/popolo/count.json
341
+ - schemas/popolo/group_result.json
337
342
  - schemas/popolo/identifier.json
338
343
  - schemas/popolo/link.json
339
344
  - schemas/popolo/membership.json
345
+ - schemas/popolo/motion.json
340
346
  - schemas/popolo/organization.json
341
347
  - schemas/popolo/other_name.json
342
348
  - schemas/popolo/person.json
343
349
  - schemas/popolo/post.json
350
+ - schemas/popolo/vote.json
351
+ - schemas/popolo/vote_event.json
344
352
  - spec/fixtures/bar.json
345
353
  - spec/fixtures/baz.json
346
354
  - spec/fixtures/foo.json
347
355
  - spec/logger_spec.rb
356
+ - spec/models/area_spec.rb
348
357
  - spec/models/concerns/contactable_spec.rb
349
358
  - spec/models/concerns/identifiable_spec.rb
350
359
  - spec/models/concerns/linkable_spec.rb
@@ -355,9 +364,12 @@ files:
355
364
  - spec/models/identifier_list_spec.rb
356
365
  - spec/models/membership_spec.rb
357
366
  - spec/models/model_spec.rb
367
+ - spec/models/motion_spec.rb
358
368
  - spec/models/organization_spec.rb
359
369
  - spec/models/person_spec.rb
360
370
  - spec/models/post_spec.rb
371
+ - spec/models/vote_event_spec.rb
372
+ - spec/models/vote_spec.rb
361
373
  - spec/processor/client_spec.rb
362
374
  - spec/processor/connection_adapters/mongodb_adapter_spec.rb
363
375
  - spec/processor/connection_adapters/postgresql_adapter_spec.rb
@@ -404,6 +416,7 @@ test_files:
404
416
  - spec/fixtures/baz.json
405
417
  - spec/fixtures/foo.json
406
418
  - spec/logger_spec.rb
419
+ - spec/models/area_spec.rb
407
420
  - spec/models/concerns/contactable_spec.rb
408
421
  - spec/models/concerns/identifiable_spec.rb
409
422
  - spec/models/concerns/linkable_spec.rb
@@ -414,9 +427,12 @@ test_files:
414
427
  - spec/models/identifier_list_spec.rb
415
428
  - spec/models/membership_spec.rb
416
429
  - spec/models/model_spec.rb
430
+ - spec/models/motion_spec.rb
417
431
  - spec/models/organization_spec.rb
418
432
  - spec/models/person_spec.rb
419
433
  - spec/models/post_spec.rb
434
+ - spec/models/vote_event_spec.rb
435
+ - spec/models/vote_spec.rb
420
436
  - spec/processor/client_spec.rb
421
437
  - spec/processor/connection_adapters/mongodb_adapter_spec.rb
422
438
  - spec/processor/connection_adapters/postgresql_adapter_spec.rb
@@ -434,3 +450,4 @@ test_files:
434
450
  - spec/refinements/opencivicdata_spec.rb
435
451
  - spec/runner_spec.rb
436
452
  - spec/spec_helper.rb
453
+ has_rdoc:
@@ -1,24 +0,0 @@
1
- module Pupa
2
- class Processor
3
- module Middleware
4
- # A Faraday response middleware for parsing gzip responses.
5
- #
6
- # @see https://gist.github.com/romanbsd/3892387
7
- class Gzip < Faraday::Response::Middleware
8
- dependency 'zlib'
9
-
10
- def on_complete(env)
11
- encoding = env[:response_headers]['content-encoding'].to_s.downcase
12
- case encoding
13
- when 'gzip'
14
- env[:body] = Zlib::GzipReader.new(StringIO.new(env[:body]), encoding: 'ASCII-8BIT').read
15
- env[:response_headers].delete('content-encoding')
16
- when 'deflate'
17
- env[:body] = Zlib::Inflate.inflate(env[:body])
18
- env[:response_headers].delete('content-encoding')
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,34 +0,0 @@
1
- module Pupa
2
- class Processor
3
- module Middleware
4
- # A Faraday response middleware for raising an error if unsuccessful.
5
- #
6
- # @see Faraday::Response::RaiseError
7
- # @note Faraday has no tests for this middleware.
8
- class RaiseError < Faraday::Response::Middleware
9
- def on_complete(env)
10
- case env[:status]
11
- when 404
12
- raise Faraday::Error::ResourceNotFound, response_values(env)
13
- when 407
14
- # mimic the behavior that we get with proxy requests with HTTPS
15
- raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
16
- when 400...600
17
- raise Faraday::Error::ClientError, response_values(env)
18
- end
19
- end
20
-
21
- def response_values(env) # XXX add more keys
22
- {
23
- method: env[:method],
24
- url: env[:url].to_s,
25
- request_headers: env[:request_headers],
26
- status: env[:status],
27
- response_headers: env[:response_headers],
28
- body: env[:body].to_s,
29
- }
30
- end
31
- end
32
- end
33
- end
34
- end