vesper 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.md +20 -0
- data/Rakefile +1 -0
- data/bin/vesper +12 -0
- data/lib/vesper.rb +5 -0
- data/lib/vesper/template/.gitignore +12 -0
- data/lib/vesper/template/Gemfile +26 -0
- data/lib/vesper/template/Gemfile.lock +102 -0
- data/lib/vesper/template/README.md +0 -0
- data/lib/vesper/template/Rakefile +5 -0
- data/lib/vesper/template/app.rb +14 -0
- data/lib/vesper/template/config.ru +5 -0
- data/lib/vesper/template/config/databases.rb +15 -0
- data/lib/vesper/template/config/email.rb +15 -0
- data/lib/vesper/template/config/mime_types.rb +2 -0
- data/lib/vesper/template/config/schedule.rb +20 -0
- data/lib/vesper/template/config/sessions.rb +5 -0
- data/lib/vesper/template/config/sms.rb +15 -0
- data/lib/vesper/template/data/seeds.rb +7 -0
- data/lib/vesper/template/data/transmogrify.rb +7 -0
- data/lib/vesper/template/ext/date_time.rb +88 -0
- data/lib/vesper/template/ext/helpers.rb +43 -0
- data/lib/vesper/template/ext/log.rb +60 -0
- data/lib/vesper/template/ext/number.rb +60 -0
- data/lib/vesper/template/ext/string.rb +40 -0
- data/lib/vesper/template/lib/hello_world.rb +20 -0
- data/lib/vesper/template/log/messages.log +0 -0
- data/lib/vesper/template/public/css/design.css +17 -0
- data/lib/vesper/template/public/img/fyeah.jpg +0 -0
- data/lib/vesper/template/public/js/hide_addressbar.js +22 -0
- data/lib/vesper/template/public/robots.txt +3 -0
- data/lib/vesper/template/tasks/databases.rb +36 -0
- data/lib/vesper/template/tasks/irb.rb +8 -0
- data/lib/vesper/template/tmp/restart.txt +0 -0
- data/lib/vesper/template/vendor/bundle/.gitkeep +0 -0
- data/lib/vesper/template/views/hello_world.html +8 -0
- data/lib/vesper/template/views/layout.html +34 -0
- data/lib/vesper/version.rb +3 -0
- data/vesper.gemspec +21 -0
- metadata +85 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Vesper is still in alpha, so you'll have to build it from source.
|
2
|
+
|
3
|
+
[Download the repo](https://github.com/jarrodtaylor/vesper/downloads), uncompress and cd into your new directory.
|
4
|
+
|
5
|
+
Install the gem from souce:
|
6
|
+
|
7
|
+
sudo rake install
|
8
|
+
|
9
|
+
Create a new Vesper web app:
|
10
|
+
|
11
|
+
cd ~/Sites
|
12
|
+
vesper create MyApp && cd MyApp
|
13
|
+
|
14
|
+
Run your new web app:
|
15
|
+
|
16
|
+
rackup
|
17
|
+
|
18
|
+
[Visit your web app locally.](http://localhost:9292)
|
19
|
+
|
20
|
+
Don't forget to periodically pull updates and reinstall to get the latest version.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/vesper
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'fileutils.rb'
|
4
|
+
|
5
|
+
if ARGV[0]
|
6
|
+
case ARGV[0]
|
7
|
+
when 'create'
|
8
|
+
FileUtils.cp_r File.dirname(__FILE__) + '/../lib/vesper/template', ARGV[1] unless Dir.exists? ARGV[1]
|
9
|
+
end
|
10
|
+
else
|
11
|
+
# Message about what commands to use goes here
|
12
|
+
end
|
data/lib/vesper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# Ignore OS X's desktop service files
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
# These files are specific to each machine and should be ignored
|
5
|
+
/.bundle
|
6
|
+
|
7
|
+
# Ignore log files, except for messages
|
8
|
+
/log/*
|
9
|
+
!/log/messages.log
|
10
|
+
|
11
|
+
# Ignore development database
|
12
|
+
/data/*sqlite3
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Use RubyGems to find and download gems
|
2
|
+
source 'http://rubygems.org'
|
3
|
+
|
4
|
+
|
5
|
+
# For date and time parsing
|
6
|
+
gem 'chronic'
|
7
|
+
|
8
|
+
# For databases and model classes
|
9
|
+
gem 'data_mapper'
|
10
|
+
# gem 'dm-mysql-adapter'
|
11
|
+
gem 'dm-sqlite-adapter'
|
12
|
+
|
13
|
+
# For sending email
|
14
|
+
gem 'pony'
|
15
|
+
|
16
|
+
# For Markdown conversions
|
17
|
+
gem 'redcarpet'
|
18
|
+
|
19
|
+
# For route handling
|
20
|
+
gem 'sinatra'
|
21
|
+
|
22
|
+
# For sending text messages
|
23
|
+
gem 'twiliolib'
|
24
|
+
|
25
|
+
# For writing cron jobs in Ruby
|
26
|
+
gem 'whenever', :require => false
|
@@ -0,0 +1,102 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activesupport (3.1.3)
|
5
|
+
multi_json (~> 1.0)
|
6
|
+
addressable (2.2.6)
|
7
|
+
bcrypt-ruby (3.0.1)
|
8
|
+
builder (3.0.0)
|
9
|
+
chronic (0.6.5)
|
10
|
+
data_mapper (1.2.0)
|
11
|
+
dm-aggregates (~> 1.2.0)
|
12
|
+
dm-constraints (~> 1.2.0)
|
13
|
+
dm-core (~> 1.2.0)
|
14
|
+
dm-migrations (~> 1.2.0)
|
15
|
+
dm-serializer (~> 1.2.0)
|
16
|
+
dm-timestamps (~> 1.2.0)
|
17
|
+
dm-transactions (~> 1.2.0)
|
18
|
+
dm-types (~> 1.2.0)
|
19
|
+
dm-validations (~> 1.2.0)
|
20
|
+
data_objects (0.10.7)
|
21
|
+
addressable (~> 2.1)
|
22
|
+
dm-aggregates (1.2.0)
|
23
|
+
dm-core (~> 1.2.0)
|
24
|
+
dm-constraints (1.2.0)
|
25
|
+
dm-core (~> 1.2.0)
|
26
|
+
dm-core (1.2.0)
|
27
|
+
addressable (~> 2.2.6)
|
28
|
+
dm-do-adapter (1.2.0)
|
29
|
+
data_objects (~> 0.10.6)
|
30
|
+
dm-core (~> 1.2.0)
|
31
|
+
dm-migrations (1.2.0)
|
32
|
+
dm-core (~> 1.2.0)
|
33
|
+
dm-serializer (1.2.1)
|
34
|
+
dm-core (~> 1.2.0)
|
35
|
+
fastercsv (~> 1.5.4)
|
36
|
+
json (~> 1.6.1)
|
37
|
+
json_pure (~> 1.6.1)
|
38
|
+
multi_json (~> 1.0.3)
|
39
|
+
dm-sqlite-adapter (1.2.0)
|
40
|
+
dm-do-adapter (~> 1.2.0)
|
41
|
+
do_sqlite3 (~> 0.10.6)
|
42
|
+
dm-timestamps (1.2.0)
|
43
|
+
dm-core (~> 1.2.0)
|
44
|
+
dm-transactions (1.2.0)
|
45
|
+
dm-core (~> 1.2.0)
|
46
|
+
dm-types (1.2.1)
|
47
|
+
bcrypt-ruby (~> 3.0.0)
|
48
|
+
dm-core (~> 1.2.0)
|
49
|
+
fastercsv (~> 1.5.4)
|
50
|
+
json (~> 1.6.1)
|
51
|
+
multi_json (~> 1.0.3)
|
52
|
+
stringex (~> 1.3.0)
|
53
|
+
uuidtools (~> 2.1.2)
|
54
|
+
dm-validations (1.2.0)
|
55
|
+
dm-core (~> 1.2.0)
|
56
|
+
do_sqlite3 (0.10.7)
|
57
|
+
data_objects (= 0.10.7)
|
58
|
+
fastercsv (1.5.4)
|
59
|
+
i18n (0.6.0)
|
60
|
+
json (1.6.3)
|
61
|
+
json_pure (1.6.1)
|
62
|
+
mail (2.3.0)
|
63
|
+
i18n (>= 0.4.0)
|
64
|
+
mime-types (~> 1.16)
|
65
|
+
treetop (~> 1.4.8)
|
66
|
+
mime-types (1.17.2)
|
67
|
+
multi_json (1.0.4)
|
68
|
+
polyglot (0.3.3)
|
69
|
+
pony (1.4)
|
70
|
+
mail (> 2.0)
|
71
|
+
rack (1.3.5)
|
72
|
+
rack-protection (1.1.4)
|
73
|
+
rack
|
74
|
+
redcarpet (1.17.2)
|
75
|
+
sinatra (1.3.1)
|
76
|
+
rack (~> 1.3, >= 1.3.4)
|
77
|
+
rack-protection (~> 1.1, >= 1.1.2)
|
78
|
+
tilt (~> 1.3, >= 1.3.3)
|
79
|
+
stringex (1.3.0)
|
80
|
+
tilt (1.3.3)
|
81
|
+
treetop (1.4.10)
|
82
|
+
polyglot
|
83
|
+
polyglot (>= 0.3.1)
|
84
|
+
twiliolib (2.0.7)
|
85
|
+
builder (>= 2.1.2)
|
86
|
+
uuidtools (2.1.2)
|
87
|
+
whenever (0.7.0)
|
88
|
+
activesupport (>= 2.3.4)
|
89
|
+
chronic (~> 0.6.3)
|
90
|
+
|
91
|
+
PLATFORMS
|
92
|
+
ruby
|
93
|
+
|
94
|
+
DEPENDENCIES
|
95
|
+
chronic
|
96
|
+
data_mapper
|
97
|
+
dm-sqlite-adapter
|
98
|
+
pony
|
99
|
+
redcarpet
|
100
|
+
sinatra
|
101
|
+
twiliolib
|
102
|
+
whenever
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Use the gems in Gemfile
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.require
|
4
|
+
|
5
|
+
# Directories to load, in order
|
6
|
+
load_files = [
|
7
|
+
'config',
|
8
|
+
'ext',
|
9
|
+
'lib'
|
10
|
+
]
|
11
|
+
load_files.each {|dir| Dir["./#{dir}/**/*.rb"].each {|file| require file}}
|
12
|
+
|
13
|
+
# Tell DataMapper that all the models are ready
|
14
|
+
DataMapper.finalize
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Shows DataMapper queries alongside page requests:
|
2
|
+
# DataMapper::Logger.new $stdout, :debug
|
3
|
+
|
4
|
+
# Setup a SQLite database for development
|
5
|
+
DataMapper.setup(:default, "sqlite://#{Dir.pwd}/data/development.sqlite3")
|
6
|
+
|
7
|
+
# Optionally set up a MySQL database for production
|
8
|
+
# configure :production do
|
9
|
+
# DataMapper.setup(:default, {
|
10
|
+
# adapter: 'mysql',
|
11
|
+
# host: '',
|
12
|
+
# username: '' ,
|
13
|
+
# password: '',
|
14
|
+
# database: ''})
|
15
|
+
# end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
set :mail_server, {
|
2
|
+
address: 'smtp.gmail.com',
|
3
|
+
port: '587',
|
4
|
+
enable_starttls_auto: true,
|
5
|
+
user_name: '',
|
6
|
+
password: '',
|
7
|
+
authentication: :plain
|
8
|
+
}
|
9
|
+
|
10
|
+
# To send email via GMail:
|
11
|
+
# Pony.mail(via: :smtp, via_options: settings.mail_server,
|
12
|
+
# to: 'you@example.com',
|
13
|
+
# subject:'This is a sample email',
|
14
|
+
# body: 'Can you read me now?'
|
15
|
+
# )
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Use this file to easily define all of your cron jobs.
|
2
|
+
#
|
3
|
+
# It's helpful, but not entirely necessary to understand cron before proceeding.
|
4
|
+
# http://en.wikipedia.org/wiki/Cron
|
5
|
+
|
6
|
+
# Example:
|
7
|
+
#
|
8
|
+
# set :output, "/path/to/my/cron_log.log"
|
9
|
+
#
|
10
|
+
# every 2.hours do
|
11
|
+
# command "/usr/bin/some_great_command"
|
12
|
+
# runner "MyModel.some_method"
|
13
|
+
# rake "some:great:rake:task"
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# every 4.days do
|
17
|
+
# runner "AnotherModel.prune_old_records"
|
18
|
+
# end
|
19
|
+
|
20
|
+
# Learn more: http://github.com/javan/whenever
|
@@ -0,0 +1,15 @@
|
|
1
|
+
set :sms_server, {
|
2
|
+
account_number: '',
|
3
|
+
account_sid: '',
|
4
|
+
account_token: '',
|
5
|
+
api_version: ''
|
6
|
+
}
|
7
|
+
|
8
|
+
# To send an sms via Twilio:
|
9
|
+
# account = Twilio::RestAccount.new(settings.sms_server[:account_sid], settings.sms_server[:account_token])
|
10
|
+
# msg = {
|
11
|
+
# 'From' => settings.sms[:account_number],
|
12
|
+
# 'To' => 'xxxxxxxxxxx',
|
13
|
+
# 'Body' => 'Can you read me now?'
|
14
|
+
# }
|
15
|
+
# account.request("/#{settings.sms_server[:api_version]}/Accounts/#{settings.sms_server[:account_sid]}/SMS/Messages", 'POST', msg)
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Timepiece
|
2
|
+
|
3
|
+
# Adds the below ClassMethods module methods as class methods to the including class
|
4
|
+
def self.included base
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
# Convert date form fields into a DB compatible date
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# >> Date.from_fields 2010, 6, 26
|
14
|
+
# => 2010-06-26 12:00:00 -0400
|
15
|
+
#
|
16
|
+
# Arguments:
|
17
|
+
# year, month, day
|
18
|
+
#
|
19
|
+
def from_fields year, month, day
|
20
|
+
Chronic.parse("#{year}-#{month}-#{day}")
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
# Convert date to human readable string
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
# >> DateTime.now.display :date
|
29
|
+
# => "Friday Dec 09, 2011"
|
30
|
+
#
|
31
|
+
# Arguments:
|
32
|
+
# format (options: date, day, day_with_time, american_day)
|
33
|
+
#
|
34
|
+
def display format = :date
|
35
|
+
case format
|
36
|
+
when :date
|
37
|
+
string = "%A %b %d, %Y"
|
38
|
+
when :day
|
39
|
+
string = "%b %d, %Y"
|
40
|
+
when :day_with_time
|
41
|
+
string = "%b %d, %Y at %I:%M%P"
|
42
|
+
when :american_day
|
43
|
+
string = "%m/%d/%y"
|
44
|
+
else
|
45
|
+
string = "%A %b %d, %Y"
|
46
|
+
end
|
47
|
+
self.strftime string
|
48
|
+
end
|
49
|
+
|
50
|
+
# Convert date form fields
|
51
|
+
#
|
52
|
+
# Example:
|
53
|
+
# >> DateTime.now.to_fields
|
54
|
+
# => (Entirely to long to show)
|
55
|
+
#
|
56
|
+
# Arguments:
|
57
|
+
# field (to reference the fields by name later)
|
58
|
+
#
|
59
|
+
def to_fields field
|
60
|
+
date_field = ""
|
61
|
+
|
62
|
+
date_field << "<select name='#{field}_month' id='#{field}_month'>"
|
63
|
+
(1..12).each do |m|
|
64
|
+
date_field << "<option value='#{m}' #{'selected' if m == self.strftime('%m').to_i}>#{m}</option>"
|
65
|
+
end
|
66
|
+
date_field << "</select>"
|
67
|
+
|
68
|
+
date_field << "<select name='#{field}_day' id='#{field}_day'>"
|
69
|
+
(1..31).each do |d|
|
70
|
+
date_field << "<option value='#{d}' #{'selected' if d == self.strftime('%d').to_i}>#{d}</option>"
|
71
|
+
end
|
72
|
+
date_field << "</select>"
|
73
|
+
|
74
|
+
date_field << "<select name='#{field}_year' id='#{field}_year'>"
|
75
|
+
(2007..Chronic.parse('3 years from now').strftime('%Y').to_i).each do |y|
|
76
|
+
date_field << "<option value='#{y}' #{'selected' if y == self.strftime('%Y').to_i}>#{y}</option>"
|
77
|
+
end
|
78
|
+
date_field << "</select>"
|
79
|
+
|
80
|
+
date_field
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
# Include the above module in Date, DateTime and Time classes
|
86
|
+
Date.class_eval { include Timepiece }
|
87
|
+
DateTime.class_eval { include Timepiece }
|
88
|
+
Time.class_eval { include Timepiece }
|
@@ -0,0 +1,43 @@
|
|
1
|
+
helpers do
|
2
|
+
|
3
|
+
# Adds a class of 'active' to an element that matches the page url
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
# <a href="#" class="<%= active '/home' %>">Home</a>
|
7
|
+
#
|
8
|
+
# Arguemnts:
|
9
|
+
# path (to match against the current url)
|
10
|
+
#
|
11
|
+
def active path
|
12
|
+
'active' if request.path_info.include? "/#{path}"
|
13
|
+
end
|
14
|
+
|
15
|
+
# Displays an alert message div
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
# session[:flash] = 'Your message here.'
|
19
|
+
#
|
20
|
+
# Notes:
|
21
|
+
# Will only display on the next page load
|
22
|
+
#
|
23
|
+
def alert
|
24
|
+
unless session[:alert].nil?
|
25
|
+
msg = session[:alert]
|
26
|
+
session[:alert] = nil
|
27
|
+
"<div id='alert'>#{msg}</div>"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Hides an element
|
32
|
+
#
|
33
|
+
# Example:
|
34
|
+
# <div style="<%= hidden %>">Content to hide</div>
|
35
|
+
#
|
36
|
+
# Notes:
|
37
|
+
# Works will with if/unless (hidden unless @var.empty?)
|
38
|
+
#
|
39
|
+
def hidden
|
40
|
+
'display: none;'
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Log
|
2
|
+
|
3
|
+
# Writes a message to /log/messages.log
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
# >> Log.message 'This is a message'
|
7
|
+
#
|
8
|
+
# Arguments:
|
9
|
+
# msg
|
10
|
+
#
|
11
|
+
def self.message msg
|
12
|
+
File.open('log/messages.log', 'a+') { |f| f.write("\n#{msg}\n") }
|
13
|
+
end
|
14
|
+
|
15
|
+
# Writes errors to a log file
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
# >> Log.write_errors request.env, request
|
19
|
+
#
|
20
|
+
# Arguments:
|
21
|
+
# env (also the name of the log file, ex: development.log), request (used to parse errors)
|
22
|
+
#
|
23
|
+
def self.write_errors env, request
|
24
|
+
if env['sinatra.error']
|
25
|
+
File.open("log/#{settings.environment}.log", 'a+') do |f|
|
26
|
+
f.write("\n#{env['sinatra.error']}\n")
|
27
|
+
f.write(" #{Time.now} #{env['SERVER_PROTOCOL']} #{request.port} #{request.request_method} #{request.url}\n\n")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Writes errors and requests to a log file
|
33
|
+
#
|
34
|
+
# Example:
|
35
|
+
# >> Log.write_requests_and_errors request.env, request
|
36
|
+
#
|
37
|
+
# Arguments:
|
38
|
+
# env (also the name of the log file, ex: development.log), request (used to parse errors and requests)
|
39
|
+
#
|
40
|
+
def self.write_requests_and_errors env, request
|
41
|
+
File.open("log/#{settings.environment}.log", 'a+') do |f|
|
42
|
+
f.write("\n#{env['sinatra.error']}\n") if env['sinatra.error']
|
43
|
+
f.write(" #{Time.now} #{env['SERVER_PROTOCOL']} #{request.port} #{request.request_method} #{request.url}\n")
|
44
|
+
f.write("\n") if env['sinatra.error']
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Clears a log file
|
49
|
+
#
|
50
|
+
# Example:
|
51
|
+
# >> Log.clear 'messages'
|
52
|
+
#
|
53
|
+
# Arguments:
|
54
|
+
# file (name of log file to clear)
|
55
|
+
#
|
56
|
+
def self.clear file
|
57
|
+
File.open("log/#{file}.log", 'w+') if File::exists?("log/#{file}.log")
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Number
|
2
|
+
|
3
|
+
# Converts a number to a dollar
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
# >> 1.dollarize
|
7
|
+
# => '$1.00'
|
8
|
+
#
|
9
|
+
# Note:
|
10
|
+
# This isn't a currency conversion, it's only a string
|
11
|
+
#
|
12
|
+
def dollarize
|
13
|
+
num = self
|
14
|
+
"$%.2f" % num.to_f
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns true if a number is even
|
18
|
+
#
|
19
|
+
# Example:
|
20
|
+
# >> 2.even?
|
21
|
+
# => true
|
22
|
+
#
|
23
|
+
def even?
|
24
|
+
self%2 == 0
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns true if a number is odd
|
28
|
+
#
|
29
|
+
# Example:
|
30
|
+
# >> 2.even?
|
31
|
+
# => false
|
32
|
+
#
|
33
|
+
def odd?
|
34
|
+
self%2 != 0
|
35
|
+
end
|
36
|
+
|
37
|
+
# Truncates a number to a float
|
38
|
+
#
|
39
|
+
# Example:
|
40
|
+
# >> 1.234.truncate_to_decimal 2
|
41
|
+
# => 1.23
|
42
|
+
#
|
43
|
+
# Arguments:
|
44
|
+
# dec (number of digits after the decimal, defaults to 1)
|
45
|
+
#
|
46
|
+
# Note:
|
47
|
+
# The standard truncate methods returns an integer
|
48
|
+
#
|
49
|
+
def truncate_to_decimal dec = 1
|
50
|
+
num = self
|
51
|
+
rounded = "%.#{dec}f" % num.to_f
|
52
|
+
rounded = rounded.to_s.split('.').first if rounded.to_s.end_with?('0')
|
53
|
+
rounded.to_f
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
# Include the above module in Fixnum and Float classes
|
59
|
+
Fixnum.class_eval { include Number }
|
60
|
+
Float.class_eval { include Number }
|
@@ -0,0 +1,40 @@
|
|
1
|
+
String.class_eval do
|
2
|
+
|
3
|
+
# Coverts markdown text to html
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
# >> '# Header'.markdown
|
7
|
+
# => '<h1>Header</h1>'
|
8
|
+
#
|
9
|
+
def markdown
|
10
|
+
Redcarpet.new(self).to_html
|
11
|
+
end
|
12
|
+
|
13
|
+
# Capitalizes the first letter of each word in a string
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
# >> 'This is a title'.titleize
|
17
|
+
# => 'This Is A Title'
|
18
|
+
#
|
19
|
+
def titleize
|
20
|
+
title = ''
|
21
|
+
self.split(' ').each {|s| title << s.capitalize + ' ' }
|
22
|
+
title
|
23
|
+
end
|
24
|
+
|
25
|
+
# Truncates by word count, not letter
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
# >> 'One Two Three Four Five'.truncate 3
|
29
|
+
# => 'One Two Three...'
|
30
|
+
#
|
31
|
+
# Arguments:
|
32
|
+
# length (word count), end_string (attached to the end of a truncated string)
|
33
|
+
#
|
34
|
+
def truncate length = 100, end_string = '...'
|
35
|
+
return if self == nil
|
36
|
+
words = self.split()
|
37
|
+
words[0..(length-1)].join(' ') + (words.length > length ? end_string : '')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Sinatra route
|
2
|
+
# For more info: http://www.sinatrarb.com/
|
3
|
+
#
|
4
|
+
get '/?' do
|
5
|
+
erb :hello_world
|
6
|
+
end
|
7
|
+
|
8
|
+
# DataMapper model class
|
9
|
+
# For more info: http://datamapper.org/
|
10
|
+
#
|
11
|
+
# class User
|
12
|
+
# include DataMapper::Resource
|
13
|
+
#
|
14
|
+
# property :id, Serial
|
15
|
+
# property :deleted_at, ParanoidDateTime
|
16
|
+
# timestamps :at
|
17
|
+
#
|
18
|
+
# property :email, String
|
19
|
+
#
|
20
|
+
# end
|
File without changes
|
@@ -0,0 +1,17 @@
|
|
1
|
+
/* Import fonts from Google */
|
2
|
+
@import url(http://fonts.googleapis.com/css?family=Vollkorn:700italic,400italic,400,700);
|
3
|
+
@import url(http://fonts.googleapis.com/css?family=Cabin+Condensed:400,700);
|
4
|
+
|
5
|
+
body {
|
6
|
+
color: #333;
|
7
|
+
font-family: 'Vollkorn', serif;
|
8
|
+
font-size: 16px;
|
9
|
+
line-height: 1.5em;
|
10
|
+
padding-top: 5%;
|
11
|
+
text-align: center;
|
12
|
+
}
|
13
|
+
|
14
|
+
h1 {
|
15
|
+
color: black;
|
16
|
+
font-family: 'Cabin Condensed', sans-serif;
|
17
|
+
}
|
Binary file
|
@@ -0,0 +1,22 @@
|
|
1
|
+
// Hide the iPhone Safari address bar
|
2
|
+
// Works on load and on device rotation
|
3
|
+
// Has no effect is the content doesn't fill the height
|
4
|
+
//
|
5
|
+
// Example: <script src="/js/hide_addressbar.js"></script>
|
6
|
+
|
7
|
+
function hideAddressBar() { window.scrollTo(0, 0); }
|
8
|
+
|
9
|
+
addEventListener('load', function() { setTimeout(hideAddressBar, 0); }, false);
|
10
|
+
|
11
|
+
window.onorientationchange = function() {
|
12
|
+
switch(window.orientation) {
|
13
|
+
case 0:
|
14
|
+
case 180:
|
15
|
+
hideAddressBar();
|
16
|
+
break;
|
17
|
+
case -90:
|
18
|
+
case 90:
|
19
|
+
hideAddressBar();
|
20
|
+
break;
|
21
|
+
}
|
22
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Example:
|
2
|
+
# >> rake build
|
3
|
+
desc 'Builds the app from scratch'
|
4
|
+
task :build => ['db:setup'] do
|
5
|
+
exec 'rackup'
|
6
|
+
end
|
7
|
+
|
8
|
+
# Database specific tasks
|
9
|
+
namespace :db do
|
10
|
+
|
11
|
+
# Example:
|
12
|
+
# >> rake db:setup
|
13
|
+
desc 'Creates a new seeded database'
|
14
|
+
task :setup => ['db:migrate', 'db:seed']
|
15
|
+
|
16
|
+
# Example:
|
17
|
+
# >> rake db:upgrade
|
18
|
+
desc 'Auto upgrades the database, non-descructive'
|
19
|
+
task(:upgrade) { DataMapper.auto_upgrade }
|
20
|
+
|
21
|
+
# Example:
|
22
|
+
# >> rake db:migrate
|
23
|
+
desc 'Auto migrates the database, destructive'
|
24
|
+
task(:migrate) { DataMapper.auto_migrate! }
|
25
|
+
|
26
|
+
# Example:
|
27
|
+
# >> rake db:seed
|
28
|
+
desc 'Seeds the database'
|
29
|
+
task(:seed) { require "#{Dir.pwd}/data/seeds.rb" }
|
30
|
+
|
31
|
+
# Example
|
32
|
+
# >> rake db:transmogrify
|
33
|
+
desc 'Alters the data'
|
34
|
+
task(:transmogrify) { require "#{Dir.pwd}/data/transmogrify.rb" }
|
35
|
+
|
36
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html lang="en">
|
3
|
+
|
4
|
+
<head>
|
5
|
+
|
6
|
+
<meta charset="utf-8">
|
7
|
+
|
8
|
+
<title>Your Name Here</title>
|
9
|
+
|
10
|
+
<!-- Mobile viewport settings -->
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="/css/design.css">
|
14
|
+
|
15
|
+
<!-- Hide address bar in Safari on iPhone -->
|
16
|
+
<script src="/js/hide_addressbar.js"></script>
|
17
|
+
|
18
|
+
<!-- Use jQuery hosted by Google -->
|
19
|
+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
|
20
|
+
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
|
21
|
+
|
22
|
+
</head>
|
23
|
+
|
24
|
+
<body>
|
25
|
+
|
26
|
+
<!-- Show alert messages -->
|
27
|
+
<%= alert %>
|
28
|
+
|
29
|
+
<!-- Show content -->
|
30
|
+
<%= yield %>
|
31
|
+
|
32
|
+
</body>
|
33
|
+
|
34
|
+
</html>
|
data/vesper.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "vesper/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "vesper"
|
7
|
+
s.version = Vesper::VERSION
|
8
|
+
s.author = "Jarrod Taylor"
|
9
|
+
s.email = "jarrodtaylor@me.com"
|
10
|
+
s.homepage = "http://jarrodtaylor.github.com/vesper/"
|
11
|
+
s.summary = "A web framework with a focus on transparency."
|
12
|
+
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
|
18
|
+
# specify any dependencies here; for example:
|
19
|
+
# s.add_development_dependency "rspec"
|
20
|
+
# s.add_runtime_dependency "rest-client"
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vesper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jarrod Taylor
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-10 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email: jarrodtaylor@me.com
|
16
|
+
executables:
|
17
|
+
- vesper
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- Gemfile
|
23
|
+
- README.md
|
24
|
+
- Rakefile
|
25
|
+
- bin/vesper
|
26
|
+
- lib/vesper.rb
|
27
|
+
- lib/vesper/template/.gitignore
|
28
|
+
- lib/vesper/template/Gemfile
|
29
|
+
- lib/vesper/template/Gemfile.lock
|
30
|
+
- lib/vesper/template/README.md
|
31
|
+
- lib/vesper/template/Rakefile
|
32
|
+
- lib/vesper/template/app.rb
|
33
|
+
- lib/vesper/template/config.ru
|
34
|
+
- lib/vesper/template/config/databases.rb
|
35
|
+
- lib/vesper/template/config/email.rb
|
36
|
+
- lib/vesper/template/config/mime_types.rb
|
37
|
+
- lib/vesper/template/config/schedule.rb
|
38
|
+
- lib/vesper/template/config/sessions.rb
|
39
|
+
- lib/vesper/template/config/sms.rb
|
40
|
+
- lib/vesper/template/data/seeds.rb
|
41
|
+
- lib/vesper/template/data/transmogrify.rb
|
42
|
+
- lib/vesper/template/ext/date_time.rb
|
43
|
+
- lib/vesper/template/ext/helpers.rb
|
44
|
+
- lib/vesper/template/ext/log.rb
|
45
|
+
- lib/vesper/template/ext/number.rb
|
46
|
+
- lib/vesper/template/ext/string.rb
|
47
|
+
- lib/vesper/template/lib/hello_world.rb
|
48
|
+
- lib/vesper/template/log/messages.log
|
49
|
+
- lib/vesper/template/public/css/design.css
|
50
|
+
- lib/vesper/template/public/img/fyeah.jpg
|
51
|
+
- lib/vesper/template/public/js/hide_addressbar.js
|
52
|
+
- lib/vesper/template/public/robots.txt
|
53
|
+
- lib/vesper/template/tasks/databases.rb
|
54
|
+
- lib/vesper/template/tasks/irb.rb
|
55
|
+
- lib/vesper/template/tmp/restart.txt
|
56
|
+
- lib/vesper/template/vendor/bundle/.gitkeep
|
57
|
+
- lib/vesper/template/views/hello_world.html
|
58
|
+
- lib/vesper/template/views/layout.html
|
59
|
+
- lib/vesper/version.rb
|
60
|
+
- vesper.gemspec
|
61
|
+
homepage: http://jarrodtaylor.github.com/vesper/
|
62
|
+
licenses: []
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.8.11
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: A web framework with a focus on transparency.
|
85
|
+
test_files: []
|