Skip to content

Commit

Permalink
Added a database to record tag clouds over time.
Browse files Browse the repository at this point in the history
Squashed commit of the following:

commit 11fe49ef19cab7e63e175f600a2f48d8dbe645f8
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 17:24:38 2009 +0000

    title & positioning tweak

commit 4ec8014cf3a5abbd7de8be56fae4a586151122b2
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 17:15:38 2009 +0000

    store cloud only if text has changed since last time

commit 3ab4b6c1762ff6fb82813253a8322f90374edba9
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 15:59:14 2009 +0000

    moved cloud text method to a new method on mp

commit cd5a5829e3d8f838b76f889e1714e12eba417f6f
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 15:37:00 2009 +0000

    added machinist plugin

commit a80783d3778e2d078bd9fd2eacfed2a69740d8ee
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 15:33:39 2009 +0000

    show mp's last cloud

commit 3ea2f9b565b2fc09bc2ff578368977bef9e53210
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 15:33:21 2009 +0000

    cloud has terms

commit b3bb8d95f4d7f213e15621cf0af92c02248f51c3
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 15:16:52 2009 +0000

    renamed word to term

commit 567163d1dc3c6ef8d1409cc2202e550b60d60861
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 14:57:23 2009 +0000

    refactoring

commit 2447d728a2e0ef92a60380775dfc8e06e08dba5a
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 14:45:34 2009 +0000

    annotated

commit 1fb7535f73ab9cfa7e9a597c0de5b1c802cad7dc
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 14:45:24 2009 +0000

    rails *really* doesn't like having a model with an 'instantiate' class method

commit 944d1832dfb37b148cd0ce8a9bb8cd6f2e4137ae
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 14:44:50 2009 +0000

    mp spec

commit 79b48bb4ef3d6622a28511fbc076a1d756d3d027
Author: David Salgado <david@digitalronin.com>
Date:   Sat Mar 28 14:44:44 2009 +0000

    deleted

commit 01ee2c605196dbf230b04100b119dc8f9073295a
Author: David Salgado <david@digitalronin.com>
Date:   Mon Mar 23 00:06:21 2009 +0000

    Cloud is now an active_record model

commit fea3dc644f789a9dab732fe669d49a3d0a2d2de0
Author: David Salgado <david@digitalronin.com>
Date:   Mon Mar 23 00:00:01 2009 +0000

    MP is now an active_record model

commit d637e3a734ac23dd027147b55e838e4209fc1b23
Author: David Salgado <david@digitalronin.com>
Date:   Sun Mar 22 23:51:56 2009 +0000

    Converted Word class to ActiveRecord model

commit 31bfd8d1cb9c4e8d52183da6a1bbb228c4d70c3f
Author: David Salgado <david@digitalronin.com>
Date:   Sun Mar 22 23:47:57 2009 +0000

    fixed broken spec task

commit e7a97b032ba867a9e95f6906bf497e6dc3d73dc7
Author: David Salgado <david@digitalronin.com>
Date:   Sun Mar 22 19:58:00 2009 +0000

    added models
  • Loading branch information
digitalronin committed Mar 28, 2009
1 parent 0dc568b commit 085f908
Show file tree
Hide file tree
Showing 38 changed files with 1,400 additions and 122 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ public/stylesheets/parlour_tag.css
public/stylesheets/common.css
public/mps.html
public/mps
db/schema.rb
tags
12 changes: 6 additions & 6 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper

def cloud_tag(word)
style = "font-size: #{(word.size_factor * 100).round / 100.0}em;"
style << " color: ##{word.colour};"
style << " left: #{word.x}px;"
style << " top: #{word.y}px"
def cloud_tag(term)
style = "font-size: #{(term.size_factor * 100).round / 100.0}em;"
style << " color: ##{term.colour};"
style << " left: #{term.x}px;"
style << " top: #{term.y}px"

