forked from igorman/data-engineering
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.rb
150 lines (93 loc) · 2.96 KB
/
app.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
%w( rubygems sinatra data_mapper dm-sqlite-adapter haml ).each do |dep|
require dep
end
# Setup database
configure do
DataMapper.setup(:default, "sqlite://#{Dir.pwd}/customer_data.db")
DataMapper::Logger.new(STDOUT, :debug)
end
# Define Models
class Item
include DataMapper::Resource
property :id, Serial
property :description, String
property :price_in_cents, Integer
property :purchase_count, Integer, default: 0
# Assocations
belongs_to :merchant
has n, :purchasers, through: Resource
end
class Merchant
include DataMapper::Resource
property :id, Serial
property :name, String
property :address, String
has n, :items
end
class Purchaser
include DataMapper::Resource
property :id, Serial
property :given_name, String
property :family_name, String
has n, :items, through: Resource
end
DataMapper.finalize
DataMapper.auto_migrate!
# Render the form to the user w/ upload instructions
get '/' do
haml :index
end
# Process the data and render results
post '/' do
# Read and parse the uploaded file
file_contents = params['file'][:tempfile].read
# Separate into rows, then columns
rows = file_contents.split("\n").map { |row| row.split("\t") }
# Grab the headers for display of results
headers = rows.shift
# Save the data - quick n' dirty
rows.each do |row|
# Align the headers with the data so that we can see what's happening!
# e.g. [:some, 'thing'] => { some: 'thing' }
mapped_row = Hash[*headers.zip(row).flatten]
given_name, family_name = mapped_row['purchaser name'].split(' ')
purchaser = Purchaser.first_or_create({
given_name: given_name,
family_name: family_name
})
merchant = Merchant.first_or_create({
name: mapped_row['merchant name'],
address: mapped_row['merchant address']
})
item = Item.first_or_create({
description: mapped_row['item description'],
price_in_cents: mapped_row['item price'].to_i * 100,
merchant_id: merchant.id
})
# Update the purchase count
item.purchase_count += mapped_row['purchase count'].to_i
item.save
# Add the item to the purchaser
purchaser.items << item
purchaser.save
end
# Calculate total revenue
revenue_in_cents = Item.reduce(0) do |sum, item|
sum += item.price_in_cents*item.purchase_count
end
# Formatting logic borrowed from http://mikepence.wordpress.com/2007/05/05/formatting-us-dollars-with-ruby/
@revenue = sprintf('$%0.2f', revenue_in_cents/100.0)
# Re-render the view
haml :index
end
enable :inline_templates
__END__
@@index
!!!
%html
%body
%h2 Please upload your tabular data file
%form{ action: "/", enctype: "multipart/form-data", method: "POST" }
%input{ type: "file", name: "file" }
%input{ type: "submit" }
= "<h1>Gross Revenue: #{@revenue}</h1>" if @revenue