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.
Files changed (94) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +41 -0
  3. data/Rakefile +16 -0
  4. data/app/assets/javascripts/popolo/application.js +13 -0
  5. data/app/assets/stylesheets/popolo/application.css +13 -0
  6. data/app/controllers/popolo/areas_controller.rb +48 -0
  7. data/app/controllers/popolo/organizations_controller.rb +48 -0
  8. data/app/controllers/popolo/people_controller.rb +12 -0
  9. data/app/controllers/popolo/posts_controller.rb +12 -0
  10. data/app/controllers/popolo_controller.rb +3 -0
  11. data/app/helpers/popolo_helper.rb +10 -0
  12. data/app/models/popolo/address.rb +27 -0
  13. data/app/models/popolo/area.rb +25 -0
  14. data/app/models/popolo/event.rb +46 -0
  15. data/app/models/popolo/identifier.rb +15 -0
  16. data/app/models/popolo/link.rb +16 -0
  17. data/app/models/popolo/membership.rb +25 -0
  18. data/app/models/popolo/organization.rb +32 -0
  19. data/app/models/popolo/other_name.rb +21 -0
  20. data/app/models/popolo/person.rb +49 -0
  21. data/app/models/popolo/post.rb +25 -0
  22. data/app/models/popolo/source.rb +29 -0
  23. data/app/views/popolo/areas/index.html.erb +1 -0
  24. data/app/views/popolo/areas/show.html.erb +1 -0
  25. data/app/views/popolo/areas_or_organizations/_index.html.erb +31 -0
  26. data/app/views/popolo/areas_or_organizations/_show.html.erb +30 -0
  27. data/app/views/popolo/organizations/index.html.erb +1 -0
  28. data/app/views/popolo/organizations/show.html.erb +1 -0
  29. data/app/views/popolo/people/index.html.erb +0 -0
  30. data/app/views/popolo/people/show.html.erb +0 -0
  31. data/app/views/popolo/posts/index.html.erb +0 -0
  32. data/app/views/popolo/posts/show.html.erb +0 -0
  33. data/config/routes.rb +15 -0
  34. data/lib/generators/popolo_generator.rb +36 -0
  35. data/lib/generators/templates/README +7 -0
  36. data/lib/popolo/engine.rb +7 -0
  37. data/lib/popolo/mixins/eventable.rb +15 -0
  38. data/lib/popolo/mixins/sluggable.rb +64 -0
  39. data/lib/popolo/version.rb +3 -0
  40. data/lib/popolo.rb +18 -0
  41. data/spec/controllers/popolo/areas_controller_spec.rb +59 -0
  42. data/spec/controllers/popolo/organizations_controller_spec.rb +59 -0
  43. data/spec/controllers/popolo/people_controller_spec.rb +30 -0
  44. data/spec/controllers/popolo/posts_controller_spec.rb +30 -0
  45. data/spec/controllers/popolo_controller_spec.rb +4 -0
  46. data/spec/dummy/Rakefile +7 -0
  47. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  48. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  49. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  50. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  51. data/spec/dummy/app/models/cat.rb +6 -0
  52. data/spec/dummy/app/models/dog.rb +10 -0
  53. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  54. data/spec/dummy/config/application.rb +62 -0
  55. data/spec/dummy/config/boot.rb +10 -0
  56. data/spec/dummy/config/environment.rb +5 -0
  57. data/spec/dummy/config/environments/development.rb +37 -0
  58. data/spec/dummy/config/environments/production.rb +67 -0
  59. data/spec/dummy/config/environments/test.rb +37 -0
  60. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  61. data/spec/dummy/config/initializers/session_store.rb +8 -0
  62. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  63. data/spec/dummy/config/locales/en.yml +5 -0
  64. data/spec/dummy/config/mongoid.yml +68 -0
  65. data/spec/dummy/config/routes.rb +3 -0
  66. data/spec/dummy/config.ru +4 -0
  67. data/spec/dummy/log/development.log +6 -0
  68. data/spec/dummy/log/test.log +35513 -0
  69. data/spec/dummy/public/404.html +26 -0
  70. data/spec/dummy/public/422.html +26 -0
  71. data/spec/dummy/public/500.html +25 -0
  72. data/spec/dummy/public/favicon.ico +0 -0
  73. data/spec/dummy/script/rails +6 -0
  74. data/spec/factories.rb +25 -0
  75. data/spec/helpers/popolo_helper_spec.rb +4 -0
  76. data/spec/models/popolo/address_spec.rb +4 -0
  77. data/spec/models/popolo/area_spec.rb +4 -0
  78. data/spec/models/popolo/event_spec.rb +7 -0
  79. data/spec/models/popolo/identifier_spec.rb +5 -0
  80. data/spec/models/popolo/link_spec.rb +5 -0
  81. data/spec/models/popolo/membership_spec.rb +27 -0
  82. data/spec/models/popolo/organization_spec.rb +25 -0
  83. data/spec/models/popolo/other_name_spec.rb +25 -0
  84. data/spec/models/popolo/person_spec.rb +25 -0
  85. data/spec/models/popolo/post_spec.rb +5 -0
  86. data/spec/models/popolo/source_spec.rb +7 -0
  87. data/spec/popolo/mixins/sluggable_spec.rb +153 -0
  88. data/spec/popolo_spec.rb +4 -0
  89. data/spec/routing/popolo/areas_routing_spec.rb +29 -0
  90. data/spec/routing/popolo/organizations_routing_spec.rb +29 -0
  91. data/spec/routing/popolo/people_routing_spec.rb +21 -0
  92. data/spec/routing/popolo/posts_routing_spec.rb +21 -0
  93. data/spec/spec_helper.rb +81 -0
  94. 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
+ [![Build Status](https://secure.travis-ci.org/opennorth/popolo.png)](http://travis-ci.org/opennorth/popolo)
4
+ [![Dependency Status](https://gemnasium.com/opennorth/popolo.png)](https://gemnasium.com/opennorth/popolo)
5
+ [![Code Climate](https://codeclimate.com/badge.png)](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,12 @@
1
+ module Popolo
2
+ class PeopleController < PopoloController
3
+ inherit_resources
4
+ respond_to :html, :json
5
+ actions :index, :show
6
+
7
+ def show
8
+ @person = Person.find_by_slug_or_id(params[:id])
9
+ show!
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Popolo
2
+ class PostsController < PopoloController
3
+ inherit_resources
4
+ respond_to :html, :json
5
+ actions :index, :show
6
+
7
+ def show
8
+ @post = Post.find_by_slug_or_id(params[:id])
9
+ show!
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ class PopoloController < Popolo.parent_controller.constantize
2
+ helper PopoloHelper
3
+ 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