popolo 0.0.1
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.
- data/LICENSE +20 -0
- data/README.md +41 -0
- data/Rakefile +16 -0
- data/app/assets/javascripts/popolo/application.js +13 -0
- data/app/assets/stylesheets/popolo/application.css +13 -0
- data/app/controllers/popolo/areas_controller.rb +48 -0
- data/app/controllers/popolo/organizations_controller.rb +48 -0
- data/app/controllers/popolo/people_controller.rb +12 -0
- data/app/controllers/popolo/posts_controller.rb +12 -0
- data/app/controllers/popolo_controller.rb +3 -0
- data/app/helpers/popolo_helper.rb +10 -0
- data/app/models/popolo/address.rb +27 -0
- data/app/models/popolo/area.rb +25 -0
- data/app/models/popolo/event.rb +46 -0
- data/app/models/popolo/identifier.rb +15 -0
- data/app/models/popolo/link.rb +16 -0
- data/app/models/popolo/membership.rb +25 -0
- data/app/models/popolo/organization.rb +32 -0
- data/app/models/popolo/other_name.rb +21 -0
- data/app/models/popolo/person.rb +49 -0
- data/app/models/popolo/post.rb +25 -0
- data/app/models/popolo/source.rb +29 -0
- data/app/views/popolo/areas/index.html.erb +1 -0
- data/app/views/popolo/areas/show.html.erb +1 -0
- data/app/views/popolo/areas_or_organizations/_index.html.erb +31 -0
- data/app/views/popolo/areas_or_organizations/_show.html.erb +30 -0
- data/app/views/popolo/organizations/index.html.erb +1 -0
- data/app/views/popolo/organizations/show.html.erb +1 -0
- data/app/views/popolo/people/index.html.erb +0 -0
- data/app/views/popolo/people/show.html.erb +0 -0
- data/app/views/popolo/posts/index.html.erb +0 -0
- data/app/views/popolo/posts/show.html.erb +0 -0
- data/config/routes.rb +15 -0
- data/lib/generators/popolo_generator.rb +36 -0
- data/lib/generators/templates/README +7 -0
- data/lib/popolo/engine.rb +7 -0
- data/lib/popolo/mixins/eventable.rb +15 -0
- data/lib/popolo/mixins/sluggable.rb +64 -0
- data/lib/popolo/version.rb +3 -0
- data/lib/popolo.rb +18 -0
- data/spec/controllers/popolo/areas_controller_spec.rb +59 -0
- data/spec/controllers/popolo/organizations_controller_spec.rb +59 -0
- data/spec/controllers/popolo/people_controller_spec.rb +30 -0
- data/spec/controllers/popolo/posts_controller_spec.rb +30 -0
- data/spec/controllers/popolo_controller_spec.rb +4 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/cat.rb +6 -0
- data/spec/dummy/app/models/dog.rb +10 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +62 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/mongoid.yml +68 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/log/development.log +6 -0
- data/spec/dummy/log/test.log +35513 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/factories.rb +25 -0
- data/spec/helpers/popolo_helper_spec.rb +4 -0
- data/spec/models/popolo/address_spec.rb +4 -0
- data/spec/models/popolo/area_spec.rb +4 -0
- data/spec/models/popolo/event_spec.rb +7 -0
- data/spec/models/popolo/identifier_spec.rb +5 -0
- data/spec/models/popolo/link_spec.rb +5 -0
- data/spec/models/popolo/membership_spec.rb +27 -0
- data/spec/models/popolo/organization_spec.rb +25 -0
- data/spec/models/popolo/other_name_spec.rb +25 -0
- data/spec/models/popolo/person_spec.rb +25 -0
- data/spec/models/popolo/post_spec.rb +5 -0
- data/spec/models/popolo/source_spec.rb +7 -0
- data/spec/popolo/mixins/sluggable_spec.rb +153 -0
- data/spec/popolo_spec.rb +4 -0
- data/spec/routing/popolo/areas_routing_spec.rb +29 -0
- data/spec/routing/popolo/organizations_routing_spec.rb +29 -0
- data/spec/routing/popolo/people_routing_spec.rb +21 -0
- data/spec/routing/popolo/posts_routing_spec.rb +21 -0
- data/spec/spec_helper.rb +81 -0
- metadata +416 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Open North Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# Popolo
|
2
|
+
|
3
|
+
[](http://travis-ci.org/opennorth/popolo)
|
4
|
+
[](https://gemnasium.com/opennorth/popolo)
|
5
|
+
[](https://codeclimate.com/github/opennorth/popolo)
|
6
|
+
|
7
|
+
Popolo's goal is to make it easier for civic developers to create government transparency, monitoring and engagement websites.
|
8
|
+
|
9
|
+
Popolo is a [Ruby on Rails engine](http://guides.rubyonrails.org/engines.html) that provides additional functionality to a [Ruby on Rails](http://rubyonrails.org/) application, so that developers can focus on what's special about the governments they want to monitor, instead of re-implementing features commonly found in open government websites. The core Popolo engine provides basic models, controllers and views for the objects found in all open government websites – people, organizations and the relationships between the two. Other engines provide additional functionality.
|
10
|
+
|
11
|
+
In addition to being a Rails engine, Popolo is also a [data standard](http://popoloproject.com/data.html) and an [API specification](http://popoloproject.com/api.html).
|
12
|
+
|
13
|
+
## Getting Started
|
14
|
+
|
15
|
+
Popolo uses Mongoid to connect to MongoDB, which requires Rails 3 and supports only MRI 1.9.3 and HEAD, and JRuby 1.6.0+ in 1.9 mode.
|
16
|
+
|
17
|
+
First, create your Rails application:
|
18
|
+
|
19
|
+
rails new myapp --skip-active-record
|
20
|
+
|
21
|
+
Add the `popolo` gem to your `Gemfile`:
|
22
|
+
|
23
|
+
gem 'popolo'
|
24
|
+
|
25
|
+
If you didn't run `rails new` with the `--skip-active-record` option, follow Mongoid's [installation instructions](http://mongoid.org/en/mongoid/docs/installation.html). Otherwise:
|
26
|
+
|
27
|
+
rails generate mongoid:config
|
28
|
+
|
29
|
+
Finally, run the `popolo` generator:
|
30
|
+
|
31
|
+
rails generate popolo
|
32
|
+
|
33
|
+
## Bugs? Questions?
|
34
|
+
|
35
|
+
This engine's main repository is on GitHub: [http://github.com/opennorth/popolo](http://github.com/opennorth/popolo), where your contributions, forks, bug reports, feature requests, and feedback are greatly welcomed.
|
36
|
+
|
37
|
+
## Acknowledgements
|
38
|
+
|
39
|
+
This gem is developed by [Open North](http://www.opennorth.ca/) through a partnership with the [Participatory Politics Foundation](http://www.participatorypolitics.org/).
|
40
|
+
|
41
|
+
Copyright (c) 2012 Open North Inc., released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
task :default => :spec
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'yard'
|
11
|
+
YARD::Rake::YardocTask.new
|
12
|
+
rescue LoadError
|
13
|
+
task :yard do
|
14
|
+
abort 'YARD is not available. In order to run yard, you must: gem install yard'
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// the compiled file.
|
9
|
+
//
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Popolo
|
2
|
+
class AreasController < PopoloController
|
3
|
+
inherit_resources
|
4
|
+
# inherited_resources assumes the routes are namespaced. If an engine is
|
5
|
+
# mounted at root, however, there will be no namespace.
|
6
|
+
self.resources_configuration[:self][:route_prefix] = nil
|
7
|
+
|
8
|
+
respond_to :html, :json
|
9
|
+
actions :index, :show
|
10
|
+
custom_actions collection: :nested_index, resource: :nested_show
|
11
|
+
|
12
|
+
before_filter :validate_path, only: [:nested_index, :nested_show]
|
13
|
+
|
14
|
+
def index
|
15
|
+
@areas = Area.roots
|
16
|
+
index!
|
17
|
+
end
|
18
|
+
|
19
|
+
def show
|
20
|
+
@area = Area.find_by_slug_or_id(params[:id])
|
21
|
+
show!
|
22
|
+
end
|
23
|
+
|
24
|
+
def nested_index
|
25
|
+
@areas = @area.children
|
26
|
+
|
27
|
+
nested_index! do |format|
|
28
|
+
format.html { render action: 'index'}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def nested_show
|
33
|
+
nested_show! do |format|
|
34
|
+
format.html { render action: 'show'}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
# @raises [Mongoid::Errors::DocumentNotFound] if a resource is improperly nested
|
41
|
+
def validate_path
|
42
|
+
parts = params[:path].split '/'
|
43
|
+
parts.each do |part|
|
44
|
+
@area = Area.find_by(parent_id: @area, slug: part)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Popolo
|
2
|
+
class OrganizationsController < PopoloController
|
3
|
+
inherit_resources
|
4
|
+
# inherited_resources assumes the routes are namespaced. If an engine is
|
5
|
+
# mounted at root, however, there will be no namespace.
|
6
|
+
self.resources_configuration[:self][:route_prefix] = nil
|
7
|
+
|
8
|
+
respond_to :html, :json
|
9
|
+
actions :index, :show
|
10
|
+
custom_actions collection: :nested_index, resource: :nested_show
|
11
|
+
|
12
|
+
before_filter :validate_path, only: [:nested_index, :nested_show]
|
13
|
+
|
14
|
+
def index
|
15
|
+
@organizations = Organization.roots
|
16
|
+
index!
|
17
|
+
end
|
18
|
+
|
19
|
+
def show
|
20
|
+
@organization = Organization.find_by_slug_or_id(params[:id])
|
21
|
+
show!
|
22
|
+
end
|
23
|
+
|
24
|
+
def nested_index
|
25
|
+
@organizations = @organization.children
|
26
|
+
|
27
|
+
nested_index! do |format|
|
28
|
+
format.html { render action: 'index'}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def nested_show
|
33
|
+
nested_show! do |format|
|
34
|
+
format.html { render action: 'show'}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
# @raises [Mongoid::Errors::DocumentNotFound] if a resource is improperly nested
|
41
|
+
def validate_path
|
42
|
+
parts = params[:path].split '/'
|
43
|
+
parts.each do |part|
|
44
|
+
@organization = Organization.find_by(parent_id: @organization, slug: part)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module PopoloHelper
|
2
|
+
# @note inherited_resources sets incorrect arguments for glob routes.
|
3
|
+
# @see https://github.com/josevalim/inherited_resources/blob/master/lib/inherited_resources/url_helpers.rb
|
4
|
+
def nested_resources_path(*args)
|
5
|
+
send("nested_#{resource_collection_name}_path", *args)
|
6
|
+
end
|
7
|
+
def nested_resource_path(*args)
|
8
|
+
send("nested_#{resource_instance_name}_path", *args)
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Popolo
|
2
|
+
# A physical location or a mail delivery point.
|
3
|
+
class Address
|
4
|
+
include Mongoid::Document
|
5
|
+
|
6
|
+
embedded_in :addressable, polymorphic: true
|
7
|
+
|
8
|
+
# The address' type, e.g. 'capitol'.
|
9
|
+
field :type, type: String
|
10
|
+
# The postal address.
|
11
|
+
field :address, type: String
|
12
|
+
# A voice telephone number.
|
13
|
+
field :voice, type: Integer
|
14
|
+
# A facsimile telephone number.
|
15
|
+
field :fax, type: Integer
|
16
|
+
# A mobile telephone number.
|
17
|
+
field :cell, type: Integer
|
18
|
+
# A toll-free telephone number.
|
19
|
+
field :tollfree, type: Integer
|
20
|
+
# A video conferencing telephone number.
|
21
|
+
field :video, type: Integer
|
22
|
+
# A paging device telephone number.
|
23
|
+
field :pager, type: Integer
|
24
|
+
# A telecommunication device for people with hearing or speech difficulties.
|
25
|
+
field :textphone, type: Integer
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Popolo
|
2
|
+
# A bounded area, like an administrative boundary.
|
3
|
+
#
|
4
|
+
# @note There is an upper limit to the number of administrative levels;
|
5
|
+
# however, there is little agreement as to what those levels are. Therefore,
|
6
|
+
# instead of having a different model for each administrative level – which
|
7
|
+
# would have advantages – we use a flexible tree structure.
|
8
|
+
class Area
|
9
|
+
include Mongoid::Document
|
10
|
+
include Mongoid::Tree
|
11
|
+
|
12
|
+
include Popolo::Sluggable
|
13
|
+
index({slug: 1, parent_id: 1}, unique: true)
|
14
|
+
|
15
|
+
# Memberships related to the area, e.g. officials.
|
16
|
+
has_many :memberships, class_name: 'Popolo::Membership'
|
17
|
+
# Organizations related to the area, e.g. governments.
|
18
|
+
has_many :organizations, class_name: 'Popolo::Organization'
|
19
|
+
# Posts related to the area, e.g. officials.
|
20
|
+
has_many :posts, class_name: 'Popolo::Post'
|
21
|
+
|
22
|
+
# The area's category.
|
23
|
+
field :classification, type: String
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Popolo
|
2
|
+
# An occurrence, e.g. an action mentioning or performed by an agent.
|
3
|
+
#
|
4
|
+
# Turtle document: @todo move into popoloproject.com
|
5
|
+
#
|
6
|
+
# <http://example.com/events/57cc67093475061e3d95369d.ttl>
|
7
|
+
# a cnt:ContentAsText;
|
8
|
+
# cnt:characterEncoding "UTF-8";
|
9
|
+
# cnt:chars "Lorem ipsum dolor sit amet, consectetur adipiscing elit. ...";
|
10
|
+
# dcterms:format "text/plain";
|
11
|
+
# dcterms:isFormatOf <http://example.org/news/123.html>;
|
12
|
+
# dcterms:issued "2012-01-01T00:00:00Z"^^xsd:dateTime;
|
13
|
+
# dcterms:identifier "57cc67093475061e3d95369d";
|
14
|
+
# dcterms:created "2012-01-01T00:00:00Z"^^xsd:dateTime;
|
15
|
+
# dcterms:modified "2012-01-01T00:00:00Z"^^xsd:dateTime .
|
16
|
+
#
|
17
|
+
# @see http://www.w3.org/TR/Content-in-RDF10/
|
18
|
+
# @see http://dublincore.org/documents/dcmi-terms/
|
19
|
+
class Event
|
20
|
+
include Mongoid::Document
|
21
|
+
include Mongoid::Timestamps
|
22
|
+
|
23
|
+
# The identifier of the source of information for the event.
|
24
|
+
field :source, type: String
|
25
|
+
# The URL to which the event may be attributed.
|
26
|
+
field :url, type: String
|
27
|
+
# The event's content.
|
28
|
+
field :body, type: String
|
29
|
+
# The time of the event or of its publication.
|
30
|
+
field :issued_at, type: Time
|
31
|
+
# The records related to the event.
|
32
|
+
field :related, type: Hash
|
33
|
+
# Any additional information about the event.
|
34
|
+
field :extra, type: Hash
|
35
|
+
|
36
|
+
# @note It's not possible to do a many-to-many polymorphic relation, so we
|
37
|
+
# must list every index individually.
|
38
|
+
|
39
|
+
index 'related.area' => 1, source: 1, issued_at: -1
|
40
|
+
index 'related.membership' => 1, source: 1, issued_at: -1
|
41
|
+
index 'related.organization' => 1, source: 1, issued_at: -1
|
42
|
+
index 'related.post' => 1, source: 1, issued_at: -1
|
43
|
+
|
44
|
+
validates_presence_of :source, :url, :body, :issued_at
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Popolo
|
2
|
+
# An issued identifier.
|
3
|
+
class Identifier
|
4
|
+
include Mongoid::Document
|
5
|
+
|
6
|
+
embedded_in :organization, class_name: 'Popolo::Organization'
|
7
|
+
|
8
|
+
# An issued identifier, e.g. a DUNS number.
|
9
|
+
field :identifier, type: String
|
10
|
+
# An identifier scheme, e.g. DUNS.
|
11
|
+
field :scheme, type: String
|
12
|
+
|
13
|
+
validates_presence_of :identifier
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Popolo
|
2
|
+
# A URL for a document about a person.
|
3
|
+
class Link
|
4
|
+
include Mongoid::Document
|
5
|
+
|
6
|
+
embedded_in :person, class_name: 'Popolo::Person'
|
7
|
+
|
8
|
+
# A URL for a document about a person.
|
9
|
+
field :url, type: String
|
10
|
+
# A note, e.g. 'Wikipedia page'.
|
11
|
+
field :note, type: String
|
12
|
+
|
13
|
+
validates_presence_of :url
|
14
|
+
# @note Add URL validation to match JSON Schema?
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Popolo
|
2
|
+
# A relationship between a person and an organization.
|
3
|
+
class Membership
|
4
|
+
include Mongoid::Document
|
5
|
+
|
6
|
+
# An area related to the membership, e.g. an electoral riding.
|
7
|
+
belongs_to :area, index: true, class_name: 'Popolo::Area'
|
8
|
+
# The person who is a party to the relationship.
|
9
|
+
belongs_to :organization, index: true, class_name: 'Popolo::Organization'
|
10
|
+
# The organization that is a party to the relationship.
|
11
|
+
belongs_to :person, index: true, class_name: 'Popolo::Person'
|
12
|
+
|
13
|
+
# The role that the person fulfills in the organization. Roles should
|
14
|
+
# preferably belong to a controlled vocabulary.
|
15
|
+
field :role, type: String
|
16
|
+
# The date on which the relationship began.
|
17
|
+
field :start_date, type: String
|
18
|
+
# The date on which the relationship ended.
|
19
|
+
field :end_date, type: String
|
20
|
+
|
21
|
+
validates_presence_of :organization_id, :person_id
|
22
|
+
validates_format_of :start_date, with: /\A\d{4}(-\d{2}){0,2}\z/, allow_blank: true
|
23
|
+
validates_format_of :end_date, with: /\A\d{4}(-\d{2}){0,2}\z/, allow_blank: true
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Popolo
|
2
|
+
# A group with a common purpose or reason for existence that goes beyond the
|
3
|
+
# set of people belonging to it, e.g. a political structure.
|
4
|
+
class Organization
|
5
|
+
include Mongoid::Document
|
6
|
+
include Mongoid::Tree
|
7
|
+
|
8
|
+
include Popolo::Sluggable
|
9
|
+
index({slug: 1, parent_id: 1}, unique: true)
|
10
|
+
|
11
|
+
# An area related to the organization, e.g. a region or country.
|
12
|
+
belongs_to :area, index: true, class_name: 'Popolo::Area'
|
13
|
+
# The relationships to which the organization is a party.
|
14
|
+
has_many :memberships, class_name: 'Popolo::Membership', dependent: :destroy
|
15
|
+
# The posts within the organization.
|
16
|
+
has_many :posts, class_name: 'Popolo::Post', dependent: :destroy
|
17
|
+
# The organization's alternate or former names.
|
18
|
+
embeds_many :other_names, as: :nameable, class_name: 'Popolo::OtherName'
|
19
|
+
# The organization's issued identifiers.
|
20
|
+
embeds_many :identifiers, class_name: 'Popolo::Identifier'
|
21
|
+
|
22
|
+
# The organization's category.
|
23
|
+
field :classification, type: String
|
24
|
+
# The organization's date of founding in ISO 8601:2004 format.
|
25
|
+
field :founding_date, type: String
|
26
|
+
# The organization's date of dissolution in ISO 8601:2004 format.
|
27
|
+
field :dissolution_date, type: String
|
28
|
+
|
29
|
+
validates_format_of :founding_date, with: /\A\d{4}(-\d{2}){0,2}\z/, allow_blank: true
|
30
|
+
validates_format_of :dissolution_date, with: /\A\d{4}(-\d{2}){0,2}\z/, allow_blank: true
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Popolo
|
2
|
+
# An alternate or former name.
|
3
|
+
class OtherName
|
4
|
+
include Mongoid::Document
|
5
|
+
|
6
|
+
embedded_in :nameable, polymorphic: true
|
7
|
+
|
8
|
+
# An alternate or former name.
|
9
|
+
field :name, type: String
|
10
|
+
# The date on which the name was adopted.
|
11
|
+
field :start_date, type: String
|
12
|
+
# The date on which the name was abandoned.
|
13
|
+
field :end_date, type: String
|
14
|
+
# A note, e.g. "Birth name".
|
15
|
+
field :note, type: String
|
16
|
+
|
17
|
+
validates_presence_of :name
|
18
|
+
validates_format_of :start_date, with: /\A\d{4}(-\d{2}){0,2}\z/, allow_blank: true
|
19
|
+
validates_format_of :end_date, with: /\A\d{4}(-\d{2}){0,2}\z/, allow_blank: true
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Popolo
|
2
|
+
# A real person, alive or dead.
|
3
|
+
class Person
|
4
|
+
include Mongoid::Document
|
5
|
+
|
6
|
+
include Popolo::Sluggable
|
7
|
+
index({slug: 1}, unique: true)
|
8
|
+
|
9
|
+
# The relationships to which the person is a party.
|
10
|
+
has_many :memberships, class_name: 'Popolo::Membership'
|
11
|
+
# The posts held by the person.
|
12
|
+
has_many :posts, class_name: 'Popolo::Post'
|
13
|
+
# The person's alternate or former names.
|
14
|
+
embeds_many :other_names, as: :nameable, class_name: 'Popolo::OtherName'
|
15
|
+
# Links to pages about this person, e.g. Wikipedia, or to accounts this
|
16
|
+
# person has on other websites, e.g. Twitter.
|
17
|
+
embeds_many :links, class_name: 'Popolo::Link'
|
18
|
+
|
19
|
+
# The person's family name.
|
20
|
+
field :family_name, type: String
|
21
|
+
# The person's given name.
|
22
|
+
field :given_name, type: String
|
23
|
+
# An additional name, e.g. a middle name.
|
24
|
+
field :additional_name, type: String
|
25
|
+
# An honorific prefix before the person's name, e.g. "Dr.".
|
26
|
+
field :honorific_prefix, type: String
|
27
|
+
# An honorific suffix after the person's name, e.g. "Jr.".
|
28
|
+
field :honorific_suffix, type: String
|
29
|
+
# The person's email address.
|
30
|
+
field :email, type: String
|
31
|
+
# The person's gender, e.g. "male", "female" or another value.
|
32
|
+
field :gender, type: String
|
33
|
+
# The person's date of birth in ISO 8601:2004 format.
|
34
|
+
field :birth_date, type: String
|
35
|
+
# The person's date of death in ISO 8601:2004 format.
|
36
|
+
field :death_date, type: String
|
37
|
+
# The URL of the person's head shot.
|
38
|
+
field :image, type: String
|
39
|
+
# The person's one-line biography.
|
40
|
+
field :summary, type: String
|
41
|
+
# The person's extended biography.
|
42
|
+
field :biography, type: String
|
43
|
+
|
44
|
+
# @note Add email address validation to match JSON Schema?
|
45
|
+
# @note Add URL validation to match JSON Schema?
|
46
|
+
validates_format_of :birth_date, with: /\A\d{4}(-\d{2}){0,2}\z/, allow_blank: true
|
47
|
+
validates_format_of :death_date, with: /\A\d{4}(-\d{2}){0,2}\z/, allow_blank: true
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Popolo
|
2
|
+
# A position in an organization that exists independently of the person
|
3
|
+
# holding it.
|
4
|
+
class Post
|
5
|
+
include Mongoid::Document
|
6
|
+
|
7
|
+
def self.slug_source
|
8
|
+
:role
|
9
|
+
end
|
10
|
+
|
11
|
+
include Popolo::Sluggable
|
12
|
+
index({slug: 1}, unique: true)
|
13
|
+
|
14
|
+
# An area related to the post, e.g. an electoral riding.
|
15
|
+
belongs_to :area, index: true, class_name: 'Popolo::Area'
|
16
|
+
# The organization in which the post exists.
|
17
|
+
belongs_to :organization, index: true, class_name: 'Popolo::Organization'
|
18
|
+
# The person holding the post.
|
19
|
+
belongs_to :person, index: true, class_name: 'Popolo::Person'
|
20
|
+
# The address at which the post is based.
|
21
|
+
embeds_many :addresses, as: :addressable, class_name: 'Popolo::Address'
|
22
|
+
|
23
|
+
validates_presence_of :organization_id
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Popolo
|
2
|
+
# A source of information.
|
3
|
+
#
|
4
|
+
# Turtle document: @todo move into popoloproject.com
|
5
|
+
#
|
6
|
+
# <http://example.com/sources/67cc67093475061e3d95369d.ttl>
|
7
|
+
# rdfs:label "news.google.com";
|
8
|
+
# dcterms:identifier "67cc67093475061e3d95369d";
|
9
|
+
# dcterms:modified "2012-01-01T00:00:00Z"^^xsd:dateTime .
|
10
|
+
#
|
11
|
+
# @see http://dublincore.org/documents/dcmi-terms/
|
12
|
+
# @todo Add the ETag to the Turtle document.
|
13
|
+
class Source
|
14
|
+
include Mongoid::Document
|
15
|
+
|
16
|
+
embedded_in :sourceable, polymorphic: true
|
17
|
+
|
18
|
+
# A human-readable unique identifier for the source, e.g. "news.google.com".
|
19
|
+
field :name, type: String
|
20
|
+
# The source's ETag.
|
21
|
+
field :etag, type: String
|
22
|
+
# The source's last modified timestamp.
|
23
|
+
field :last_modified, type: Time
|
24
|
+
# Any additional information about the source.
|
25
|
+
field :extra, type: Hash
|
26
|
+
|
27
|
+
validates_presence_of :name, :last_modified
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render partial: 'popolo/areas_or_organizations/index', locals: {collection: @areas, object: @area} %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render partial: 'popolo/areas_or_organizations/show', locals: {object: @area} %>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<% if object %>
|
2
|
+
<nav>
|
3
|
+
<ul class="breadcrumb">
|
4
|
+
<li><%= link_to resource_collection_name.capitalize, collection_path %> <span class="divider">/</span></li>
|
5
|
+
<% ancestors = object.ancestors %>
|
6
|
+
<% ancestors.each_with_index do |ancestor,index| %>
|
7
|
+
<li>
|
8
|
+
<%= link_to ancestor.name, nested_resources_path(ancestors[0..index]) %>
|
9
|
+
<span class="divider">/</span>
|
10
|
+
</li>
|
11
|
+
<% end %>
|
12
|
+
<li class="active"><%= object.name %></li>
|
13
|
+
</ul>
|
14
|
+
</nav>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<% unless collection.empty? %>
|
18
|
+
<% groups = collection.asc(:sort_name).group_by(&:classification) %>
|
19
|
+
<% groups.each do |classification,documents| %>
|
20
|
+
<section>
|
21
|
+
<header>
|
22
|
+
<h1><%= t(classification, scope: [:popolo, resource_collection_name, :classifications]) %></h1>
|
23
|
+
</header>
|
24
|
+
<ul>
|
25
|
+
<% documents.each do |document| %>
|
26
|
+
<li><%= link_to document.name, nested_resources_path([object, document].compact) %></li>
|
27
|
+
<% end %>
|
28
|
+
</ul>
|
29
|
+
</section>
|
30
|
+
<% end %>
|
31
|
+
<% end %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<nav>
|
2
|
+
<ul class="breadcrumb">
|
3
|
+
<li><%= link_to resource_collection_name.capitalize, collection_path %> <span class="divider">/</span></li>
|
4
|
+
<% ancestors = object.ancestors %>
|
5
|
+
<% ancestors.each_with_index do |ancestor,index| %>
|
6
|
+
<li>
|
7
|
+
<%= link_to ancestor.name, nested_resource_path(ancestors[0..index]) %>
|
8
|
+
<span class="divider">/</span>
|
9
|
+
</li>
|
10
|
+
<% end %>
|
11
|
+
<li class="active"><%= object.name %></li>
|
12
|
+
</ul>
|
13
|
+
</nav>
|
14
|
+
|
15
|
+
<% collection = object.children %>
|
16
|
+
<% unless collection.empty? %>
|
17
|
+
<% groups = collection.asc(:sort_name).group_by(&:classification) %>
|
18
|
+
<% groups.each do |classification,documents| %>
|
19
|
+
<section>
|
20
|
+
<header>
|
21
|
+
<h1><%= t(classification, scope: [:popolo, resource_collection_name, :classifications]) %></h1>
|
22
|
+
</header>
|
23
|
+
<ul>
|
24
|
+
<% documents.each do |document| %>
|
25
|
+
<li><%= link_to document.name, nested_resource_path([object, document]) %></li>
|
26
|
+
<% end %>
|
27
|
+
</ul>
|
28
|
+
</section>
|
29
|
+
<% end %>
|
30
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render partial: 'popolo/areas_or_organizations/index', locals: {collection: @organizations, object: @organization} %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render partial: 'popolo/areas_or_organizations/show', locals: {object: @organization} %>
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|