Pratt 1.6.8-x86-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/.exrc +61 -0
  2. data/.gitignore +6 -0
  3. data/History.txt +6 -0
  4. data/Manifest.txt +46 -0
  5. data/Pratt.gemspec +173 -0
  6. data/Pratt.mm +1867 -0
  7. data/README.txt +67 -0
  8. data/Rakefile +96 -0
  9. data/TODO +56 -0
  10. data/VERSION +1 -0
  11. data/bin/pratt +13 -0
  12. data/config.rb +19 -0
  13. data/db/sqlite_databases_go_here +0 -0
  14. data/db/zips.csv.zip +0 -0
  15. data/lib/models.rb +8 -0
  16. data/lib/pratt.rb +308 -0
  17. data/lib/pratt/core_ext.rb +6 -0
  18. data/lib/pratt/core_ext/array.rb +20 -0
  19. data/lib/pratt/core_ext/float.rb +29 -0
  20. data/lib/pratt/core_ext/nil.rb +5 -0
  21. data/lib/pratt/core_ext/numeric.rb +9 -0
  22. data/lib/pratt/core_ext/string.rb +31 -0
  23. data/lib/pratt/core_ext/time.rb +20 -0
  24. data/lib/pratt/dialogs.rb +81 -0
  25. data/lib/pratt/formatting.rb +19 -0
  26. data/lib/pratt/project_actions.rb +25 -0
  27. data/lib/pratt/reports.rb +140 -0
  28. data/models/app.rb +39 -0
  29. data/models/customer.rb +50 -0
  30. data/models/invoice.rb +28 -0
  31. data/models/invoice_whence.rb +18 -0
  32. data/models/payment.rb +22 -0
  33. data/models/pratt.rb +15 -0
  34. data/models/project.rb +89 -0
  35. data/models/whence.rb +77 -0
  36. data/models/zip.rb +27 -0
  37. data/pratt.mm +1875 -0
  38. data/spec/app_spec.rb +48 -0
  39. data/spec/array_spec.rb +24 -0
  40. data/spec/customer_spec.rb +31 -0
  41. data/spec/fixtures/empty_graph.expectation +8 -0
  42. data/spec/fixtures/graph.expectation +13 -0
  43. data/spec/fixtures/proportions.expectation +4 -0
  44. data/spec/float_spec.rb +24 -0
  45. data/spec/formatting_spec.rb +7 -0
  46. data/spec/money_spec.rb +9 -0
  47. data/spec/nil_class_spec.rb +8 -0
  48. data/spec/numeric_spec.rb +30 -0
  49. data/spec/payment_spec.rb +19 -0
  50. data/spec/pratt_spec.rb +106 -0
  51. data/spec/project_spec.rb +182 -0
  52. data/spec/rcov.opts +0 -0
  53. data/spec/report_action_spec.rb +83 -0
  54. data/spec/report_spec.rb +205 -0
  55. data/spec/seed_data.rb +33 -0
  56. data/spec/spec.opts +1 -0
  57. data/spec/spec_helper.rb +24 -0
  58. data/spec/string_ext_spec.rb +33 -0
  59. data/spec/whence_spec.rb +54 -0
  60. data/tasks/pratt.rb +87 -0
  61. data/templates/model.eruby +12 -0
  62. data/templates/spec.eruby +8 -0
  63. data/views/current.eruby +5 -0
  64. data/views/general-invoice.eruby +538 -0
  65. data/views/graph.eruby +16 -0
  66. data/views/invoice.eruby +148 -0
  67. data/views/main.rb +90 -0
  68. data/views/pid.eruby +3 -0
  69. data/views/pop.rb +78 -0
  70. data/views/proportions.eruby +4 -0
  71. data/views/raw.eruby +11 -0
  72. metadata +275 -0
