daily 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.mdown +46 -0
  3. data/Rakefile +7 -0
  4. data/app/assets/images/rails.png +0 -0
  5. data/app/assets/javascripts/application.js +9 -0
  6. data/app/assets/stylesheets/application.css +16 -0
  7. data/app/assets/stylesheets/bootstrap.css +2467 -0
  8. data/app/controllers/application_controller.rb +14 -0
  9. data/app/controllers/files_controller.rb +5 -0
  10. data/app/controllers/main_controller.rb +5 -0
  11. data/app/controllers/reports_controller.rb +35 -0
  12. data/app/controllers/tables_controller.rb +20 -0
  13. data/app/controllers/users_controller.rb +28 -0
  14. data/app/formatters/html_formatter.rb +65 -0
  15. data/app/formatters/json_formatter.rb +81 -0
  16. data/app/helpers/application_helper.rb +85 -0
  17. data/app/jobs/generate_report_job.rb +13 -0
  18. data/app/models/report.rb +112 -0
  19. data/app/models/table.rb +65 -0
  20. data/app/models/user.rb +20 -0
  21. data/app/transforms/column_filter.rb +7 -0
  22. data/app/transforms/moving_average.rb +119 -0
  23. data/app/transforms/transform.rb +32 -0
  24. data/app/views/devise/sessions/new.erb +15 -0
  25. data/app/views/layouts/application.html.erb +40 -0
  26. data/app/views/main/home.erb +4 -0
  27. data/app/views/reports/_form.erb +14 -0
  28. data/app/views/reports/_list.erb +9 -0
  29. data/app/views/reports/edit.erb +2 -0
  30. data/app/views/reports/index.erb +3 -0
  31. data/app/views/reports/new.erb +2 -0
  32. data/app/views/reports/show.erb +23 -0
  33. data/app/views/tables/_form.erb +8 -0
  34. data/app/views/tables/_list.erb +9 -0
  35. data/app/views/tables/edit.erb +2 -0
  36. data/app/views/tables/index.erb +3 -0
  37. data/app/views/tables/new.erb +2 -0
  38. data/app/views/tables/show.erb +35 -0
  39. data/app/views/users/_form.erb +5 -0
  40. data/app/views/users/_items.erb +8 -0
  41. data/app/views/users/_list.erb +9 -0
  42. data/app/views/users/edit.erb +2 -0
  43. data/app/views/users/index.erb +3 -0
  44. data/app/views/users/new.erb +2 -0
  45. data/app/views/users/show.erb +4 -0
  46. data/config/application.rb +52 -0
  47. data/config/authorization_rules.rb +49 -0
  48. data/config/boot.rb +6 -0
  49. data/config/daily.example.yml +19 -0
  50. data/config/daily.yml +27 -0
  51. data/config/database.yml +25 -0
  52. data/config/environment.rb +5 -0
  53. data/config/environments/development.rb +32 -0
  54. data/config/environments/production.rb +63 -0
  55. data/config/environments/test.rb +39 -0
  56. data/config/initializers/backtrace_silencers.rb +7 -0
  57. data/config/initializers/devise.rb +212 -0
  58. data/config/initializers/inflections.rb +10 -0
  59. data/config/initializers/mime_types.rb +5 -0
  60. data/config/initializers/ruport.rb +5 -0
  61. data/config/initializers/secret_token.rb +7 -0
  62. data/config/initializers/session_store.rb +8 -0
  63. data/config/initializers/simple_form.rb +113 -0
  64. data/config/initializers/wrap_parameters.rb +14 -0
  65. data/config/locales/devise.en.yml +58 -0
  66. data/config/locales/en.yml +5 -0
  67. data/config/locales/simple_form.en.yml +24 -0
  68. data/config/routes.rb +29 -0
  69. data/db/development.sqlite3 +0 -0
  70. data/db/migrate/20111109081414_devise_create_users.rb +28 -0
  71. data/db/migrate/20111111165640_create_tables.rb +14 -0
  72. data/db/migrate/20111112022333_add_name_to_tables.rb +9 -0
  73. data/db/migrate/20111112170802_add_reports.rb +15 -0
  74. data/db/migrate/20111113000026_add_guid_to_tables.rb +9 -0
  75. data/db/migrate/20111113073326_add_times_to_reports.rb +11 -0
  76. data/db/migrate/20111113075747_add_times_to_tables.rb +9 -0
  77. data/db/migrate/20111114041729_create_delayed_jobs.rb +21 -0
  78. data/db/migrate/20111114053016_add_report_to_delayed_jobs.rb +11 -0
  79. data/db/migrate/20111115014959_add_admin_to_users.rb +9 -0
  80. data/db/migrate/20111127065357_add_column_names_to_table.rb +9 -0
  81. data/db/migrate/20111203020425_add_transform_to_table.rb +16 -0
  82. data/db/migrate/20111214020029_add_formatter_data_to_reports.rb +8 -0
  83. data/db/schema.rb +80 -0
  84. data/db/seeds.rb +7 -0
  85. data/db/test.sqlite3 +0 -0
  86. data/lib/daily.rb +9 -0
  87. data/lib/daily/daily_config.rb +51 -0
  88. data/lib/daily/engine.rb +4 -0
  89. data/lib/daily/has_data.rb +52 -0
  90. data/lib/daily/shared_behaviors.rb +65 -0
  91. data/lib/daily/version.rb +3 -0
  92. data/lib/tasks/user.rake +24 -0
  93. metadata +454 -0
