camping 2.1.532 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +72 -53
- data/Rakefile +25 -20
- data/bin/camping +1 -0
- data/book/01_introduction.md +6 -6
- data/book/02_getting_started.md +348 -267
- data/book/03_more_about_controllers.md +124 -0
- data/book/04_more_about_views.md +118 -0
- data/book/05_more_about_markaby.md +173 -0
- data/book/06_more_about_models.md +58 -0
- data/book/06_rules_of_thumb.md +143 -0
- data/book/07_philosophy.md +23 -0
- data/book/08_publishing_an_app.md +118 -0
- data/book/09_upgrade_notes.md +96 -0
- data/book/10_middleware.md +69 -0
- data/book/11_gear.md +50 -0
- data/examples/blog.rb +38 -38
- data/lib/camping/ar.rb +20 -5
- data/lib/camping/commands.rb +388 -0
- data/lib/camping/gear/filters.rb +48 -0
- data/lib/camping/gear/inspection.rb +32 -0
- data/lib/camping/gear/kuddly.rb +178 -0
- data/lib/camping/gear/nancy.rb +170 -0
- data/lib/camping/loads.rb +15 -0
- data/lib/camping/mab.rb +1 -1
- data/lib/camping/reloader.rb +22 -17
- data/lib/camping/server.rb +145 -70
- data/lib/camping/session.rb +8 -5
- data/lib/camping/template.rb +1 -2
- data/lib/camping/tools.rb +43 -0
- data/lib/camping/version.rb +6 -0
- data/lib/camping-unabridged.rb +360 -133
- data/lib/camping.rb +78 -47
- data/lib/campingtrip.md +341 -0
- data/test/app_camping_gear.rb +121 -0
- data/test/app_camping_tools.rb +1 -0
- data/test/app_config.rb +30 -0
- data/test/app_cookies.rb +1 -1
- data/test/app_file.rb +3 -3
- data/test/app_goes_meta.rb +23 -0
- data/test/app_inception.rb +39 -0
- data/test/app_markup.rb +5 -20
- data/test/app_migrations.rb +16 -0
- data/test/app_partials.rb +1 -1
- data/test/app_prefixed.rb +88 -0
- data/test/app_reloader.rb +1 -2
- data/test/app_route_generating.rb +69 -2
- data/test/app_sessions.rb +24 -2
- data/test/app_simple.rb +18 -18
- data/test/apps/migrations.rb +82 -82
- data/test/apps/misc.rb +1 -1
- data/test/gear/gear_nancy.rb +129 -0
- data/test/test_helper.rb +69 -12
- metadata +152 -92
- data/CHANGELOG +0 -145
- data/book/51_upgrading.md +0 -110
@@ -0,0 +1,388 @@
|
|
1
|
+
module Camping
|
2
|
+
module CommandsHelpers
|
3
|
+
|
4
|
+
# transform app_name to snake case
|
5
|
+
def self.to_snake_case(string)
|
6
|
+
string = string.to_s if string.class == Symbol
|
7
|
+
string.gsub(/::/, '/').
|
8
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
9
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
10
|
+
tr("-", "_").
|
11
|
+
downcase
|
12
|
+
end
|
13
|
+
|
14
|
+
RouteCollection = Struct.new(:routes)
|
15
|
+
class RouteCollection
|
16
|
+
# Displays formatted routes from a route collection
|
17
|
+
# Assumes that Route structs are stored in :routes.
|
18
|
+
def display
|
19
|
+
current_app, current_controller, current_method = "", "", ""
|
20
|
+
puts "App VERB Route"
|
21
|
+
routes.each { |r|
|
22
|
+
if current_app != r.app.to_s
|
23
|
+
current_app = r.app.to_s
|
24
|
+
puts "-----------------------------------"
|
25
|
+
puts r.app_header
|
26
|
+
end
|
27
|
+
if current_controller != r.controller.to_s
|
28
|
+
current_controller = r.controller.to_s
|
29
|
+
puts r.controller_header
|
30
|
+
end
|
31
|
+
puts r.padded_message true
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
# Route Struct, for making and formatting a route.
|
38
|
+
Route = Struct.new(:http_method, :controller, :app, :url)
|
39
|
+
class Route
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
"#{controller}: #{http_method}: #{url} - #{replace_reg url}"
|
43
|
+
end
|
44
|
+
|
45
|
+
# pad the controller name to be the right length, if we can.
|
46
|
+
def padded_message(with_method = false)
|
47
|
+
"#{pad}#{(with_method ? http_method.to_s.upcase.ljust(pad.length, " ") : pad)}#{replace_reg url}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def app_header
|
51
|
+
"#{app.to_s}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def controller_header
|
55
|
+
"#{pad}#{app.to_s}::#{controller.to_s}"
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def http_methods
|
61
|
+
["get", "post", "put", "patch", "delete"]
|
62
|
+
end
|
63
|
+
|
64
|
+
def replace_reg(pattern = "")
|
65
|
+
xstr = "([^/]+)"; nstr = "(\d+)"
|
66
|
+
pattern = pattern.gsub(xstr, ":string").gsub("(\\d+)", ":integer") unless pattern == "/"
|
67
|
+
pattern
|
68
|
+
end
|
69
|
+
|
70
|
+
def pad
|
71
|
+
" "
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
class RoutesParser
|
77
|
+
def self.parse(app)
|
78
|
+
new(app).parse
|
79
|
+
end
|
80
|
+
|
81
|
+
def initialize(app = Camping)
|
82
|
+
@parent_app, @routes = app, []
|
83
|
+
end
|
84
|
+
|
85
|
+
def parse
|
86
|
+
routes = @parent_app.make_camp
|
87
|
+
collected_routes = []
|
88
|
+
|
89
|
+
make_routes = -> (a) {
|
90
|
+
|
91
|
+
a::X.all.map {|c|
|
92
|
+
k = a::X.const_get(c)
|
93
|
+
im = k.instance_methods(false).map!(&:to_s)
|
94
|
+
methods = im & ["get", "post", "put", "patch", "delete"]
|
95
|
+
if k.respond_to?:urls
|
96
|
+
methods.each { |m|
|
97
|
+
k.urls.each { |u|
|
98
|
+
collected_routes.append Camping::CommandsHelpers::Route.new(m,c,a.to_s,u)
|
99
|
+
}
|
100
|
+
}
|
101
|
+
end
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
if @parent_app == Camping
|
106
|
+
@parent_app::Apps.each {|a|
|
107
|
+
make_routes.(a)
|
108
|
+
}
|
109
|
+
else
|
110
|
+
make_routes.(@parent_app)
|
111
|
+
end
|
112
|
+
|
113
|
+
routes_collection = Camping::CommandsHelpers::RouteCollection.new(collected_routes)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
class Generators
|
120
|
+
class << self
|
121
|
+
|
122
|
+
# write a file
|
123
|
+
def write(file, content)
|
124
|
+
raise "Cannot write to nil file." unless file
|
125
|
+
folder = File.dirname(file)
|
126
|
+
`mkdir -p #{folder}` unless File.exist?(folder)
|
127
|
+
File.open(file, 'w') { |f| f.write content }
|
128
|
+
end
|
129
|
+
|
130
|
+
# read a file
|
131
|
+
def read(file)
|
132
|
+
File.read(file)
|
133
|
+
end
|
134
|
+
|
135
|
+
def make_camp_file(app_name="Tent")
|
136
|
+
write "camp.rb", <<-RUBY
|
137
|
+
require 'camping'
|
138
|
+
|
139
|
+
Camping.goes :#{app_name}
|
140
|
+
|
141
|
+
module #{app_name}
|
142
|
+
module Models
|
143
|
+
end
|
144
|
+
|
145
|
+
module Controllers
|
146
|
+
class Index
|
147
|
+
def get
|
148
|
+
@title = "#{app_name}"
|
149
|
+
render :index
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
module Helpers
|
155
|
+
end
|
156
|
+
|
157
|
+
module Views
|
158
|
+
|
159
|
+
def layout
|
160
|
+
html do
|
161
|
+
head do
|
162
|
+
title '#{app_name}'
|
163
|
+
link :rel => 'stylesheet', :type => 'text/css',
|
164
|
+
:href => '/styles.css', :media => 'screen'
|
165
|
+
end
|
166
|
+
body do
|
167
|
+
h1 '#{app_name}'
|
168
|
+
|
169
|
+
div.wrapper! do
|
170
|
+
self << yield
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def index
|
177
|
+
h2 'Let\'s go Camping'
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
RUBY
|
185
|
+
end
|
186
|
+
|
187
|
+
# makes a gitignore.
|
188
|
+
def make_gitignore
|
189
|
+
write '.gitignore', <<-GIT
|
190
|
+
.DS_Store
|
191
|
+
node_modules/
|
192
|
+
tmp/
|
193
|
+
db/camping.db
|
194
|
+
db/camping.sqlite3
|
195
|
+
db/camping.sqlite
|
196
|
+
GIT
|
197
|
+
end
|
198
|
+
|
199
|
+
def make_ruby_version
|
200
|
+
write '.ruby-version', <<-RUBY
|
201
|
+
#{RUBY_VERSION}
|
202
|
+
RUBY
|
203
|
+
end
|
204
|
+
|
205
|
+
# writes a rakefile
|
206
|
+
def make_rakefile
|
207
|
+
write 'Rakefile', <<-TXT
|
208
|
+
# Rakefile
|
209
|
+
require 'rake'
|
210
|
+
require 'rake/clean'
|
211
|
+
require 'rake/testtask'
|
212
|
+
require 'tempfile'
|
213
|
+
require 'open3'
|
214
|
+
|
215
|
+
task :default => :test
|
216
|
+
task :test => 'test:all'
|
217
|
+
|
218
|
+
namespace 'test' do
|
219
|
+
Rake::TestTask.new('all') do |t|
|
220
|
+
t.libs << 'test'
|
221
|
+
t.test_files = FileList['test/nuts_*.rb']
|
222
|
+
end
|
223
|
+
end
|
224
|
+
TXT
|
225
|
+
end
|
226
|
+
|
227
|
+
# write a config.kdl
|
228
|
+
def make_configkdl
|
229
|
+
write 'config.kdl', <<-KDL
|
230
|
+
# config.kdl
|
231
|
+
hostname {
|
232
|
+
default "localhost"
|
233
|
+
}
|
234
|
+
KDL
|
235
|
+
end
|
236
|
+
|
237
|
+
# write a Gemfile
|
238
|
+
def make_gemfile
|
239
|
+
write 'Gemfile', <<-GEM
|
240
|
+
# frozen_string_literal: true
|
241
|
+
source 'https://rubygems.org'
|
242
|
+
|
243
|
+
gem 'camping'
|
244
|
+
gem 'puma'
|
245
|
+
gem 'rake'
|
246
|
+
|
247
|
+
group :production do
|
248
|
+
gem 'rack-ssl-enforcer'
|
249
|
+
end
|
250
|
+
|
251
|
+
group :development do
|
252
|
+
end
|
253
|
+
|
254
|
+
group :test do
|
255
|
+
gem 'minitest', '~> 5.0'
|
256
|
+
gem 'minitest-reporters'
|
257
|
+
gem 'rack-test'
|
258
|
+
end
|
259
|
+
|
260
|
+
GEM
|
261
|
+
end
|
262
|
+
|
263
|
+
# write a README.md
|
264
|
+
def make_readme
|
265
|
+
write 'README.md', <<-READ
|
266
|
+
# Camping
|
267
|
+
Camping is really fun and I hope you enjoy it.
|
268
|
+
|
269
|
+
Start camping by running: `camping` in the root directory.
|
270
|
+
|
271
|
+
READ
|
272
|
+
end
|
273
|
+
|
274
|
+
def make_public_folder
|
275
|
+
Dir.mkdir("public") unless Dir.exist?("public")
|
276
|
+
end
|
277
|
+
|
278
|
+
def make_test_folder
|
279
|
+
Dir.mkdir("test") unless Dir.exist?("test")
|
280
|
+
write 'test/test_helper.rb', <<-RUBY
|
281
|
+
$:.unshift File.dirname(__FILE__) + '/../'
|
282
|
+
# shift to act like we're in the regular degular directory
|
283
|
+
|
284
|
+
begin
|
285
|
+
require 'rubygems'
|
286
|
+
rescue LoadError
|
287
|
+
end
|
288
|
+
|
289
|
+
require 'camping'
|
290
|
+
require 'minitest/autorun'
|
291
|
+
require 'minitest'
|
292
|
+
require 'rack/test'
|
293
|
+
require "minitest/reporters"
|
294
|
+
Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(:color => true)]
|
295
|
+
|
296
|
+
class TestCase < MiniTest::Test
|
297
|
+
include Rack::Test::Methods
|
298
|
+
|
299
|
+
def self.inherited(mod)
|
300
|
+
mod.app = Object.const_get(mod.to_s[/\w+/])
|
301
|
+
super
|
302
|
+
end
|
303
|
+
|
304
|
+
class << self
|
305
|
+
attr_accessor :app
|
306
|
+
end
|
307
|
+
|
308
|
+
def body() last_response.body end
|
309
|
+
def app() self.class.app end
|
310
|
+
|
311
|
+
def assert_reverse
|
312
|
+
begin
|
313
|
+
yield
|
314
|
+
rescue Exception
|
315
|
+
else
|
316
|
+
assert false, "Block didn't fail"
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
def assert_body(str)
|
321
|
+
case str
|
322
|
+
when Regexp
|
323
|
+
assert_match(str, last_response.body.strip)
|
324
|
+
else
|
325
|
+
assert_equal(str.to_s, last_response.body.strip)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
def assert_status(code)
|
330
|
+
assert_equal(code, last_response.status)
|
331
|
+
end
|
332
|
+
|
333
|
+
def test_silly; end
|
334
|
+
|
335
|
+
end
|
336
|
+
|
337
|
+
RUBY
|
338
|
+
end
|
339
|
+
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
class Commands
|
344
|
+
|
345
|
+
# A helper method to spit out Routes for an application
|
346
|
+
def self.routes(theApp = Camping, silent = false)
|
347
|
+
routes = Camping::CommandsHelpers::RoutesParser.parse theApp
|
348
|
+
routes.display unless silent == true
|
349
|
+
return routes
|
350
|
+
end
|
351
|
+
|
352
|
+
def self.new_cmd(app_name=:Camp)
|
353
|
+
app_name = :Camp if app_name == nil
|
354
|
+
app_name = app_name.to_sym if app_name.class == String
|
355
|
+
|
356
|
+
snake_app_name = Camping::CommandsHelpers.to_snake_case(app_name)
|
357
|
+
|
358
|
+
# make a directory then move there.
|
359
|
+
# _original_dir = Dir.pwd
|
360
|
+
Dir.mkdir("#{snake_app_name}") unless Dir.exist?("#{snake_app_name}")
|
361
|
+
Dir.chdir("#{snake_app_name}")
|
362
|
+
|
363
|
+
# generate a new camping app in a directory named after it:
|
364
|
+
Generators::make_camp_file(app_name)
|
365
|
+
Generators::make_gitignore()
|
366
|
+
Generators::make_rakefile()
|
367
|
+
Generators::make_ruby_version()
|
368
|
+
Generators::make_configkdl()
|
369
|
+
Generators::make_gemfile()
|
370
|
+
Generators::make_readme()
|
371
|
+
Generators::make_public_folder()
|
372
|
+
Generators::make_test_folder()
|
373
|
+
|
374
|
+
# optionally add omnibus support
|
375
|
+
# add src/ folder
|
376
|
+
# add lib/ folder
|
377
|
+
# add views/ folder
|
378
|
+
|
379
|
+
# optionally add a local database too, through guidebook
|
380
|
+
# add db/ folder
|
381
|
+
# add db/migrate folder
|
382
|
+
# add db/config.kdl
|
383
|
+
# append migrations stuff to Rakefile.
|
384
|
+
`ls`
|
385
|
+
end
|
386
|
+
|
387
|
+
end
|
388
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# This gear is originally from filtering_camping gem by judofyr, and techarc.
|
2
|
+
module Gear
|
3
|
+
module Filters
|
4
|
+
module ClassMethods
|
5
|
+
def filters
|
6
|
+
@_filters ||= {:before => [], :after => []}
|
7
|
+
end
|
8
|
+
|
9
|
+
def before(actions, &blk)
|
10
|
+
actions = [actions] unless actions.is_a?(Array)
|
11
|
+
actions.each do |action|
|
12
|
+
filters[:before] << [action, blk]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def after(actions, &blk)
|
17
|
+
actions = [actions] unless actions.is_a?(Array)
|
18
|
+
actions.each do |action|
|
19
|
+
filters[:after] << [action, blk]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.included(mod)
|
25
|
+
mod.extend(ClassMethods)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.setup(app, *a, &block) end
|
29
|
+
|
30
|
+
def run_filters(type)
|
31
|
+
o = self.class.to_s.split("::")
|
32
|
+
filters = Object.const_get(o.first).filters
|
33
|
+
filters[type].each do |filter|
|
34
|
+
if (filter[0].is_a?(Symbol) && (filter[0] == o.last.to_sym || filter[0] == :all)) ||
|
35
|
+
(filter[0].is_a?(String) && /^#{filter[0]}\/?$/ =~ @env.REQUEST_URI)
|
36
|
+
self.instance_eval(&filter[1])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def service(*a)
|
42
|
+
run_filters(:before)
|
43
|
+
super(*a)
|
44
|
+
run_filters(:after)
|
45
|
+
self
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
# This gear adds inspection utilities to Camping
|
3
|
+
module Gear
|
4
|
+
module Inspection
|
5
|
+
|
6
|
+
# reserved module for Camping Class Methods we add because we're the best.
|
7
|
+
module ClassMethods
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
module ControllersClassMethods
|
12
|
+
# All Helper helps us inspect our Controllers from outside of the app.
|
13
|
+
# TODO: Move to CampTools for introspection.
|
14
|
+
def all
|
15
|
+
all = []
|
16
|
+
constants.map { |c|
|
17
|
+
all << c.name if !["I", "Camper"].include? c.to_s
|
18
|
+
}
|
19
|
+
all
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.included(mod)
|
24
|
+
mod.extend(ClassMethods)
|
25
|
+
mod::Controllers.extend(ControllersClassMethods)
|
26
|
+
end
|
27
|
+
|
28
|
+
# empty setup as determined by the Camping Gear Spec API.
|
29
|
+
def self.setup(app, *a, &block) end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# lib/camping/config
|
3
|
+
# load and parse settings.
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'kdl'
|
7
|
+
rescue LoadError => e
|
8
|
+
raise "kdl could not be loaded (is it installed?): #{e.message}"
|
9
|
+
end
|
10
|
+
|
11
|
+
module Gear
|
12
|
+
|
13
|
+
# Namespace to hide all of the KDL Configure stuff.
|
14
|
+
module Kuddly
|
15
|
+
WARNINGS = []
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def configure(app)
|
19
|
+
config = Gear::Kuddly.get_config()
|
20
|
+
config.each do |k,v|
|
21
|
+
app.set(k.to_sym, v)
|
22
|
+
end unless config == nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
|
28
|
+
def included(mod)
|
29
|
+
mod.extend(ClassMethods)
|
30
|
+
end
|
31
|
+
|
32
|
+
# required for compliance reasons
|
33
|
+
def setup(app, *a, &block) end
|
34
|
+
|
35
|
+
def kdl_error_message(kdl_string="",error_message="", error=nil)
|
36
|
+
# parse error message to get line number and column:
|
37
|
+
m = error_message.match( /\((\d)+:(\d)\)/ )
|
38
|
+
|
39
|
+
if m == nil
|
40
|
+
warn "kdl_error_message was called on a nil error message?"
|
41
|
+
warn "message: #{error_message}"
|
42
|
+
warn "kdl_string: #{kdl_string}"
|
43
|
+
warn "current dir: #{Dir.pwd}"
|
44
|
+
warn "#{error}"
|
45
|
+
return
|
46
|
+
end
|
47
|
+
|
48
|
+
line = m[1].to_i
|
49
|
+
lines = kdl_string.split( "\n" )
|
50
|
+
|
51
|
+
em = "\n"
|
52
|
+
em << "#{line-4}: #{lines[line-4]}\n" if (line-4) > 0 && (line-4) < lines.count
|
53
|
+
em << "#{line-3}: #{lines[line-3]}\n" if (line-3) > 0 && (line-3) < lines.count
|
54
|
+
em << "#{line-2}: #{lines[line-2]}\n" if (line-2) > 0 && (line-2) < lines.count
|
55
|
+
em << "#{line-1}: #{lines[line-1]}\n" if (line-1) > 0 && (line-1) < lines.count
|
56
|
+
em << "#{line}: #{lines[line]}\n" if (line)
|
57
|
+
em << "#{line+1}: #{lines[line+1]}\n" if (line+1) > 0 && (line+1) < lines.count
|
58
|
+
em << "#{line+2}: #{lines[line+2]}\n" if (line+2) > 0 && (line+2) < lines.count
|
59
|
+
em << "#{line+3}: #{lines[line+3]}\n" if (line+3) > 0 && (line+3) < lines.count
|
60
|
+
em << "#{line+4}: #{lines[line+4]}\n" if (line+4) > 0 && (line+4) < lines.count
|
61
|
+
# em << "\n"
|
62
|
+
WARNINGS << em
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# parses a kdl file into a kdl document Object.
|
67
|
+
# returns nil if it's false. Also assumes that the file is exists.
|
68
|
+
# an optional silence_warnings parameter is set to false. This is used for
|
69
|
+
# testing.
|
70
|
+
def parse_kdl(config_file = nil, silence_warnings = false)
|
71
|
+
begin
|
72
|
+
kdl_string = File.open(config_file).read
|
73
|
+
rescue => error # Errno::ENOENT
|
74
|
+
puts ""
|
75
|
+
puts "Error trying to read a config file: \"#{error}.\""
|
76
|
+
puts " Attempted to open: #{config_file}"
|
77
|
+
puts " Current directory: #{Dir.pwd}"
|
78
|
+
puts " files in directory: #{Dir.glob('*')}"
|
79
|
+
puts ""
|
80
|
+
end
|
81
|
+
|
82
|
+
begin
|
83
|
+
kdl_doc = KDL.parse_document(kdl_string)
|
84
|
+
rescue => error
|
85
|
+
warn "#{error}"
|
86
|
+
# parse error message to get line number and column:
|
87
|
+
message = Kuddly.kdl_error_message(kdl_string, error.message, error)
|
88
|
+
m = error.message.match( /\((\d)+:(\d)\)/ )
|
89
|
+
|
90
|
+
line, column = m[1].to_i, m[2].to_i if m.respond_to? '[]'
|
91
|
+
|
92
|
+
warn("\nError parsing config: #{config_file}, on line: #{line}, at column: #{column}.", message, "#{error.message}", uplevel: 1) unless silence_warnings
|
93
|
+
end
|
94
|
+
|
95
|
+
kdl_doc
|
96
|
+
end
|
97
|
+
|
98
|
+
# Maps kdl settings. Settings Example:
|
99
|
+
# ```
|
100
|
+
# database {
|
101
|
+
# default adapter="sqlite3" database="#{database}" host="localhost" max_connections=5 timeout=5000
|
102
|
+
# development
|
103
|
+
# test
|
104
|
+
# production adapter="postgres" database="kow"
|
105
|
+
# }
|
106
|
+
# ```
|
107
|
+
def map_kdl(kdl_doc=nil)
|
108
|
+
configs = {}
|
109
|
+
|
110
|
+
if kdl_doc
|
111
|
+
|
112
|
+
# We have a kdl document, so that's good.
|
113
|
+
# iterate through each top level node to see what kind of data we have.
|
114
|
+
kdl_doc.nodes.each do |d|
|
115
|
+
config_name = d.name.to_sym
|
116
|
+
configs[config_name] = {}
|
117
|
+
|
118
|
+
if d.children.length > 0
|
119
|
+
# we've got kids!
|
120
|
+
# This node will have sub nodes with properties
|
121
|
+
d.children.each do |en|
|
122
|
+
env_name = en.name.to_sym
|
123
|
+
# parse the settings for each environment
|
124
|
+
configs[config_name][env_name] = {}
|
125
|
+
en.properties.each do |key, value|
|
126
|
+
configs[config_name][env_name][key.to_sym] = value.value
|
127
|
+
end
|
128
|
+
end
|
129
|
+
else
|
130
|
+
# we've got raw data, so place it into a default hash spot.
|
131
|
+
vals = []
|
132
|
+
if d.arguments.length > 1
|
133
|
+
d.arguments.each { |v| vals << v.value }
|
134
|
+
else
|
135
|
+
vals = d.arguments.first.value
|
136
|
+
end
|
137
|
+
|
138
|
+
configs[config_name]['default'] = vals
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
configs
|
144
|
+
end
|
145
|
+
|
146
|
+
# get_config
|
147
|
+
# searches for any kdl document inside of the root folder
|
148
|
+
# Then parses it, and merges the data based on the current environment.
|
149
|
+
def get_config(provided_config_file = nil)
|
150
|
+
|
151
|
+
config_file, kdl_doc, merged_configs = provided_config_file, nil, {}
|
152
|
+
config_file = get_root_config_file() unless provided_config_file != nil
|
153
|
+
|
154
|
+
# If the config file is just nil then we probably don't have one.
|
155
|
+
return nil unless config_file != nil
|
156
|
+
|
157
|
+
# parses then maps the kdl
|
158
|
+
configs = map_kdl(parse_kdl(config_file))
|
159
|
+
env = ENV['environment'] ||= "development"
|
160
|
+
|
161
|
+
configs.each do |key, setting|
|
162
|
+
if setting.has_key? :default && env.to_sym
|
163
|
+
merged_configs[key] = setting[:default].merge(setting[env.to_sym])
|
164
|
+
else
|
165
|
+
merged_configs[key] = setting['default']
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
merged_configs
|
170
|
+
end
|
171
|
+
|
172
|
+
# get kdl config file
|
173
|
+
def get_root_config_file(search_pattern = "config.kdl")
|
174
|
+
Dir.glob(search_pattern).first
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|