Skip to content

Commit

Permalink
Proof of concept charting working again, with balances displayed on t…
Browse files Browse the repository at this point in the history
…he left
  • Loading branch information
konklone committed Feb 28, 2010
1 parent 6a7b256 commit aac9f14
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 14 deletions.
16 changes: 6 additions & 10 deletions Rakefile
Expand Up @@ -4,6 +4,9 @@ task :migrate => :environment do
ActiveRecord::Migrator.migrate 'migrations', (ENV['version'] ? ENV['version'].to_i : nil) ActiveRecord::Migrator.migrate 'migrations', (ENV['version'] ? ENV['version'].to_i : nil)
end end


def all_models
[User, Account, Day]
end


namespace :fixtures do namespace :fixtures do


Expand All @@ -26,18 +29,11 @@ task :environment do
require 'ohnomymoney' require 'ohnomymoney'
end end


def all_models
[User, Account, Day]
end

def fixture_dir
"fixtures"
end


def restore_fixture(model) def restore_fixture(model)
model.delete_all model.delete_all


YAML::load_file("#{fixture_dir}/#{model.table_name}.yml").each do |row| YAML::load_file("fixtures/#{model.table_name}.yml").each do |row|
record = model.new record = model.new
row.keys.each do |field| row.keys.each do |field|
record[field] = row[field] if row[field] record[field] = row[field] if row[field]
Expand All @@ -57,8 +53,8 @@ def dump_fixture(model)
records << element records << element
end end


FileUtils.mkdir_p fixture_dir FileUtils.mkdir_p "fixtures"
File.open("#{fixture_dir}/#{model.table_name}.yml", "w") do |file| File.open("fixtures/#{model.table_name}.yml", "w") do |file|
YAML.dump data, file YAML.dump data, file
end end


Expand Down
78 changes: 78 additions & 0 deletions charting.rb
@@ -0,0 +1,78 @@
require 'google_chart'

helpers do

def chart_for(days)
oldest = days.first
newest = days[days.size-1]
balances = days.map {|day| day.balance}

min = balances.min
max = balances.max
disparity = max - min
y = (disparity * 1.66).to_i
buffer = (y - disparity) / 2

y_min = round(min - buffer)
y_max = round(max + buffer)
y = y_max - y_min
y_step = round(y / 10.0, 2)

x_step = days.size / 7
x_step = 1 if x_step < 1
x_days = []
days.each_with_index {|b, i| x_days << b if i % x_step == 0}
x_days[0] = days[0]
x_days[-1] = days[-1]

y_labels = (0..10).map {|i| format_balance(y_min + (y_step * i))}
x_labels = x_days.map {|day| format_date day.date_of}

label = newest.balance > 0 ? 'Money' : 'Debt'
data = balances.map {|balance| (balance - y_min).to_f}
color = newest.balance > 0 ? '008800' : 'cc0000'

chart = GoogleChart::LineChart.new '857x350'
chart.data_encoding = :text
chart.max_value y
chart.data label, data, color
chart.axis :x, :labels => x_labels
chart.axis :y, :labels => y_labels
chart.axis :right, :labels => y_labels

p chart.to_url(:chdlp => 'b')
chart.to_url :chdlp => 'b'
end

def round(n, level = 3)
(n - (n % (10**level))).to_i
end

def double_encode(text)
text.gsub("&", "&amp;")
end

def format_balance(balance)
number = balance.to_f / 100
parts = ("%01.2f" % number).split('.')
answer = '$' + number_with_delimiter(parts[0]) + '.' + parts[1].to_s
if number > 0
answer = '+' + answer
elsif number < 0
answer = '-' + answer
end
answer
end

def number_with_delimiter(number)
number = number.to_i.abs
parts = number.to_s.split('.')
parts[0].gsub! /(\d)(?=(\d\d\d)+(?!\d))/, "\\1,"
parts.join '.'
end

def format_date(date)
date.strftime("%B ") + date.strftime("%d").gsub(/^0/, "")
end

end
4 changes: 2 additions & 2 deletions fixtures/accounts.yml
Expand Up @@ -20,12 +20,12 @@
- name: Credit Card - name: Credit Card
created_at: 2010-02-15 01:55:20 -05:00 created_at: 2010-02-15 01:55:20 -05:00
updated_at: 2010-02-15 02:23:49 -05:00 updated_at: 2010-02-15 02:23:49 -05:00
account_type: debt account_type: debts
id: 4 id: 4
user_id: 1 user_id: 1
- name: Student Loans - name: Student Loans
created_at: 2010-02-15 01:57:24 -05:00 created_at: 2010-02-15 01:57:24 -05:00
updated_at: 2010-02-15 02:23:55 -05:00 updated_at: 2010-02-15 02:23:55 -05:00
account_type: debt account_type: debts
id: 5 id: 5
user_id: 1 user_id: 1
9 changes: 8 additions & 1 deletion models.rb
Expand Up @@ -6,7 +6,7 @@ class Day < ActiveRecord::Base
end end


class Account < ActiveRecord::Base class Account < ActiveRecord::Base
TYPES = %w( worth assets debt ) TYPES = %w( worth assets debts )


belongs_to :user belongs_to :user
has_many :days has_many :days
Expand All @@ -15,10 +15,17 @@ class Account < ActiveRecord::Base
validates_presence_of :user_id validates_presence_of :user_id
validates_inclusion_of :account_type, :in => TYPES validates_inclusion_of :account_type, :in => TYPES


named_scope :worth, :conditions => {:account_type => 'worth'}
named_scope :assets, :conditions => {:account_type => 'assets'}
named_scope :debts, :conditions => {:account_type => 'debts'}


def needs_name def needs_name
account_type != 'worth' account_type != 'worth'
end end

def balance
days.count > 0 ? days.first(:order => "created_at DESC").balance : 0
end
end end


class User < ActiveRecord::Base class User < ActiveRecord::Base
Expand Down
10 changes: 9 additions & 1 deletion ohnomymoney.rb
Expand Up @@ -4,6 +4,9 @@
require 'sinatra' require 'sinatra'
require 'environment' require 'environment'


require 'erb'
require 'charting'

# For now, have the root URL act as if we visited the userpage of the first user # For now, have the root URL act as if we visited the userpage of the first user
before do before do
request.path_info = "/#{User.first.handle}" if request.path_info == '/' request.path_info = "/#{User.first.handle}" if request.path_info == '/'
Expand All @@ -12,5 +15,10 @@
get "/:handle" do get "/:handle" do
halt 404 unless user = User.find_by_handle(params[:handle]) halt 404 unless user = User.find_by_handle(params[:handle])


user.accounts.all.map(&:name).join("<br/>\n") erb :index, :locals => {
:user => user,
:worth => user.accounts.worth.first,
:assets => user.accounts.assets.all,
:debts => user.accounts.debts.all
}
end end
29 changes: 29 additions & 0 deletions views/index.erb
@@ -0,0 +1,29 @@
<!doctype html>
<html>
<head>
<title><%= user.name %>'s Money</title>
</head>
<body>

<h1><%= user.name %>'s Money</h1>

<div class="sidebar">
<div class="account worth">
<h2>Net Worth</h2>
<span><%= worth.balance %></span>
</div>

<% (assets + debts).each do |account| %>
<div class="account <%= account.account_type %>">
<h2><%= account.name %></h2>
<span><%= account.balance %></span>
</div>
<% end %>
</div>

<div class="main">
<img src="<%= double_encode chart_for(worth.days.all(:limit => 10)) %>" />
</div>

</body>
</html>

0 comments on commit aac9f14

Please sign in to comment.