Skip to content

Commit

Permalink
finish tech and civic life importing, create models for live site data
Browse files Browse the repository at this point in the history
  • Loading branch information
dougcole committed Mar 19, 2018
1 parent 8fac9a9 commit 6ef32dd
Show file tree
Hide file tree
Showing 30 changed files with 327 additions and 19 deletions.
2 changes: 2 additions & 0 deletions app/models/candidate.rb
@@ -0,0 +1,2 @@
class Candidate < ApplicationRecord
end
3 changes: 3 additions & 0 deletions app/models/techandciviclife/candidate.rb
@@ -0,0 +1,3 @@
class Techandciviclife::Candidate < ApplicationRecord
belongs_to :person, :primary_key => :internal_id
end
2 changes: 2 additions & 0 deletions app/models/techandciviclife/candidate_contest.rb
@@ -0,0 +1,2 @@
class Techandciviclife::CandidateContest < ApplicationRecord
end
2 changes: 2 additions & 0 deletions app/models/techandciviclife/candidate_selection.rb
@@ -0,0 +1,2 @@
class Techandciviclife::CandidateSelection < ApplicationRecord
end
3 changes: 3 additions & 0 deletions app/models/techandciviclife/electoral_district.rb
@@ -0,0 +1,3 @@
class Techandciviclife::ElectoralDistrict < ApplicationRecord
self.inheritance_column = 'unused'
end
2 changes: 2 additions & 0 deletions app/models/techandciviclife/office.rb
@@ -0,0 +1,2 @@
class Techandciviclife::Office < ApplicationRecord
end
3 changes: 3 additions & 0 deletions app/models/techandciviclife/party.rb
@@ -1,2 +1,5 @@
#workaround for https://github.com/rails/rails/issues/21476
require 'techandciviclife'

class Techandciviclife::Party < ApplicationRecord
end
2 changes: 1 addition & 1 deletion db/migrate/20180211182437_create_contests.rb
@@ -1,7 +1,7 @@
class CreateContests < ActiveRecord::Migration[5.1]
def change
create_table :contests do |t|
t.string "name"
t.string :name
t.timestamps
end
end
Expand Down
6 changes: 5 additions & 1 deletion db/migrate/20180214002402_create_techandciviclife_parties.rb
@@ -1,8 +1,12 @@
class CreateTechandciviclifeParties < ActiveRecord::Migration[5.1]
def change
create_table :techandciviclife_parties do |t|

t.text "internal_id"
t.text "name"
t.timestamps
end

add_index(:techandciviclife_parties, :internal_id, unique: true)
add_index(:techandciviclife_parties, :name, unique: true)
end
end
4 changes: 3 additions & 1 deletion db/migrate/20180214002416_create_techandciviclife_people.rb
@@ -1,8 +1,10 @@
class CreateTechandciviclifePeople < ActiveRecord::Migration[5.1]
def change
create_table :techandciviclife_people do |t|

t.text :internal_id
t.text :name
t.timestamps
end
add_index(:techandciviclife_people, :internal_id, unique: true)
end
end
12 changes: 12 additions & 0 deletions db/migrate/20180316005727_create_techandciviclife_candidates.rb
@@ -0,0 +1,12 @@
class CreateTechandciviclifeCandidates < ActiveRecord::Migration[5.1]
def change
create_table :techandciviclife_candidates do |t|
t.text :internal_id, null: false
t.text :person_id, null: false
t.text :party_id
t.text :name
t.timestamps
end
add_index(:techandciviclife_candidates, :internal_id, unique: true)
end
end
@@ -0,0 +1,13 @@
class CreateTechandciviclifeCandidateContests < ActiveRecord::Migration[5.1]
def change
create_table :techandciviclife_candidate_contests do |t|
t.text :internal_id, null: false
t.text :name, null: false
t.text :candidate_selections, array: true, null: false, default: []
t.text :electoral_district_id, null: false
t.text :office_id, null: false
t.timestamps
end
add_index(:techandciviclife_candidate_contests, :internal_id, unique: true)
end
end
@@ -0,0 +1,11 @@
class CreateTechandciviclifeCandidateSelections < ActiveRecord::Migration[5.1]
def change
create_table :techandciviclife_candidate_selections do |t|
t.text :internal_id, null: false
t.text :candidate_ids, array: true, null: false, default: []
t.timestamps
end