@@ -0,0 +1,65 @@
1
+ class Table < ActiveRecord::Base
2
+ include SharedBehaviors
3
+
4
+ belongs_to :user
5
+ has_many :reports
6
+
7
+ generate_guid :guid
8
+
9
+ validates_presence_of :user
10
+ validates_unique_presence_of :name
11
+ validates_stripped_presence_of :data
12
+ validates_stripped_presence_of :data_type
13
+
14
+ validate :data_type_known
15
+
16
+ serialize :column_names, Array
17
+
18
+ def sql?
19
+ data_type == "sql"
20
+ end
21
+
22
+ def result
23
+ fetch
24
+ end
25
+
26
+ def fetch
27
+ time = Time.now.to_i
28
+
29
+ out = fetch_data
30
+ out = apply_transform(out)
31
+
32
+ atts = {}
33
+ atts[:fetch_time_in_seconds] = Time.now.to_i - time
34
+ atts[:column_names] = out.column_names
35
+ self.attributes = atts
36
+ save unless new_record?
37
+
38
+ out
39
+ end
40
+
41
+ def test
42
+ # ouputs html of the table
43
+ begin
44
+ fetch.to_html.html_safe
45
+ rescue => e
46
+ out = "#{e.message}"
47
+ out += "\n\nTrace shown in development environment:\n#{e.backtrace.join("\n")}" if Rails.env.development?
48
+ out.gsub("\n", "<br/>").html_safe
49
+ end
50
+ end
51
+
52
+ protected
53
+ def data_type_known
54
+ return if data_type.blank?
55
+ unless sql?
56
+ errors.add(:data_type, "is not known")
57
+ end
58
+ end
59
+
60
+ def fetch_data
61
+ return Ruport::Query.new(data).result if sql?
62
+ Ruport::Data::Table.new
63
+ end
64
+
65
+ end
@@ -0,0 +1,20 @@
1
+ class User < ActiveRecord::Base
2
+ # Include default devise modules. Others available are:
3
+ # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
4
+ devise :database_authenticatable, :registerable,
5
+ :recoverable, :rememberable, :trackable, :validatable
6
+
7
+ # Setup accessible (or protected) attributes for your model
8
+ attr_accessible :email, :password, :password_confirmation, :remember_me
9
+
10
+ has_many :tables
11
+ has_many :reports
12
+
13
+ def role_symbols
14
+ return [] if new_record?
15
+
16
+ out = [:user]
17
+ out << :admin if admin?
18
+ out
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ class ColumnFilter < Transform
2
+ def result
3
+ to_remove = table.column_names - columns
4
+ table.remove_columns(to_remove)
5
+ table
6
+ end
7
+ end
@@ -0,0 +1,119 @@
1
+ class MovingAverage < Transform
2
+ def self.form_keys
3
+ [:columns, :days, :date]
4
+ end
5
+
6
+ def num_days
7
+ val = setting(:days).to_i
8
+ val <= 0 ? 7 : val
9
+ end
10
+
11
+ def date_column
12
+ setting(:date) || default_date_column || first_date_column
13
+ end
14
+
15
+ def result
16
+ cols = self.columns
17
+ datecol = self.date_column
18
+ daycount = self.num_days
19
+
20
+ avg_cols = cols.collect { |col| "#{col}_#{daycount}" }
21
+
22
+ out = Ruport::Data::Table.new( :column_names => [datecol] + cols + avg_cols)
23
+
24
+ data = day_data
25
+ days = data["days"]
26
+ first = data["earliest"]
27
+ latest = data["latest"]
28
+
29
+ current = first
30
+ while current <= latest do
31
+ row = {}
32
+ row[datecol] = current
33
+
34
+ cols.each do |col|
35
+ # this cols value for the day
36
+ value = 0
37
+ value = days[current][col].to_f if days[current]
38
+
39
+ # add them up
40
+ sum = 0
41
+ count = 0
42
+ check = current - daycount + 1
43
+ while check <= current
44
+ count += 1 unless check < first
45
+ sum += days[check][col].to_f if days[check]
46
+ check += 1
47
+ end
48
+
49
+ row["#{col}_#{daycount}"] = sum / count
50
+ row["#{col}"] = value
51
+ end
52
+
53
+ out << row
54
+ current += 1
55
+ end
56
+
57
+ out
58
+ end
59
+
60
+ protected
61
+
62
+ def self.to_day(time_or_date)
63
+ time = Time.zone.parse(time_or_date.strftime("%Y-%m-%d %H:%M:%S %z"))
64
+ Date.new(time.year, time.month, time.day)
65
+ end
66
+
67
+ def day_data
68
+ earliest = Date.new(2032,1,1)
69
+ latest = Date.new(1492,1,1)
70
+ datenum = column_name_hash[date_column]
71
+ cols = self.columns
72
+
73
+ days = {}
74
+
75
+ table.each do |row|
76
+ time = row[datenum]
77
+ day = self.class.to_day(time)
78
+ latest = day if day > latest
79
+ earliest = day if day < earliest
80
+
81
+ days[day] ||= {}
82
+ cols.each do |col|
83
+ index = column_name_hash[col]
84
+ if index
85
+ days[day][col] ||= 0
86
+ days[day][col] += row[index].to_f
87
+ end
88
+ end
89
+ end
90
+
91
+ {"days" => days, "earliest" => earliest, "latest" => latest}
92
+ end
93
+
94
+ def column_name_hash
95
+ return @column_name_hash if @column_name_hash
96
+ @column_name_hash = {}
97
+ table.column_names.each_with_index do |name, i|
98
+ @column_name_hash[name.to_s] = i
99
+ end
100
+ @column_name_hash
101
+ end
102
+
103
+ def default_date_column
104
+ ["created_at", "updated_at", "state_changed_at"].each do |col|
105
+ return col if column_name_hash[col]
106
+ end
107
+ return nil
108
+ end
109
+
110
+ def first_date_column
111
+ return nil if table.size == 0
112
+ table[0].each_with_index do |val, i|
113
+ if val.is_a? Date or val.is_a? Time
114
+ return table.column_names[i]
115
+ end
116
+ end
117
+ nil
118
+ end
119
+ end
@@ -0,0 +1,32 @@
1
+ class Transform
2
+ def self.transforms
3
+ [ColumnFilter, MovingAverage]
4
+ end
5
+
6
+ def self.display_name
7
+ name.demodulize.underscore.humanize.titleize
8
+ end
9
+ def self.form_keys
10
+ [:columns] # override to get more / different
11
+ end
12
+
13
+ attr_accessor :table
14
+ attr_accessor :settings
15
+ def initialize(table, settings)
16
+ self.table = table
17
+ self.settings = (settings || {}).symbolize_keys
18
+ end
19
+
20
+ def setting(key, default = nil)
21
+ val = settings[key.to_sym]
22
+ val.blank? ? default : val
23
+ end
24
+
25
+ def columns
26
+ setting(:columns, []).collect(&:to_s)
27
+ end
28
+
29
+ def result
30
+ raise("Transforms must override result")
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ <h2>Sign in</h2>
2
+
3
+ <%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
4
+ <div><%= f.label :email %><br />
5
+ <%= f.email_field :email %></div>
6
+
7
+ <div><%= f.label :password %><br />
8
+ <%= f.password_field :password %></div>
9
+
10
+ <% if devise_mapping.rememberable? -%>
11
+ <div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
12
+ <% end -%>
13
+
14
+ <div><%= f.submit "Sign in" %></div>
15
+ <% end %>
@@ -0,0 +1,40 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= page_title %></title>
5
+ <%= stylesheet_link_tag "application" %>
6
+ <%= javascript_include_tag "application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+ <div class="topbar">
11
+ <div class="fill">
12
+ <div class="container">
13
+ <a class="brand" href="<%= current_user ? user_root_path : root_path %>">Daily</a>
14
+ </div>
15
+ </div>
16
+ </div>
17
+
18
+ <div class="container">
19
+ <% if header_title %>
20
+ <h1><%= header_title %></h1>
21
+ <% end %>
22
+
23
+ <% if notice %>
24
+ <div class="alert-message success">
25
+ <p><%= notice %></p>
26
+ </div>
27
+ <% end %>
28
+
29
+ <% if alert %>
30
+ <div class="alert-message error">
31
+ <p><%= alert %></p>
32
+ </div>
33
+ <% end %>
34
+
35
+ <%= yield %>
36
+
37
+ </div>
38
+
39
+ </body>
40
+ </html>
@@ -0,0 +1,4 @@
1
+ <% title "Welcome #{current_user.email}" %>
2
+ <%= content_tag(:p, link_to("Update Account", account_path)) if permitted_to? :account, current_user %>
3
+
4
+ <%= render 'users/items', :user => current_user %>
@@ -0,0 +1,14 @@
1
+ <h3>Table: <%= link_to @report.table.name, table_path(@report.table) %></h3>
2
+
3
+ <%= simple_form_for [@report.table, @report] do |f| %>
4
+ <%= f.input :name %>
5
+ <%= f.input :filename unless @report.new_record? %>
6
+
7
+ <%= f.input :formatter, :collection => Report.formatters %>
8
+ <%= f.input :formatter_json, :as => :text %>
9
+
10
+ <%= f.input :transform, :collection => Transform.transforms, :label_method => :display_name, :value_method => :name %>
11
+ <%= f.input :transform_json, :as => :text %>
12
+
13
+ <%= f.button :submit %>
14
+ <% end %>
@@ -0,0 +1,9 @@
1
+ <% if list.size > 0 %>
2
+ <ul>
3
+ <% list.each do |report| %>
4
+ <% if permitted_to? :show, report %>
5
+ <li><%= link_to report.name, table_report_path(report.table, report) %></li>
6
+ <% end %>
7
+ <% end %>
8
+ </ul>
9
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <% title "Edit Report: #{@report.name}" %>
2
+ <%= render 'form' %>
@@ -0,0 +1,3 @@
1
+ <% title "Reports" %>
2
+
3
+ <%= render "reports/list", :list => @reports %>
@@ -0,0 +1,2 @@
1
+ <% title "New Report" %>
2
+ <%= render 'form' %>
@@ -0,0 +1,23 @@
1
+ <% title @report.name %>
2
+ <h3>Table: <%= link_to @report.table.name, table_path(@report.table) %></h3>
3
+
4
+ <% if @report.file_exists? %>
5
+ <h5>URL: <%= link_to @report.url(root_url), @report.url(root_url) %></h5>
6
+ <% else %>
7
+ <h5>URL: <%= @report.url(root_url) %></h5>
8
+ <% end %>
9
+
10
+ <h6>User: <%= "#{@report.user.email}" %></h6>
11
+ <h6>Running time: <%= report_time_run(@report) %></h6>
12
+ <h6>Last updated: <%= report_time_ago(@report) %></h6>
13
+ <h6>Next updated: <%= report_time_next(@report) %></h6>
14
+ <%= button_to "Queue Update Now", generate_table_report_path(@report.table, @report) if permitted_to? :generate, @report %>
15
+
16
+ <%= content_tag(:p, link_to("Edit", edit_table_report_path(@report.table, @report))) if permitted_to? :edit, @report %>
17
+
18
+ <%= formatter_display(@report) %>
19
+
20
+ <%= transform_display(@report) %>
21
+
22
+ <hr/>
23
+ <%= report_error_html(@report) %>
@@ -0,0 +1,8 @@
1
+ <%= simple_form_for @table do |f| %>
2
+ <%= f.input :name %>
3
+ <%= f.input :data %>
4
+
5
+ <%= f.input :transform, :collection => Transform.transforms, :label_method => :display_name, :value_method => :name %>
6
+ <%= f.input :transform_json, :as => :text %>
7
+ <%= f.button :submit %>
8
+ <% end %>
@@ -0,0 +1,9 @@
1
+ <% if list.size > 0 %>
2
+ <ul>
3
+ <% list.each do |table| %>
4
+ <% if permitted_to? :show, table %>
5
+ <li><%= link_to table.name, table %></li>
6
+ <% end %>
7
+ <% end %>
8
+ </ul>
9
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <% title "Edit Table: #{@table.name}" %>
2
+ <%= render 'form' %>
@@ -0,0 +1,3 @@
1
+ <% title "Tables" %>
2
+
3
+ <%= render "tables/list", :list => @tables %>
@@ -0,0 +1,2 @@
1
+ <% title "New Table" %>
2
+ <%= render 'form' %>
@@ -0,0 +1,35 @@
1
+ <% title @table.name %>
2
+
3
+ <h3>Reports</h3>
4
+ <p><%= link_to "New report from this table", new_table_report_path(@table) if permitted_to? :report, @table %></p>
5
+ <%= render "reports/list", :list => @table.reports %>
6
+
7
+ <hr/>
8
+
9
+ <h6>User: <%= "#{@table.user.email}" %></h6>
10
+ <h6>Type: <%= "#{@table.data_type}" %></h6>
11
+ <h6>Running time: <%= table_time_run(@table) %></h6>
12
+ <%= content_tag(:p, link_to("Edit", edit_table_path(@table))) if permitted_to? :edit, @table %>
13
+
14
+ <% if @test_html %>
15
+ <p><%= link_to "Hide Table Output", table_path(@table) %></p>
16
+ <%= @test_html %>
17
+ <% else %>
18
+ <p><%= link_to "See Table Output", table_path(@table, :test => true) %></p>
19
+
20
+ <% if @table.column_names and @table.column_names.size > 0 %>
21
+ <table>
22
+ <tr>
23
+ <% @table.column_names.each do |name| %>
24
+ <th><%= name %></th>
25
+ <% end %>
26
+ </tr>
27
+ </table>
28
+ <% end %>
29
+ <% end %>
30
+
31
+ <hr/>
32
+
33
+ <%= simple_format(@table.data) %>
34
+
35
+ <%= transform_display(@table) %>