@@ -0,0 +1,67 @@
1
+ = pratt
2
+
3
+ * Pratt (url)
4
+
5
+ == DESCRIPTION:
6
+
7
+ Pratt (Pro/Re)-Active Time Tracker
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ (list of features or problems)
12
+ * Currently you'll need to manually fix the project data since I haven't
13
+ fully integrated the support for Projects to have a Customer.
14
+ * Upgrading versions looses your database. (See TODO)
15
+ * Windows doesn't work (no fork). (See TODO)
16
+
17
+
18
+ == SYNOPSIS:
19
+
20
+ * pratt (code sample of usage)
21
+
22
+ ** PRATT_ENV=production pratt -D # daemonize (or if already daemonized init the
23
+ gui)
24
+ ** pratt -h (as you'd expect lists available commands)
25
+
26
+ == REQUIREMENTS:
27
+
28
+ * pratt
29
+ debian: libtcltk-ruby tk-tile libsqlite3-dev
30
+ gems: activerecord sqlite3-ruby rspec mocha
31
+ tk: http://sourceforge.net/project/showfiles.php?group_id=11464&package_id=107795&release_id=562098
32
+
33
+ == INSTALL:
34
+
35
+ * sudo gem install
36
+
37
+ Credits
38
+
39
+ Michael Goff
40
+ Thanks for helping me with some of the workflow details
41
+ Michael and Kent Krenrich
42
+ Thanks for the UI input, suggestions, and testing.
43
+
44
+ == LICENSE:
45
+
46
+ (The MIT License)
47
+
48
+ Copyright (c) 2009 Frogstarr78 Software
49
+
50
+ Permission is hereby granted, free of charge, to any person obtaining
51
+ a copy of this software and associated documentation files (the
52
+ 'Software'), to deal in the Software without restriction, including
53
+ without limitation the rights to use, copy, modify, merge, publish,
54
+ distribute, sublicense, and/or sell copies of the Software, and to
55
+ permit persons to whom the Software is furnished to do so, subject to
56
+ the following conditions:
57
+
58
+ The above copyright notice and this permission notice shall be
59
+ included in all copies or substantial portions of the Software.
60
+
61
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
62
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
63
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
64
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
65
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
66
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
67
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,96 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'lib/pratt'
6
+ require 'tasks/pratt'
7
+
8
+ task :default => :spec
9
+
10
+ begin
11
+ require 'jeweler'
12
+ Jeweler::Tasks.new do |gem|
13
+ gem.rubyforge_project = Pratt::NAME
14
+ gem.name = Pratt::NAME
15
+ gem.summary = Pratt::SUMMARY
16
+ gem.description = Pratt::DESCRIPTION
17
+ gem.email = "frogstarr78@gmail.com"
18
+ gem.homepage = "http://github.com/frogstarr78/pratt"
19
+ gem.authors = Pratt::AUTHORS
20
+ gem.add_development_dependency 'rspec', '>=1.2.6'
21
+ gem.add_development_dependency 'mocha', '>=0.9.5'
22
+ gem.add_runtime_dependency 'activerecord', '>=2.1.1'
23
+ gem.add_runtime_dependency 'sqlite3-ruby', '=1.2.4'
24
+ gem.add_runtime_dependency 'shifty_week', '>=0.1.0'
25
+ gem.add_runtime_dependency 'erubis', '=2.6.5'
26
+ gem.add_runtime_dependency 'chronic', '=0.2.3'
27
+ gem.add_runtime_dependency 'colored', '=1.2'
28
+ gem.platform = 'current'
29
+ gem.test_files = FileList['spec/**/*.{rb,opts}', 'spec/fixtures/*.expectation']
30
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
31
+ end
32
+ Jeweler::GemcutterTasks.new
33
+ Jeweler::RubyforgeTasks.new do |rubyforge|
34
+ rubyforge.doc_task = "rdoc"
35
+ end
36
+ rescue LoadError
37
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
38
+ end
39
+
40
+ require 'spec/rake/spectask'
41
+ Spec::Rake::SpecTask.new(:spec) do |spec|
42
+ spec.libs << 'lib' << 'spec'
43
+ spec.spec_files = FileList['spec/**/*_spec.rb']
44
+ end
45
+
46
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
47
+ spec.libs << 'lib' << 'spec'
48
+ spec.pattern = 'spec/**/*_spec.rb'
49
+ spec.rcov = true
50
+ spec.rcov_opts = %w(--text-report --exclude=activerecord,ruby-debug,shifty_week,sqlite3-ruby,rspec,mocha,erubis,chronic,colored,columnize,builder,activesupport,i18n,linecache,json_pure,rcov,abstract,spec_helper.rb,config.rb,spec)
51
+ end
52
+
53
+ task :spec => :check_dependencies
54
+
55
+ begin
56
+ require 'reek/adapters/rake_task'
57
+ Reek::RakeTask.new do |t|
58
+ t.fail_on_error = true
59
+ t.verbose = false
60
+ t.source_files = 'lib/**/*.rb'
61
+ end
62
+ rescue LoadError
63
+ task :reek do
64
+ abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
65
+ end
66
+ end
67
+
68
+ begin
69
+ require 'roodi'
70
+ require 'roodi_task'
71
+ RoodiTask.new do |t|
72
+ t.verbose = false
73
+ end
74
+ rescue LoadError
75
+ task :roodi do
76
+ abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
77
+ end
78
+ end
79
+
80
+ task :default => :spec
81
+
82
+ require 'rake/rdoctask'
83
+ Rake::RDocTask.new do |rdoc|
84
+ if File.exist?('VERSION')
85
+ version = File.read('VERSION')
86
+ else
87
+ version = ""
88
+ end
89
+
90
+ rdoc.rdoc_dir = 'rdoc'
91
+ rdoc.title = "pratt #{version}"
92
+ rdoc.rdoc_files.include('README*')
93
+ rdoc.rdoc_files.include('lib/**/*.rb')
94
+ end
95
+
96
+ # vim: syntax=ruby
data/TODO ADDED
@@ -0,0 +1,56 @@
1
+ General:
2
+ [ ] Remove environment ability
3
+ [ ] Change to use raw command line arguments / Remove optparse lib
4
+ [ ] Update general package setup (It's messy)
5
+ [?] Add file watching like merb
6
+ [?] Move to Observer Pattern for reporting functionality
7
+
8
+ Invoicing:
9
+ [x] Add shifty week plugin
10
+ [ ] Add support for variable rates.
11
+
12
+ Templating:
13
+ [ ] Invoices
14
+ [x] Move other output to template based
15
+
16
+ Data:
17
+ [?] Change to Use DataMapper
18
+ [?] Put everything in the db? (logs, app locks, etc)
19
+ [ ] Move database location to central location that doesn't dissappear when upgrading the app.
20
+
21
+ GUI:
22
+ [ ] Add TrayIcon.
23
+ [ ] Customer CRUD
24
+ [ ] Payment CRUD
25
+ [ ] Re-design prompts
26
+ [ ] Remove fork in favor of ( eval OR (!?!) GUI classes )
27
+ [ ] Don't assume gui.
28
+
29
+ Test:
30
+ [ ] Add more I'm not testing everything
31
+ [ ] Flog
32
+ [ ] Flay
33
+
34
+
35
+
36
+ Done:
37
+ [x] Whence.last should be last unended.
38
+ [x] Add date range argument to timed report.
39
+ [x] Add validation for start/end at.
40
+ [x] Manual data manipulation date/time.
41
+ [x] Change pop prompt to show helpful time.
42
+ [x] Change Start/Continue interface.
43
+ [x] Add directoryless agnostic runner.
44
+ [x] Log output.
45
+ [x] Add Quiet option??
46
+ [x] Allow only one prompt at a time.
47
+ [x] Handle stop when there isn't a running project w/out errors
48
+ [x] fix gui so if last_unended is detected app knows which gui to display
49
+ [x] Intelligently detect correctly running stored pid.
50
+ [x] Fix pid directory access.
51
+
52
+ [x] Add support for Customer's model
53
+ [x] Add Template command
54
+ [x] Add Invoice command
55
+ [x] Fix colorability
56
+ [x] Add console command
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.6.8
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fileutils'
4
+ bin_file = __FILE__
5
+ bin_file = File.symlink?(bin_file) ? File.readlink(bin_file) : bin_file
6
+
7
+ bin_path = File.expand_path( '..', bin_file )
8
+ pratt_dir = File.dirname( bin_path )
9
+ FileUtils.chdir pratt_dir
10
+
11
+ require "lib/pratt"
12
+
13
+ Pratt.parse(ARGV)
@@ -0,0 +1,19 @@
1
+ PRATT_ENV = ENV["PRATT_ENV"] || 'development' unless Object.const_defined? :PRATT_ENV
2
+
3
+ class Pratt
4
+ include FileUtils
5
+
6
+ class << self
7
+ def connect! to_env = :development
8
+ connect_to = "db/#{to_env}.sqlite3"
9
+ ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => connect_to )
10
+ unless File.exists? connect_to
11
+ Pratt.migrate
12
+ end
13
+ end
14
+
15
+ def connected?
16
+ ActiveRecord::Base.connected?
17
+ end
18
+ end
19
+ end
File without changes
Binary file
@@ -0,0 +1,8 @@
1
+ require 'models/app'
2
+ require 'models/customer'
3
+ require 'models/whence'
4
+ require 'models/project'
5
+ require 'models/payment'
6
+ require 'models/invoice'
7
+ require 'models/invoice_whence'
8
+ require 'models/zip'
@@ -0,0 +1,308 @@
1
+ # coding: utf-8
2
+ require 'fileutils'
3
+ require 'optparse'
4
+ require 'pathname'
5
+
6
+ require 'rubygems'
7
+ require 'colored'
8
+ require 'chronic'
9
+ require 'active_record'
10
+ require 'erubis'
11
+ require 'config'
12
+ require 'shifty_week'
13
+ require 'shifty_week/time'
14
+ require 'shifty_week/date'
15
+
16
+ require 'lib/pratt/formatting'
17
+ require 'lib/pratt/core_ext'
18
+ require 'lib/pratt/dialogs'
19
+ require 'lib/pratt/project_actions'
20
+ require 'lib/pratt/reports'
21
+ require 'lib/models'
22
+
23
+
24
+ class Pratt
25
+
26
+ NAME = 'Pratt'
27
+ URL = 'http://www.frogstarr78.com/projects/pratt'
28
+ AUTHORS = ['Scott Noel-Hemming']
29
+ SUMMARY = "Pro/Re-Active Time Tracker. Track time based on what you expect to be working on, with frequent prompts to ensure accuracy."
30
+ DESCRIPTION = %q|
31
+ Need a way to keep track of your time, but get caught up in work? Or constant interruptions?
32
+ Yeah you know who I'm talking about. Those people from the [abc] department always "NEEDING xyz FEATURE NOW!!!".
33
+ Seriously though. I'm usually just loose track of time. I wanted an app that I could start with a task I think
34
+ I'll be working on, but that get's in my face constantly to ensure I'm still working on it. And if I'm not any longer,
35
+ provides an easy way of changing to another task, or if I have changed tasks and not already updated the app, would
36
+ provide an easy way of changing the task of the previously recorded interval. That's what this is intended to do.
37
+
38
+ Time Tracking.
39
+ Proactively set what you expect to work on.
40
+ Reactively modify what you are no longer working on.
41
+ |
42
+ DEPENDENCIES = ["activerecord >=2.1.1", "sqlite3-ruby >=1.2.4", "rspec >=1.2.6", "mocha >=0.9.5"]
43
+ VERSION = File.open( File.join(Dir.pwd, 'VERSION') ).read.strip
44
+
45
+ PID_FILE='pratt.pid'
46
+ FMT = "%a %X %b %d %Y"
47
+ INVOICE_FMT = "%x"
48
+
49
+ attr_accessor :when_to, :scale, :color, :show_all, :raw_conditions, :template, :week_day_start
50
+ attr_reader :project, :todo
51
+ def initialize proj = nil
52
+ @when_to = DateTime.now
53
+ @week = false
54
+ @day = false
55
+ @todo = []
56
+ @scale = nil
57
+ @show_all = false
58
+ @template = nil
59
+ @raw_conditions = ''
60
+ self.project = proj unless proj.nil?
61
+ end
62
+
63
+ # Set the project to something (Project/String)
64
+ # Conditionally creating a new project if the project
65
+ # named by the parameter isn't found
66
+ def project= proj
67
+ if proj.is_a?(Project)
68
+ @project = proj
69
+ else
70
+ @project = Project.find_or_create_by_name( { :name => proj } )
71
+ end
72
+ end
73
+
74
+ # We should act like an array
75
+ def << what
76
+ @todo << what
77
+ end
78
+
79
+ # Connect to the database in irb for manual commands/investigation
80
+ def console
81
+ require 'irb'
82
+ require 'irb/completion'
83
+ ARGV.clear
84
+ IRB.start
85
+ end
86
+
87
+ # Stop everything and kill daemonized processes.
88
+ def quit
89
+ project.stop! if project? and project.whences.last_unended
90
+ Whence.last_unended.stop! if Whence.last_unended
91
+ begin
92
+ Process.kill("KILL", app.pid.to_i)
93
+ rescue Errno::ESRCH
94
+ puts "Unable to kill Pratt@pid(#{app.pid})."
95
+ end
96
+ app.pid = ''
97
+ app.gui = ''
98
+ app.save!
99
+ end
100
+
101
+ # Singleton Accessor for @app
102
+ def app
103
+ @app ||= App.last
104
+ @app
105
+ end
106
+
107
+ # "Unlock" the gui.
108
+ def unlock
109
+ self.app.unlock
110
+ end
111
+
112
+ def run
113
+ # ensure we've shifted the when_to value to the
114
+ # current start of week
115
+ self.when_to.week_day_start = self.week_day_start
116
+
117
+ # << order is semi important
118
+ self.end if i_should? :end
119
+ self.begin if i_should? :begin
120
+ self.change if i_should? :change
121
+ self.restart if i_should? :restart
122
+
123
+ self.destroy if i_should? :destroy
124
+ # end order is semi important
125
+
126
+ # << order doesn't matter within this set
127
+ self.pid if i_should? :pid
128
+ self.raw if i_should? :raw
129
+ self.current if i_should? :current
130
+ self.graph if i_should? :graph
131
+ self.proportions if i_should? :proportions
132
+ self.invoice if i_should? :invoice
133
+ self.console if i_should? :console
134
+ self.gui if i_should? :gui
135
+ self.detect if i_should? :detect
136
+ self.unlock if i_should? :unlock
137
+ # end order doesn't matter within this set
138
+
139
+ # << these should happen last
140
+ self.quit if i_should? :quit
141
+ self.daemonize! if i_should? :daemonize and not self.daemonized?
142
+ # end these should happen last
143
+ end
144
+
145
+ private
146
+ def i_should? what
147
+ @todo.include?(what)
148
+ end
149
+
150
+ # Is there a project that can be operated on?
151
+ def project?
152
+ !@project.nil? and @project.name?
153
+ end
154
+
155
+ class << self
156
+
157
+ # Parse cli arguments and init Pratt
158
+ def parse args
159
+ me = Pratt.new
160
+
161
+ # There are aa few things we're parsing here
162
+ # Pratt config arguments (Ideally that should be all we do)
163
+ # Pratt actions. These may require ordering or not. They also may require an argument value.
164
+ #
165
+ # TODO: Redo the cli parsing...
166
+ # In some cases we require arguments to be run in a certain order, but we don't want some to be run concurrently w/ others.
167
+ # Sometimes it may be unexpected but helpful to allow that behavior.
168
+ opt = OptionParser.new do |opt|
169
+ Pratt.connect! ENV['PRATT_ENV'] || 'development' unless Pratt.connected?
170
+
171
+ # Actionable options
172
+ opt.on('-b', "--begin", String, "Begin project tracking.") do
173
+ me << :begin
174
+ end
175
+ opt.on('-r', "--restart", String, "Restart project log (stop last log and start a new one).
176
+ Applies to last un-ended project, unless a specific project is provided.") do
177
+ me << :restart
178
+ end
179
+ opt.on('-e', "--end", String, "Stop tracking interval for last project or supplied project if provided.") do
180
+ me << :end
181
+ end
182
+ opt.on('-c', "--change", String, "Change last time interval to this project.") do
183
+ me << :change
184
+ end
185
+ opt.on('-g', "--graph", String, "Display time spent on supplied project or all projects without argument value.") do
186
+ me << :graph
187
+ end
188
+ opt.on('-I', "--invoice", "Create an invoice.") do
189
+ me << :invoice
190
+ end
191
+ opt.on('-r', '--proportions', "") do
192
+ me << :proportions
193
+ end
194
+ opt.on('-p', '--pid', "Process id display. (Is it still running)") do
195
+ me << :pid
196
+ end
197
+ opt.on('-R', '--raw [CONDITIONS]', "Dump logs (semi-)raw") do |conditions|
198
+ me << :raw
199
+ me.raw_conditions = conditions
200
+ end
201
+ opt.on('-C', "--current", "Show available projects and current project (if there is one)") do
202
+ me << :current
203
+ end
204
+ opt.on("-d", "--daemonize", "Start daemon.") do
205
+ me << :daemonize
206
+ end
207
+ opt.on('-D', '--detect', 'Detect appropriate behavior. (Daemonize or Graphical).') do
208
+ me << :detect
209
+ end
210
+ opt.on('-G', '--gui', 'Show "smart" gui.') do
211
+ me << :gui
212
+ end
213
+ opt.on('-q', "--quit", "Stop daemon.") do
214
+ me << :quit
215
+ end
216
+ opt.on('-U', '--unlock', "Manually unlock a gui that has died but left it's lock around.") do
217
+ me << :unlock
218
+ end
219
+ opt.on '-V', '--version' do
220
+ puts "Pro-Reactive Time Tracker [Pratt] (#{VERSION})"
221
+ end
222
+ opt.on('--destroy', String, "Remove a project.") do
223
+ me << :destroy
224
+ end
225
+
226
+ # Strictly configuration options
227
+ project_names = Project.all.collect(&:name)
228
+ colored_project_names = project_names.collect{|name|
229
+ " #{name.cyan}"}
230
+ opt.on('-P', "--project PROJECT_NAME", project_names, "Set project.
231
+ Available projects are:\n#{colored_project_names*"\n"}") do |proj|
232
+ me.project = proj
233
+ end
234
+
235
+ templates = []
236
+ Pratt.root("views", "*.eruby") {|view| templates << File.basename(view, '.eruby') }
237
+ opt.on('-t', "--template TEMPLATE", templates, "Template to use for displaying work done.
238
+ Available templates are #{templates.to_sentence('or')}.") do |template|
239
+ me.template = template
240
+ end
241
+ opt.on '-w', '--when_to TIME', String, 'When to do something.
242
+ (e.g. log time start|stop, or what time interval to graph)
243
+ If graphing, silently ignored w/out scale argument.' do |when_to|
244
+ me.when_to = Chronic.parse(when_to).to_datetime
245
+ end
246
+ scales = %w(day week month quarter year)
247
+ opt.on('-l', '--scale SCALE', scales, "Granularity of time argument
248
+ Available scales are #{scales.to_sentence('or')}.
249
+ Only applies to graphing.") do |scale|
250
+ me.scale = scale
251
+ end
252
+ opt.on('-L', '--log', "Redirect errors") do
253
+ FileUtils.mkdir 'log' unless File.exists? 'log'
254
+ $stderr.reopen('log/pratt.log', 'a')
255
+ $stderr.sync = true
256
+ end
257
+ opt.on('-N', '--no-color', "Display output without color or special characters.") do
258
+ Pratt.color = false
259
+ end
260
+ opt.on('-A', '--show-all', "Display all project regardless of other options.") do
261
+ me.show_all = true
262
+ end
263
+ opt.on '-s', '--start-day WEEK_DAY_START', String, "" do |wday_start|
264
+ me.week_day_start = wday_start
265
+ end
266
+ opt.on('-i', "--interval INTERVAL", Float, "Set the remind interval/min (Only applies to daemonized process).") do |interval|
267
+ me.app.interval = interval
268
+ me.app.save
269
+ end
270
+
271
+ opt.parse!
272
+ end
273
+
274
+ me << :console if args.include? 'console'
275
+
276
+ me.run
277
+ end
278
+
279
+ # Where is Pratt installed.
280
+ # We've already chdir'd to it's base dir in the bin file
281
+ def root *globs, &block
282
+ root = Dir.pwd
283
+ if globs.empty?
284
+ subdir = root
285
+ else
286
+ subdir = File.join(root, *globs)
287
+ end
288
+
289
+ if block_given?
290
+ Pathname.glob(subdir) {|dir_files| yield dir_files }
291
+ else
292
+ Pathname.glob(subdir)
293
+ end
294
+ end
295
+
296
+ # Migrate schema.
297
+ def migrate
298
+ Pratt.root( 'models', '*.rb' ) do |model_file|
299
+ klass = File.basename( model_file, '.rb' ).classify.constantize
300
+ begin
301
+ ActiveRecord::Base.connection.table_structure(model_file)
302
+ rescue ActiveRecord::StatementInvalid
303
+ klass.migrate :up if klass.superclass == ActiveRecord::Base
304
+ end
305
+ end
306
+ end
307
+ end
308
+ end