add_index(:techandciviclife_candidate_selections, :internal_id, unique: true)
end
end
@@ -0,0 +1,13 @@
class CreateTechandciviclifeElectoralDistricts < ActiveRecord::Migration[5.1]
def change
create_table :techandciviclife_electoral_districts do |t|

t.text :internal_id, null: false
t.text :name, null: false
t.text :type, null: false
t.timestamps
end

add_index(:techandciviclife_electoral_districts, :internal_id, unique: true)
end
end
14 changes: 14 additions & 0 deletions db/migrate/20180316201754_create_techandciviclife_offices.rb
@@ -0,0 +1,14 @@
class CreateTechandciviclifeOffices < ActiveRecord::Migration[5.1]
def change
create_table :techandciviclife_offices do |t|

t.text :internal_id, null: false
t.text :name, null: false
t.text :description, null: false
t.text :electoral_district_id, null: false
t.timestamps
end

add_index(:techandciviclife_offices, :internal_id, unique: true)
end
end
12 changes: 12 additions & 0 deletions db/migrate/20180316222346_create_candidates.rb
@@ -0,0 +1,12 @@
class CreateCandidates < ActiveRecord::Migration[5.1]
def change
create_table :candidates do |t|
t.text :primary_name
t.text :primary_party
t.text :secondary_name
t.text :secondary_party
t.text :candidate_selection_id
t.timestamps
end
end
end
9 changes: 9 additions & 0 deletions db/migrate/20180316223038_add_contest_columns.rb
@@ -0,0 +1,9 @@
class AddContestColumns < ActiveRecord::Migration[5.1]
def change
add_column :contests, :office_name, :text
add_column :contests, :office_description, :text
add_column :contests, :candidate_contest_id, :text
add_column :contests, :electoral_district_name, :text
add_column :contests, :electoral_district_type, :text
end
end
125 changes: 109 additions & 16 deletions lib/techandciviclife_parser.rb
Expand Up @@ -2,20 +2,20 @@ module Techandciviclife
class Parser

TOP_LEVEL_NODES = %w(
Party
Office
Person
Party
Candidate
CandidateContest
CandidateSelection
ElectoralDistrict
)
=begin
Person
Candidate
BallotMeasureContest
ElectoralDistrict
BallotMeasureContest - nope
Office
CandidateSelection
CandidateContest
Party
BallotMeasureSelection
Selection
RetentionContest
BallotMeasureSelection - nope
Selection - what?
RetentionContest - nope
)
=end

Expand All @@ -25,11 +25,12 @@ def reader

def run
t = Time.now
clean!
unknown_node_names = Set.new
reader.each do |node|
if node.node_type != Nokogiri::XML::Reader::TYPE_END_ELEMENT
if node.name.in?(TOP_LEVEL_NODES)
Techandciviclife::Parsers.const_get(node.name).new.parse(node)
Techandciviclife::Parsers.const_get(node.name).new(node).parse
else
unknown_node_names.add(node.name)
end
Expand All @@ -38,14 +39,106 @@ def run
puts "skipped unknown nodes: #{unknown_node_names.inspect}"
puts "finished in: #{Time.now - t} seconds"
end

def clean!
::Techandciviclife::Party.delete_all
::Techandciviclife::Person.delete_all
::Techandciviclife::Candidate.delete_all
::Techandciviclife::CandidateContest.delete_all
::Techandciviclife::CandidateSelection.delete_all
::Techandciviclife::ElectoralDistrict.delete_all
::Techandciviclife::Office.delete_all
end
end