%[<li class='word' style="#{style}">#{word.text}</li>\n]
%[<li class='term' style="#{style}">#{term.text}</li>\n]
end

end
29 changes: 19 additions & 10 deletions app/models/cloud.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
class Cloud
attr_accessor :title, :words
# == Schema Information
# Schema version: 20090322184246
#
# Table name: clouds
#
# id :integer(4) not null, primary key
# mp_id :integer(4)
# created_at :datetime
# updated_at :datetime
#

class Cloud < ActiveRecord::Base
belongs_to :mp
has_many :terms

def initialize(params)
@mp = params[:mp]
@title = "#{@mp.full_name} Written Questions"
tc = TextChunk.new text
@words = tc.terms_with_counts
super params
tc = TextChunk.new mp.text_for_cloud
self.terms = tc.terms_with_counts
end

private

def text
@text ||= @mp.written_answer_text
def title
"#{mp.full_name} Written Questions"
end

end
78 changes: 61 additions & 17 deletions app/models/mp.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
# == Schema Information
# Schema version: 20090322184246
#
# Table name: mps
#
# id :integer(4) not null, primary key
# full_name :string(255)
# person_id :integer(4)
# constituency :string(255)
# party :string(255)
# written_questions_text :text
# created_at :datetime
# updated_at :datetime
#

require 'twfy'

class Mp
class Mp < ActiveRecord::Base
include Keys

attr_accessor :full_name, :person_id, :constituency, :party
has_many :clouds

validates_presence_of :full_name, :person_id
validates_numericality_of :person_id, :only_integer => true
validates_uniqueness_of :person_id

def self.fetch_list
RAILS_DEFAULT_LOGGER.info "Fetching MP list from TWFY"
objs = self.twfy_client.mps
mps = objs.collect do |obj|
self.instantiate obj
self.find_or_create_from_twfy obj
end
mps.sort {|a,b| a.surname <=> b.surname}
end
Expand All @@ -17,48 +36,73 @@ def self.twfy_client
Twfy::Client.new TWFY_API_KEY
end

def self.from_postcode(postcode)
client = self.twfy_client
mp = client.mp :postcode => postcode
self.instantiate obj
end
# def self.from_postcode(postcode)
# client = self.twfy_client
# mp = client.mp :postcode => postcode
# self.find_or_create_from_twfy obj
# end

# TWFY person_id
def self.from_person_id(person_id)
client = self.twfy_client
mp = client.mp :id => person_id
self.instantiate mp[0]
self.find_or_create_from_twfy mp[0]
end

def self.find_or_create_from_twfy(obj)
self.find_by_person_id(obj.person_id) || self.create_from_twfy(obj)
end

def self.instantiate(obj)
def self.create_from_twfy(obj)
mp = Mp.new
name = obj.respond_to?(:full_name) ? obj.full_name : obj.name
name = obj.name if name.blank?
mp.full_name = name
mp.person_id = obj.person_id
mp.party = obj.party
mp.constituency = obj.constituency.name
mp.save!
mp
end

def surname
@full_name.split(/ /)[-1]
full_name.to_s.split(/ /)[-1]
end

def to_param
"#{person_id}-#{@full_name.gsub(/ /, '-')}"
"#{person_id}-#{full_name.gsub(/ /, '-')}"
end

def get_cloud
cloud = self.clouds.last
return clouds.create if cloud.nil? or written_question_text_has_changed?
cloud
end

def cloud
@cloud ||= Cloud.new(:mp => self)
def text_for_cloud
return written_questions_text unless written_questions_text.blank?
self.written_questions_text = get_wrans
save!
self.written_questions_text
end

def written_answer_text
def get_wrans
RAILS_DEFAULT_LOGGER.info "Calling TWFY.wrans for MP:#{full_name}"
answers = twfy_client.wrans :person => person_id
answers.rows.inject("") {|text, row| text << row['body']}
end

private
def written_question_text_has_changed?
return true if written_questions_text.blank?
text = get_wrans
if self.written_questions_text != text
self.written_questions_text = text
save!
return true
else
return false
end
end

def twfy_client
@twfy_client ||= Twfy::Client.new TWFY_API_KEY
Expand Down
45 changes: 45 additions & 0 deletions app/models/term.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# == Schema Information
# Schema version: 20090322184246
#
# Table name: terms
#
# id :integer(4) not null, primary key
# text :string(255)
# value :integer(4)
# cloud_id :integer(4)
# created_at :datetime
# updated_at :datetime
#

class Term < ActiveRecord::Base
include PhraseCoordinates

belongs_to :cloud

OFFSET_FROM_TOP = 160
OFFSET_FROM_LEFT = 10

# distance from left in percentages
def x
OFFSET_FROM_LEFT + (coordinates.x * 700).to_i
end

# distance from top in percentages
def y
OFFSET_FROM_TOP + (coordinates.y * 700).to_i
end

def colour
phrase_colour
end

def size_factor
(Math.log(value) / Math.log(3) + 1) * 1.5
end

private

def coordinates
@coordinates ||= phrase_coordinates
end
end
8 changes: 4 additions & 4 deletions app/models/text_chunk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ def terms_with_counts
RAILS_DEFAULT_LOGGER.debug "Counting: #{term}, #{value}"
@max_count = [ @max_count, value ].max
@min_count = [ @min_count, value ].min
word = Word.new(term, value)
rtn << word
term = Term.new(:text => term, :value => value)
rtn << term
end
# Return words in descending order of occurrences, so that the
# biggest words are drawn on the page first, with smaller words
# Return terms in descending order of occurrences, so that the
# biggest terms are drawn on the page first, with smaller terms
# on top, to make it easier to read the tag cloud
rtn.sort {|a,b| a.value <=> b.value}.reverse
end
Expand Down
34 changes: 0 additions & 34 deletions app/models/word.rb

This file was deleted.

9 changes: 5 additions & 4 deletions app/views/mps/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
%p.back_link
=link_to 'back', mps_path

%h1= @mp.cloud.title

%h2= "#{@mp.party} MP for #{@mp.constituency}"
- cloud = @mp.get_cloud
%h1= cloud.title
%h3= "#{@mp.party} MP for #{@mp.constituency}"
%h2= "Updated on #{cloud.created_at.to_date.to_s(:db)}"

#cloud
%ul
= render :partial => @mp.cloud.words
= render :partial => cloud.terms

2 changes: 2 additions & 0 deletions app/views/terms/_term.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
= cloud_tag term

2 changes: 0 additions & 2 deletions app/views/words/_word.html.haml

This file was deleted.

31 changes: 31 additions & 0 deletions db/migrate/20090322184246_create_models.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
class CreateModels < ActiveRecord::Migration
def self.up

create_table :clouds do |t|
t.integer :mp_id
t.timestamps
end

create_table :terms do |t|
t.string :text
t.integer :value
t.integer :cloud_id
t.timestamps
end

create_table :mps do |t|
t.string :full_name
t.integer :person_id
t.string :constituency
t.string :party
t.text :written_questions_text
t.timestamps
end
end

def self.down
drop_table :mps
drop_table :terms
drop_table :clouds
end
end
4 changes: 2 additions & 2 deletions lib/phrase_coordinates.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ class Coordinate < Struct.new(:x, :y)
MAX_COORDINATE_VALUE = "ffff".hex.to_f

def phrase_coordinates
md5 = MD5::hexdigest(@text)
md5 = MD5::hexdigest(self.text)
x = md5[0, 4].hex / MAX_COORDINATE_VALUE
y = md5[4, 4].hex / MAX_COORDINATE_VALUE
Coordinate.new(x, y)
end

def phrase_colour
md5 = MD5::hexdigest(@text)
md5 = MD5::hexdigest(self.text)
r = md5[0,10].hex % 255
g = md5[11,20].hex % 255
b = md5[21,31].hex % 255
Expand Down
30 changes: 3 additions & 27 deletions lib/tasks/rspec.rake
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,8 @@ gem 'test-unit', '1.2.3' if RUBY_VERSION.to_f >= 1.9
# Don't load rspec if running "rake gems:*"
unless ARGV.any? {|a| a =~ /^gems/}

begin
require 'spec/rake/spectask'
rescue MissingSourceFile
module Spec
module Rake
class SpecTask
def initialize(name)
task name do
# if rspec-rails is a configured gem, this will output helpful material and exit ...
require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")

# ... otherwise, do this:
raise <<-MSG
#{"*" * 80}
* You are trying to run an rspec rake task defined in
* #{__FILE__},
* but rspec can not be found in vendor/gems, vendor/plugins or system gems.
#{"*" * 80}
MSG
end
end
end
end
end
end
require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
require 'spec/rake/spectask'

Rake.application.instance_variable_get('@tasks').delete('default')

Expand Down Expand Up @@ -162,4 +138,4 @@ namespace :spec do
end
end

end
end
Loading

0 comments on commit 085f908

Please sign in to comment.