sinatra-chassis 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE +7 -0
  4. data/README.md +19 -0
  5. data/Rakefile +1 -0
  6. data/bin/chassis +73 -0
  7. data/lib/sinatra/chassis.rb +213 -0
  8. data/lib/sinatra/chassis/file_manager.rb +151 -0
  9. data/lib/sinatra/chassis/helpers.rb +237 -0
  10. data/lib/sinatra/chassis/tasks.rb +7 -0
  11. data/lib/sinatra/tasks/assets.rake +40 -0
  12. data/lib/sinatra/tasks/chassis.rake +23 -0
  13. data/lib/sinatra/tasks/datamapper.rake +117 -0
  14. data/lib/sinatra/tasks/pony.rake +11 -0
  15. data/lib/sinatra/tasks/sinatra.rake +23 -0
  16. data/lib/sinatra/templates/chassis/.gitignore +6 -0
  17. data/lib/sinatra/templates/chassis/Gemfile +8 -0
  18. data/lib/sinatra/templates/chassis/README.md +4 -0
  19. data/lib/sinatra/templates/chassis/Rakefile +2 -0
  20. data/lib/sinatra/templates/chassis/app.rb +20 -0
  21. data/lib/sinatra/templates/chassis/config.ru +2 -0
  22. data/lib/sinatra/templates/chassis/public/favicon.ico +0 -0
  23. data/lib/sinatra/templates/chassis/public/robots.txt +3 -0
  24. data/lib/sinatra/templates/chassis/tmp/restart.txt +0 -0
  25. data/lib/sinatra/templates/chassis/views/layout.erb +18 -0
  26. data/lib/sinatra/templates/chassis/views/readme.erb +23 -0
  27. data/lib/sinatra/templates/datamapper/data/migrations/datamapper_migration.rb +13 -0
  28. data/lib/sinatra/templates/datamapper/data/seeds/seed.rb +1 -0
  29. data/lib/sinatra/templates/datamapper/models/datamapper.rb +8 -0
  30. data/lib/sinatra/templates/datamapper/settings/datamapper.rb +16 -0
  31. data/lib/sinatra/templates/datamapper/tests/models/datamapper_tests.rb +16 -0
  32. data/lib/sinatra/templates/pony/settings/pony.rb +27 -0
  33. data/lib/sinatra/templates/sinatra/routes/routes.rb +7 -0
  34. data/lib/sinatra/templates/sinatra/tests/routes/routes_tests.rb +17 -0
  35. data/lib/sinatra/views/error.erb +36 -0
  36. data/sinatra-chassis.gemspec +28 -0
  37. metadata +149 -0