module Parsers
class Party
def parse(node)
id = node.attribute('id')
name = Nokogiri::XML(node.outer_xml).xpath("//Party/Name/Text[@language='en']").text

class Base
attr_reader :node, :xml, :id

def initialize(node)
@node = node
@xml = Nokogiri::XML(node.outer_xml)
@id = node.attribute('id')
end
end

class Party < Base
def parse
name = xml.xpath("//Party/Name/Text[@language='en']").text
::Techandciviclife::Party.create!(name: name, internal_id: id)
end
end

#Maybe redundant... can we just use the Candidate name and ignore this?
class Person < Base
def parse
name = xml.xpath("//Person/FullName/Text[@language='en']").text
puts [id, name]
::Techandciviclife::Person.create!(name: name, internal_id: id)
end
end

class Candidate < Base
def parse
person_id = xml.xpath("//Candidate/PersonId").text
party_id = xml.xpath("//Candidate/PartyId").text
name = xml.xpath("//Candidate/BallotName/Text[@language='en']").text
puts [id, person_id, party_id, name]
::Techandciviclife::Candidate.create!(name: name, internal_id: id, party_id: party_id, person_id: person_id)
end
end

class CandidateContest < Base
def parse
name = xml.xpath("//CandidateContest/Name").text
candidate_selections = xml.xpath("//CandidateContest/BallotSelectionIds").
text.to_s.split(' ')
electoral_district_id = xml.xpath("//CandidateContest/ElectoralDistrictId").text
office_id = xml.xpath("//CandidateContest/OfficeIds").text
::Techandciviclife::CandidateContest.create!(
name: name,
internal_id: id,
candidate_selections: candidate_selections,
electoral_district_id: electoral_district_id,
office_id: office_id
)
end
end

class CandidateSelection < Base
def parse
candidate_ids = xml.xpath("//CandidateSelection/CandidateIds").text.to_s.split(' ')
::Techandciviclife::CandidateSelection.create!(
candidate_ids: candidate_ids,
internal_id: id
)
end
end

class ElectoralDistrict < Base
def parse
name = xml.xpath("//ElectoralDistrict/Name").text
type = xml.xpath("//ElectoralDistrict/Type").text
::Techandciviclife::ElectoralDistrict.create!(
name: name,
internal_id: id,
type: type
)
end
end

class Office < Base
def parse
description = xml.xpath("//Office/Description/Text[@language='en']").text
electoral_district_id = xml.xpath("//Office/ElectoralDistrictId").text
name = xml.xpath("//Office/Name/Text[@language='en']").text
::Techandciviclife::Office.create!(
description: description,
internal_id: id,
electoral_district_id: electoral_district_id,
name: name
)
end
end
end
Expand Down
11 changes: 11 additions & 0 deletions test/fixtures/candidates.yml
@@ -0,0 +1,11 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
11 changes: 11 additions & 0 deletions test/fixtures/techandciviclife/candidate_contests.yml
@@ -0,0 +1,11 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
11 changes: 11 additions & 0 deletions test/fixtures/techandciviclife/candidate_selections.yml
@@ -0,0 +1,11 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
11 changes: 11 additions & 0 deletions test/fixtures/techandciviclife/candidates.yml
@@ -0,0 +1,11 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
11 changes: 11 additions & 0 deletions test/fixtures/techandciviclife/electoral_districts.yml
@@ -0,0 +1,11 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
11 changes: 11 additions & 0 deletions test/fixtures/techandciviclife/offices.yml
@@ -0,0 +1,11 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
7 changes: 7 additions & 0 deletions test/models/candidate_test.rb
@@ -0,0 +1,7 @@
require 'test_helper'

class CandidateTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end
7 changes: 7 additions & 0 deletions test/models/techandciviclife/candidate_contest_test.rb
@@ -0,0 +1,7 @@
require 'test_helper'

class Techandciviclife::CandidateContestTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end

0 comments on commit 6ef32dd

Please sign in to comment.