Election results in the London Borough of Sutton.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

237 lines
7.4 KiB

  1. require 'data_mapper'
  2. class Poll
  3. include DataMapper::Resource
  4. property :district_id, Integer, :key => true
  5. property :election_id, Integer, :key => true
  6. property :electorate, Integer # The number of people eligible to vote in this district in this election
  7. property :ballot_papers_issued, Integer # The number of ballot papers issued (includes spoiled ballots)
  8. property :seats, Integer, :required => true # The number of seats to be elected in this district in this election
  9. def turnout_percent
  10. @ballot_papers_issued.to_f / @electorate.to_f * 100.0
  11. end
  12. end
  13. class Postcode
  14. include DataMapper::Resource
  15. # Postcode natural key, uppercase with space, eg. "SM1 1EA"
  16. # Column names derived from Ordnance Survey CodePoint Open
  17. property :postcode, String, :key => true
  18. property :positional_quality_indicator, Integer
  19. property :eastings, Integer, :required => true
  20. property :northings, Integer, :required => true
  21. property :country_code, String, :required => true
  22. property :nhs_regional_ha_code, String, :required => true
  23. property :nhs_ha_code, String, :required => true
  24. property :admin_county_code, String # NULL within Greater London
  25. property :admin_district_code, String, :required => true # e.g. London Borough of Sutton
  26. property :admin_ward_code, String, :required => true # e.g. Sutton Central
  27. property :lat, Float, :required => true
  28. property :lng, Float, :required => true
  29. property :ward_id, Integer, :required => true # Sutton Council
  30. property :constituency_id, Integer, :required => false # UK Parliament
  31. belongs_to :district, :child_key => [:ward_id]
  32. def self.finder(postcode)
  33. postcode = postcode.strip.upcase
  34. if o = self.get(postcode)
  35. return o
  36. end
  37. result = Pat.get(postcode)
  38. unless result.code == 404
  39. # cache API result
  40. self.create(
  41. :postcode => postcode,
  42. :lat => result['geo']['lat'],
  43. :lng => result['geo']['lng'],
  44. :district_name => result['administrative']['district']['title'],
  45. :district_code => result['administrative']['district']['uri'].match(/.+\/(.+)$/)[1],
  46. :ward_name => result['administrative']['ward']['title'],
  47. :ward_code => result['administrative']['ward']['uri'].match(/.+\/(.+)$/)[1]
  48. )
  49. else
  50. # invalid postcode
  51. nil
  52. end
  53. end
  54. end
  55. class Candidate
  56. include DataMapper::Resource
  57. property :id, Serial
  58. property :forenames, String, :required => true
  59. property :surname, String, :required => true, :index => true
  60. property :sex, String
  61. has n, :candidacies
  62. def short_name
  63. @forenames.split(' ')[0] + ' ' + @surname
  64. end
  65. def name
  66. @forenames + ' ' + @surname
  67. end
  68. end
  69. class Candidacy
  70. include DataMapper::Resource
  71. property :id, Serial
  72. property :election_id, Integer, :required => true
  73. property :candidate_id, Integer, :required => true
  74. property :party_id, Integer
  75. property :district_id, Integer, :required => true
  76. property :votes, Integer
  77. property :address, String, :length => 200
  78. property :postcode, String
  79. property :position, Integer # Position of this candidate in this district. (1..n)
  80. property :seats, Integer # Number of seats won by this candidacy (0 or 1)
  81. property :labcoop, Boolean, :default => false # Candidacy is for joint Labour/Co-op party
  82. belongs_to :election
  83. belongs_to :candidate
  84. belongs_to :party
  85. belongs_to :district
  86. end
  87. class Election
  88. include DataMapper::Resource
  89. property :id, Serial
  90. property :body_id, Integer, :required => true
  91. property :d, Date, :required => true, :index => true
  92. property :reason, String, :length => 255
  93. property :kind, String, :length => 255
  94. has n, :candidacies
  95. belongs_to :body
  96. def self.past
  97. self.all(:d.lt => Time.now.to_s, :order => [ :d.desc ])
  98. end
  99. def self.future
  100. self.all(:d.gte => Time.now.to_s, :order => [ :d.desc ])
  101. end
  102. end
  103. class District
  104. include DataMapper::Resource
  105. property :id, Serial
  106. property :body_id, Integer, :required => true
  107. property :name, String, :length => 255, :required => true
  108. property :slug, String
  109. property :seats, Integer
  110. property :ons_district_code, String
  111. belongs_to :body
  112. has n, :postcodes, :child_key => [:ward_id]
  113. def self.slugify(name)
  114. name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase
  115. end
  116. end
  117. class Body
  118. include DataMapper::Resource
  119. property :id, Serial
  120. property :name, String, :length => 255, :required => true
  121. property :district_name, String, :length => 255, :required => true # singular
  122. property :districts_name, String, :length => 255, :required => true # plural
  123. property :slug, String, :length => 255
  124. has n, :elections
  125. has n, :districts
  126. end
  127. class Party
  128. include DataMapper::Resource
  129. property :id, Serial
  130. property :name, String, :required => true
  131. property :colour, String
  132. has n, :candidacies
  133. end
  134. # These models are now redundant
  135. class Ward
  136. include DataMapper::Resource
  137. property :id, Serial
  138. property :slug, String, :required => true
  139. property :ons_id, String, :required => true
  140. property :name, String, :required => true
  141. property :constituency_id, Integer, :required => true
  142. has n, :councilcandidates, :order => ['surname']
  143. belongs_to :constituency
  144. def self.slugify(name)
  145. name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase
  146. end
  147. end
  148. class Councilcandidate
  149. include DataMapper::Resource
  150. property :id, Serial
  151. property :ward_id, Integer, :required => true
  152. property :party_id, Integer, :required => true
  153. property :forenames, String, :required => true
  154. property :surname, String, :required => true
  155. property :address, String, :length => 200
  156. property :postcode, String, :required => true
  157. property :votes_2010, Integer
  158. belongs_to :party
  159. belongs_to :ward
  160. end
  161. class Parliamentcandidate
  162. include DataMapper::Resource
  163. property :id, Serial
  164. property :constituency_id, Integer, :required => true
  165. property :party_id, Integer, :required => true
  166. property :forenames, String, :required => true
  167. property :surname, String, :required => true
  168. property :address, String, :length => 200
  169. property :postcode, String
  170. property :votes_2010, Integer
  171. property :votes_2005, Integer
  172. property :percent_2005, Float
  173. belongs_to :party
  174. belongs_to :constituency
  175. end
  176. class Constituency
  177. include DataMapper::Resource
  178. property :id, Serial
  179. property :name, String, :required => true
  180. has n, :wards, :order => ['name']
  181. has n, :parliamentcandidates, :order => ['surname']
  182. end
  183. DataMapper.setup(:default, ENV['DATABASE_URL'] || "postgres://postgres@localhost:5432/suttonelections")
  184. DataMapper.auto_upgrade!