@@ -0,0 +1,237 @@
1
+ require 'sinatra/base'
2
+ require 'rack-flash'
3
+
4
+ # Public: Adds helpers
5
+ module Sinatra
6
+
7
+ module ChassisExtraHelpers
8
+ # Public: Checks if the argument can be evaluated numerically.
9
+ #
10
+ # Example
11
+ #
12
+ # is_numeric?('1')
13
+ # # => true
14
+ #
15
+ # is_numeric?('hello')
16
+ # # => false
17
+ #
18
+ # Returns true/false.
19
+ def numeric? x
20
+ true if Float(x) rescue false
21
+ end
22
+
23
+ # Public: Truncates a String or Number.
24
+ #
25
+ # x - String or Number to truncate
26
+ # word_count - Integer number of words to return if x is a String (default: 100)
27
+ # end_string - String appended to the end of the returned String if
28
+ # the original x String is longer than word_count (default: '...')
29
+ # decimal - Integer number of maximum places after decimal if x is a Number (default: 1)
30
+ # trailing_zeros - Boolean to decide if a returned Number should keep the
31
+ # trailing 0's as a String (default: false)
32
+ #
33
+ # Examples
34
+ #
35
+ # truncate('Lorem ipsum dolor sit amet.', word_count: 3, end_string: '...')
36
+ # # => 'Lorem ipsum dolor...'
37
+ #
38
+ # truncate(1.234000, decimal: 1)
39
+ # # => 1.2
40
+ # truncate(1.234000, decimal: 5)
41
+ # # => 1.234
42
+ # truncate(1.234000, decimal: 5, trailing_zeros: true)
43
+ # # => '1.23400'
44
+ #
45
+ # Returns a String or Float.
46
+ def truncate x, options = {}
47
+ options[:word_count] ||= 100
48
+ options[:end_string] ||= '...'
49
+ options[:decimal] ||= 2
50
+ options[:trailing_zeros] ||= false
51
+
52
+ if x.kind_of? String
53
+ return if x == nil
54
+ words = x.split()
55
+ return words[0..(options[:word_count]-1)].join(' ') + (words.length > options[:word_count] ? options[:end_string] : '')
56
+ elsif is_numeric? x
57
+ number = "%.#{options[:decimal]}f" % x.to_f
58
+ number = number.to_f unless options[:trailing_zeros]
59
+ return number
60
+ end
61
+ end
62
+
63
+ # Public: Uppercases the first letter of each word.
64
+ #
65
+ # Example
66
+ #
67
+ # titleize('hello world')
68
+ # # => 'Hello World'
69
+ #
70
+ # Returns a String.
71
+ def titleize x
72
+ title = ''
73
+ x.to_s.split(' ').each { |s| title << s.capitalize + ' ' }
74
+ title
75
+ end
76
+
77
+ # Public: Compares a string to the request path.
78
+ #
79
+ # path - String to compare against the request path
80
+ #
81
+ # Exmaple
82
+ #
83
+ # Requested URL: http://localhost:4567/hello/world
84
+ # active('hello')
85
+ # # => 'active'
86
+ # active('goodbye')
87
+ # # => ''
88
+ #
89
+ # Returns a Sting: 'active' if there's a match, '' if not.
90
+ def active path
91
+ path = Array[path] unless path.kind_of? Array
92
+ match = false
93
+ path.each { |p| match = true if request.path_info.include?(p) }
94
+ 'active' if match
95
+ end
96
+
97
+ # Public: Displays an alert unless flash[:alert] if nil.
98
+ # flash[:alert] empties itself after the first request after it's set.
99
+ # To use, set flash[:alert] to a String.
100
+ #
101
+ # Example
102
+ # <%= alert %>
103
+ #
104
+ # Returns a div with an id of 'alert' and containing the contents
105
+ # of flash[:alert], or if flash[:alert] if nil, returns nothing.
106
+ def alert
107
+ "<div id='alert'>#{flash[:alert]}</div>" if flash[:alert]
108
+ end
109
+
110
+ # Public: Hides an HTML element.
111
+ # Useful in combination with inline true/false comparators.
112
+ #
113
+ # Example
114
+ #
115
+ # <div style="<%= hidden unless session[:user] %>">Hello, world!</div>
116
+ #
117
+ # Returns a String of CSS.
118
+ def hidden
119
+ 'display: none;'
120
+ end
121
+
122
+ # Public: Converts a Date to select form fields.
123
+ # All generated fields have classes of month_select, day_select, or year_select.
124
+ # None of the options are required, but they are all recommended.
125
+ #
126
+ # select_name - name attr for fields, appended with '_day', '_month', or '_year'
127
+ # select_id - id attr for fields, appended with '_day', '_month', or '_year'
128
+ # select_class - class attr for fields, appended with '_day', '_month', or '_year'
129
+ # start_year - first year to use in year select (default: 3 years ago)
130
+ # end_year - last year to use in year select (default: 3 years from now)
131
+ # day_first - Boolean to show the day before the month (default: false)
132
+ # month_name - Boolean to display month names (default: false)
133
+ #
134
+ # Example
135
+ #
136
+ # date_select(
137
+ # DateTime.now
138
+ # select_class: 'your_class',
139
+ # select_id: 'your_id',
140
+ # select_name: 'your_name',
141
+ # start_year: 1999,
142
+ # end_year: 2021,
143
+ # day_first: true,
144
+ # month_name: false
145
+ # )
146
+ #
147
+ # Returns select fields as a String.
148
+ def date_select date, options = {}
149
+ options[:select_name] ||= ''
150
+ options[:select_id] ||= ''
151
+ options[:select_class] ||= ''
152
+
153
+ unless options[:select_id] == ''
154
+ day_id = " id='#{options[:select_id]}_day'"
155
+ month_id = " id='#{options[:select_id]}_month'"
156
+ year_id = " id='#{options[:select_id]}_year'"
157
+ else
158
+ day_id = ''
159
+ month_id = ''
160
+ year_id = ''
161
+ end
162
+
163
+ unless options[:select_name] == ''
164
+ day_name = " name='#{options[:select_name]}_day'"
165
+ month_name = " name='#{options[:select_name]}_month'"
166
+ year_name = " name='#{options[:select_name]}_year'"
167
+ else
168
+ day_name = ''
169
+ month_name = ''
170
+ year_name = ''
171
+ end
172
+
173
+ options[:day_first] ||= false
174
+ options[:start_year] ||= Time.now.strftime('%Y').to_i - 3
175
+ options[:end_year] ||= Time.now.strftime('%Y').to_i + 3
176
+ options[:month_name] ||= false
177
+
178
+ options[:start_year] = date.strftime('%Y').to_i if date.strftime('%Y').to_i < options[:start_year]
179
+ options[:end_year] = date.strftime('%Y').to_i if date.strftime('%Y').to_i > options[:end_year]
180
+
181
+ months = [
182
+ { num: '01', name: 'January' },
183
+ { num: '02', name: 'February' },
184
+ { num: '03', name: 'March' },
185
+ { num: '04', name: 'April' },
186
+ { num: '05', name: 'May' },
187
+ { num: '06', name: 'June' },
188
+ { num: '07', name: 'July' },
189
+ { num: '08', name: 'August' },
190
+ { num: '09', name: 'September' },
191
+ { num: '10', name: 'October' },
192
+ { num: '11', name: 'November' },
193
+ { num: '12', name: 'December' }
194
+ ]
195
+
196
+ day = "<select class='day_select #{options[:select_class]}'#{day_id}#{day_name}'>"
197
+ (1..31).each do |d|
198
+ day << "<option value='#{d}' #{'selected' if d == date.strftime('%d').to_i}>#{d}</option>"
199
+ end
200
+ day << "</select>"
201
+
202
+ month = "<select class='month_select #{options[:select_class]}'#{month_id}#{month_name}>"
203
+ months.each do |m|
204
+ options[:month_name] ? d = m[:name] : d = m[:num]
205
+ month << "<option value='#{m[:num]}' #{'selected' if m[:num] == date.strftime('%m').to_i}>#{d}</option>"
206
+ end
207
+ month << "</select>"
208
+
209
+ year = "<select class='year_select #{options[:select_class]}'#{year_id}#{year_name}>"
210
+ (options[:start_year]..options[:end_year]).each do |y|
211
+ year << "<option value='#{y}' #{'selected' if y == date.strftime('%Y').to_i}>#{y}</option>"
212
+ end
213
+ year << "</select>"
214
+
215
+ if options[:day_first]
216
+ return "#{day} #{month} #{year}"
217
+ else
218
+ return "#{month} #{day} #{year}"
219
+ end
220
+ end
221
+
222
+ end
223
+
224
+ module ChassisExtras
225
+
226
+ # Adds Rack::Flash to the app (requires sessions)
227
+ def self.registered(app)
228
+ app.enable :sessions
229
+ app.set :session_secret, [*('A'..'Z')].sample(40).join if app.session_secret.nil?
230
+ use Rack::Flash
231
+ end
232
+
233
+ end
234
+
235
+ helpers ChassisExtraHelpers
236
+ register ChassisExtras
237
+ end
@@ -0,0 +1,7 @@
1
+ # Require this script in app Rakefiles to import the Chassis file_manager,
2
+ # the Chassis app rake tasks, and the tasks in the app /tasks directory.
3
+
4
+ require "#{File.dirname(__FILE__)}/file_manager"
5
+
6
+ Dir[File.join(File.dirname(__FILE__) + "/../tasks/**/*.rake")].each { |file| import file }
7
+ Dir["./tasks/**/*.rake"].each { |file| import file }
@@ -0,0 +1,40 @@
1
+ namespace :assets do
2
+
3
+ desc 'Compile .coffee and .sass files in /public'
4
+ task :precompile do
5
+ settings.assets_path.each do |path|
6
+ copy_directory("./#{path}", "./public/#{path}") unless path == 'public'
7
+ end
8
+ Dir.glob("./public/**/*.coffee").each do |asset|
9
+ File.open(asset.gsub('.coffee', '.js'), 'w') do |f|
10
+ f.write(CoffeeScript.compile(File.read(asset)))
11
+ end
12
+ end
13
+ Dir.glob("./public/**/*.scss").each do |asset|
14
+ File.open(asset.gsub('.scss', '.css'), 'w') do |f|
15
+ f.write(Sass::Engine.for_file(asset, {}).render)
16
+ end
17
+ end
18
+ settings.assets_path.each do |path|
19
+ unless path == 'public'
20
+ Dir.glob("./public/#{path}/**/*.{coffee,scss}").each do |asset|
21
+ File.delete(asset)
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ desc 'Remove compiled assets'
28
+ task :decompile do
29
+ settings.assets_path.each do |path|
30
+ FileUtils.rm_rf("./public/#{path}") unless path == 'public'
31
+ end
32
+ Dir.glob("./public/**/*.coffee").each do |asset|
33
+ File.delete(asset.gsub('.coffee', '.js')) if File.exists?(asset.gsub('.coffee', '.js'))
34
+ end
35
+ Dir.glob("./public/**/*.scss").each do |asset|
36
+ File.delete(asset.gsub('.scss', '.css')) if File.exists?(asset.gsub('.scss', '.css'))
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,23 @@
1
+ namespace :chassis do
2
+
3
+ desc 'Run app in an IRB session'
4
+ task :irb do
5
+ require 'irb'
6
+ ARGV.clear
7
+ IRB.start
8
+ end
9
+
10
+ namespace :run do
11
+
12
+ desc 'Run one or all /tests scripts'
13
+ task :test, :file do |t, args|
14
+ if args.file == nil
15
+ Dir["./tests/**/*.rb"].each { |file| require file }
16
+ else
17
+ require "./tests/#{args.file}"
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,117 @@
1
+ namespace :setup do
2
+
3
+ desc 'Set up DataMapper'
4
+ task :datamapper do
5
+ create_directory './settings'
6
+ append_to_file './Gemfile', "\ngem 'data_mapper', '~> 1.2.0'"
7
+ append_to_file './Gemfile', "\ngem 'dm-sqlite-adapter', '~> 1.2.0'"
8
+ append_to_file './Gemfile', "\n# gem 'dm-mysql-adapter', '~> 1.2.0'"
9
+ append_to_file './Gemfile', "\n# gem 'dm-postgres-adapter', '~> 1.2.0'\n"
10
+ append_to_file './app.rb', "\nDataMapper.finalize\n"
11
+ copy_file "#{TEMPLATES}/datamapper/settings/datamapper.rb",
12
+ "./settings/datamapper.rb"
13
+ end
14
+
15
+ end
16
+
17
+ namespace :dm do
18
+
19
+ def create_dm_path
20
+ if DataMapper.repository.adapter.options[:path].include? 'sqlite'
21
+ db = DataMapper.repository.adapter.options[:path].split('/').last
22
+ create_directory DataMapper.repository.adapter.options[:path].gsub(db, '')
23
+ end
24
+ end
25
+
26
+ namespace :add do
27
+
28
+ desc 'Add a data migration' if defined? DataMapper
29
+ task :migration, :name do |t, args|
30
+ if args.name == nil
31
+ puts 'You must define a migration name.'
32
+ puts 'Example: rake add:migration[my_migration]'
33
+ exit
34
+ end
35
+ create_directory './data', './data/migrations'
36
+ t = Time.now.strftime("%Y%m%d%H%M%S")
37
+ copy_template "#{TEMPLATES}/datamapper/data/migrations/datamapper_migration.rb",
38
+ "./data/migrations/#{t}_#{args.name}.rb",
39
+ { t: t, migration: args.name }
40
+ end
41
+
42
+ desc 'Add a model' if defined? DataMapper
43
+ task :model, :name do |t, args|
44
+ if args.name == nil
45
+ puts 'You must define a model name.'
46
+ puts 'Example: rake add:model[my_model]'
47
+ exit
48
+ end
49
+ create_directory './models', './tests', './tests/models'
50
+ copy_template "#{TEMPLATES}/datamapper/models/datamapper.rb",
51
+ "./models/#{args.name}.rb",
52
+ { model: args.name }
53
+ copy_template "#{TEMPLATES}/datamapper/tests/models/datamapper_tests.rb",
54
+ "./tests/models/#{args.name}_tests.rb",
55
+ { model: args.name }
56
+ end
57
+
58
+ desc 'Add a seed data script' if defined? DataMapper
59
+ task :seed, :name do |t, args|
60
+ if args.name == nil
61
+ puts 'You must define a seed file name.'
62
+ puts 'Example: rake add:seed[my_seed_script]'
63
+ exit
64
+ end
65
+ create_directory './data', './data/seeds'
66
+ copy_template "#{TEMPLATES}/datamapper/data/seeds/seed.rb",
67
+ "./data/seeds/#{args.name}.rb"
68
+ end
69
+
70
+ end
71
+
72
+ desc 'Auto upgrade one or all models' if defined? DataMapper
73
+ task :upgrade, :model do |t, args|
74
+ create_dm_path
75
+ args.model == nil ? DataMapper.auto_upgrade! : args.model.constantize.auto_upgrade!
76
+ end
77
+
78
+ desc 'Auto migrate one or all models' if defined? DataMapper
79
+ task :migrate, :model do |t, args|
80
+ create_dm_path
81
+ args.model == nil ? DataMapper.auto_migrate! : args.model.constantize.auto_migrate!
82
+ end
83
+
84
+ namespace :migrate do
85
+
86
+ desc 'Migrate up to a specific migration number' if defined? DataMapper
87
+ task :up, :number do |t, args|
88
+ create_dm_path
89
+ require 'dm-migrations/migration_runner'
90
+ Dir['./data/migrations/*.rb'].each { |m| require m }
91
+ args.number == nil ? migrate_up! : migrate_up!(args.number)
92
+ end
93
+
94
+ desc 'Migrate down to a specific migration number' if defined? DataMapper
95
+ task :down, :number do |t, args|
96
+ create_dm_path
97
+ require 'dm-migrations/migration_runner'
98
+ Dir['./data/migrations/*.rb'].each { |m| require m }
99
+ args.number == nil ? migrate_down! : migrate_down!(args.number)
100
+ end
101
+
102
+ end
103
+
104
+ namespace :run do
105
+
106
+ desc 'Run one or all /data/seeds scripts' if defined? DataMapper
107
+ task :seed, :file do |t, args|
108
+ if args.file == nil
109
+ Dir["./data/seeds/**/*.rb"].each { |file| require file }
110
+ else
111
+ require "./data/seeds/#{args.file}"
112
+ end
113
+ end
114
+
115
+ end
116
+
117
+ end
@@ -0,0 +1,11 @@
1
+ namespace :setup do
2
+
3
+ desc 'Set up Pony'
4
+ task :pony do
5
+ create_directory './settings'
6
+ append_to_file './Gemfile', "\ngem 'pony', '~> 1.4'\n"
7
+ copy_file "#{TEMPLATES}/pony/settings/pony.rb",
8
+ "./settings/pony.rb"
9
+ end
10
+
11
+ end
@@ -0,0 +1,23 @@
1
+ namespace :sinatra do
2
+
3
+ namespace :add do
4
+
5
+ desc 'Add a namespaced /routes file'
6
+ task :routes, :namespace do |t, args|
7
+ if args.namespace == nil
8
+ puts 'You must define a route namespace.'
9
+ puts 'Example: rake sinatra:add:routes[my_routes]'
10
+ exit
11
+ end
12
+ create_directory './routes', './tests', './tests/routes'
13
+ copy_template "#{TEMPLATES}/sinatra/routes/routes.rb",
14
+ "./routes/#{args.namespace}.rb",
15
+ { namespace: args.namespace }
16
+ copy_template "#{TEMPLATES}/sinatra/tests/routes/routes_tests.rb",
17
+ "./tests/routes/#{args.namespace}_tests.rb",
18
+ { namespace: args.namespace }
19
+ end
20
+
21
+ end
22
+
23
+ end