|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- require 'data_mapper'
-
- class Poll
- include DataMapper::Resource
-
- property :district_id, Integer, :key => true
- property :election_id, Integer, :key => true
- property :electorate, Integer # The number of people eligible to vote in this district in this election
- property :ballot_papers_issued, Integer # The number of ballot papers issued (includes spoiled ballots)
- property :seats, Integer, :required => true # The number of seats to be elected in this district in this election
-
- def turnout_percent
- @ballot_papers_issued.to_f / @electorate.to_f * 100.0
- end
-
- belongs_to :election
- belongs_to :district
- end
-
- class PollingStation
- include DataMapper::Resource
-
- property :id, String, :key => true, :length => 2 # e.g. "KA"
- property :name, String, :length => 255#, :required => true
- property :address, String, :length => 255#, :required => true
- property :postcode, String#, :required => true
- property :easting, Float, :required => true
- property :northing, Float, :required => true
- property :lat, Float, :required => true
- property :lng, Float, :required => true
-
- has n, :postcodes
- end
-
- class Postcode
- include DataMapper::Resource
-
- # Postcode natural key, uppercase with space, eg. "SM1 1EA"
- # Column names derived from Ordnance Survey CodePoint Open
- property :postcode, String, :key => true
- property :positional_quality_indicator, Integer
- property :eastings, Integer, :required => true
- property :northings, Integer, :required => true
- property :country_code, String, :required => true
- property :nhs_regional_ha_code, String, :required => true
- property :nhs_ha_code, String, :required => true
- property :admin_county_code, String # NULL within Greater London
- property :admin_district_code, String, :required => true # e.g. London Borough of Sutton
- property :admin_ward_code, String, :required => true # e.g. Sutton Central
- property :lat, Float, :required => true
- property :lng, Float, :required => true
- property :ward_id, Integer, :required => true # Sutton Council
- property :constituency_id, Integer, :required => false # UK Parliament
- property :polling_station_id, String, :length => 2
-
- belongs_to :district, :child_key => [:ward_id]
- belongs_to :polling_station
-
- def self.finder(postcode)
- postcode = postcode.strip.upcase
-
- if o = self.get(postcode)
- return o
- end
-
- result = Pat.get(postcode)
-
- unless result.code == 404
- # cache API result
- self.create(
- :postcode => postcode,
- :lat => result['geo']['lat'],
- :lng => result['geo']['lng'],
- :district_name => result['administrative']['district']['title'],
- :district_code => result['administrative']['district']['uri'].match(/.+\/(.+)$/)[1],
- :ward_name => result['administrative']['ward']['title'],
- :ward_code => result['administrative']['ward']['uri'].match(/.+\/(.+)$/)[1]
- )
- else
- # invalid postcode
- nil
- end
-
- end
- end
-
- class Candidate
- include DataMapper::Resource
-
- property :id, Serial
- property :forenames, String, :required => true
- property :surname, String, :required => true, :index => true
-
- has n, :candidacies
-
- def short_name
- @forenames.split(' ')[0] + ' ' + @surname
- end
-
- def name
- @forenames + ' ' + @surname
- end
- end
-
- class DeletedCandidate
- include DataMapper::Resource
-
- property :old_candidate_id, Integer, :key => true # ID of candidate that has been merged/deleted
- property :candidate_id, Integer, :required => true # ID of candidate that has been kept
- end
-
- class Candidacy
- include DataMapper::Resource
-
- property :id, Serial
- property :election_id, Integer, :required => true
- property :candidate_id, Integer, :required => true
- property :party_id, Integer
- property :district_id, Integer, :required => true
- property :votes, Integer
- property :address, String, :length => 200
- property :postcode, String
- property :position, Integer # Position of this candidate in this district. (1..n)
- property :seats, Integer # Number of seats won by this candidacy (0 or 1)
- property :labcoop, Boolean, :default => false # Candidacy is for joint Labour/Co-op party
-
- belongs_to :election
- belongs_to :candidate
- belongs_to :party
- belongs_to :district
- end
-
- class Campaign
- include DataMapper::Resource
-
- property :party_id, Integer, :key => true
- property :election_id, Integer, :key => true
- property :party_url, String, :length => 255
- property :manifesto_html_url, String, :length => 255
- property :manifesto_pdf_url, String, :length => 255
-
- belongs_to :party
- belongs_to :election
- end
-
- class Election
- include DataMapper::Resource
-
- property :id, Serial
- property :body_id, Integer, :required => true
- property :d, Date, :required => true, :index => true
- property :reason, String, :length => 255
- property :kind, String, :length => 255
-
- has n, :candidacies
- has n, :polls
- belongs_to :body
- has n, :campaigns
-
- def self.past
- self.all(:d.lt => Time.now.to_s, :order => [ :d.desc ])
- end
-
- def self.future
- self.all(:d.gte => Time.now.to_s, :order => [ :d.desc ])
- end
-
- # electorate and ballot_papers_issued assume there's a Poll object for every district in this election
- def electorate
- Poll.sum(:electorate, :election => self)
- end
-
- def ballot_papers_issued
- Poll.sum(:ballot_papers_issued, :election => self)
- end
- end
-
- class District
- include DataMapper::Resource
-
- property :id, Serial
- property :body_id, Integer, :required => true
- property :name, String, :length => 255, :required => true
- property :slug, String
- property :seats, Integer
- property :ons_district_code, String
-
- belongs_to :body
- has n, :postcodes, :child_key => [:ward_id]
- has n, :polls
-
- def self.slugify(name)
- name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase
- end
- end
-
- class Body
- include DataMapper::Resource
-
- property :id, Serial
- property :name, String, :length => 255, :required => true
- property :district_name, String, :length => 255, :required => true # singular
- property :districts_name, String, :length => 255, :required => true # plural
- property :slug, String, :length => 255
-
- has n, :elections
- has n, :districts
- end
-
- class Party
- include DataMapper::Resource
-
- property :id, Serial
- property :name, String, :required => true
- property :colour, String
-
- has n, :candidacies
- has n, :campaigns
- end
-
- # These models are now redundant
-
- class Ward
- include DataMapper::Resource
-
- property :id, Serial
- property :slug, String, :required => true
- property :ons_id, String, :required => true
- property :name, String, :required => true
- property :constituency_id, Integer, :required => true
-
- has n, :councilcandidates, :order => ['surname']
- belongs_to :constituency
-
- def self.slugify(name)
- name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase
- end
-
- end
-
- class Councilcandidate
- include DataMapper::Resource
-
- property :id, Serial
- property :ward_id, Integer, :required => true
- property :party_id, Integer, :required => true
- property :forenames, String, :required => true
- property :surname, String, :required => true
- property :address, String, :length => 200
- property :postcode, String, :required => true
- property :votes_2010, Integer
-
- belongs_to :party
- belongs_to :ward
- end
-
- class Parliamentcandidate
- include DataMapper::Resource
-
- property :id, Serial
- property :constituency_id, Integer, :required => true
- property :party_id, Integer, :required => true
- property :forenames, String, :required => true
- property :surname, String, :required => true
- property :address, String, :length => 200
- property :postcode, String
- property :votes_2010, Integer
- property :votes_2005, Integer
- property :percent_2005, Float
-
-
- belongs_to :party
- belongs_to :constituency
- end
-
- class Constituency
- include DataMapper::Resource
-
- property :id, Serial
- property :name, String, :required => true
-
- has n, :wards, :order => ['name']
- has n, :parliamentcandidates, :order => ['surname']
- end
-
- DataMapper.setup(:default, ENV['DATABASE_URL'] || "postgres://postgres@localhost:5432/suttonelections")
- DataMapper.auto_upgrade!
|