ella 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +56 -0
- data/LICENSE.txt +21 -0
- data/README.md +115 -0
- data/ella-0.1.0.gem +0 -0
- data/ella.gemspec +26 -0
- data/exe/ella +14 -0
- data/lib/ella.rb +45 -0
- data/lib/ella/cli.rb +114 -0
- data/lib/ella/controller.rb +36 -0
- data/lib/ella/generator.rb +42 -0
- data/lib/ella/generator/config_generator.rb +16 -0
- data/lib/ella/generator/controller_generator.rb +34 -0
- data/lib/ella/generator/destroyer.rb +44 -0
- data/lib/ella/generator/gemfile_generator.rb +15 -0
- data/lib/ella/generator/model_generator.rb +27 -0
- data/lib/ella/generator/project_generator.rb +88 -0
- data/lib/ella/generator/rackfile_generator.rb +76 -0
- data/lib/ella/generator/view_generator.rb +42 -0
- data/lib/ella/log.rb +70 -0
- data/lib/ella/model.rb +0 -0
- data/lib/ella/name_formatter.rb +32 -0
- data/lib/ella/pipeline.rb +99 -0
- data/lib/ella/reloader.rb +430 -0
- data/lib/ella/server.rb +107 -0
- data/lib/ella/template.rb +46 -0
- data/lib/ella/test.rb +9 -0
- data/lib/ella/version.rb +3 -0
- data/lib/ella/view.rb +0 -0
- data/templates/Gemfile +12 -0
- data/templates/configs/css.rb +20 -0
- data/templates/configs/js.rb +19 -0
- data/templates/configs/puma.rb +5 -0
- data/templates/controller +9 -0
- data/templates/controllers/root.rb +7 -0
- data/templates/main.rb +8 -0
- data/templates/model +6 -0
- data/templates/test +22 -0
- data/templates/views/layout.erb +18 -0
- data/templates/views/root/index.erb +3 -0
- data/version.txt +1 -0
- metadata +94 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'sinatra/base'
|
|
4
|
+
require_relative 'reloader'
|
|
5
|
+
|
|
6
|
+
module Ella
|
|
7
|
+
# Sinatra was not specifically designed to have different modular controller
|
|
8
|
+
# files. Some of the magic needs to go here, and maintaining a specific
|
|
9
|
+
# loading order is important: seemingly insignificant changes can break the
|
|
10
|
+
# little hacks that allow Sinatra to be used as a macro-framework.
|
|
11
|
+
class Controller < Sinatra::Base
|
|
12
|
+
set :views, Dir.pwd + '/views' # TODO This can be more dynamic.
|
|
13
|
+
set :public_folder, Dir.pwd + '/public'
|
|
14
|
+
|
|
15
|
+
configure :development do
|
|
16
|
+
register Sinatra::Reloader
|
|
17
|
+
also_reload File.join(Dir.pwd, 'models/*')
|
|
18
|
+
also_reload File.join(Dir.pwd, 'controllers/*')
|
|
19
|
+
after_reload do
|
|
20
|
+
puts('Reloading')
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# TODO: Some fancy-pants metaprogramming to allow for all user-defined
|
|
25
|
+
# pipelines.
|
|
26
|
+
def js_path
|
|
27
|
+
filename = Dir.glob("public/js/*").max_by {|f| File.mtime(f)}
|
|
28
|
+
filename.sub('public', '')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def css_path
|
|
32
|
+
filename = Dir.glob("public/css/*").max_by {|f| File.mtime(f)}
|
|
33
|
+
filename.sub('public', '')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ella
|
|
4
|
+
# This is an abstract class for the numerous generators that make up the bulk
|
|
5
|
+
# of this project. It cannot be run on its own.
|
|
6
|
+
# TODO: The first parameter should be part of the hash, for clarity.
|
|
7
|
+
class Generator
|
|
8
|
+
def initialize(directory: nil, files: [], templates: [], template_vars: {})
|
|
9
|
+
@directory = NameFormatter.new(directory) if directory
|
|
10
|
+
@files = files
|
|
11
|
+
@templates = templates
|
|
12
|
+
@template_vars = template_vars
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def run
|
|
16
|
+
raise NotImplementedError, 'Subclasses must define \'run\'.'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def generator_type
|
|
22
|
+
self.class.name.gsub(/^.*::(.*)Generator$/, '\1').downcase + 's'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def make_directory(special_name = nil)
|
|
26
|
+
target = special_name || generator_type
|
|
27
|
+
return if Dir.exist?(target)
|
|
28
|
+
|
|
29
|
+
Log.create(target + '/')
|
|
30
|
+
Dir.mkdir(target)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def make_test_directory
|
|
34
|
+
make_directory('tests')
|
|
35
|
+
make_directory("tests/#{generator_type}")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def target_name
|
|
39
|
+
@directory ? @directory.snake_case : @directory
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ella
|
|
4
|
+
# This class generates Ella project config files, which are needed to nicely
|
|
5
|
+
# configure Puma and Sinatra.
|
|
6
|
+
class ConfigGenerator < Generator
|
|
7
|
+
def run
|
|
8
|
+
Ella.find_root
|
|
9
|
+
make_directory('log') # necessary for Puma config
|
|
10
|
+
make_directory # make config directory
|
|
11
|
+
Ella::Template.new('configs/puma.rb').write
|
|
12
|
+
Ella::Template.new('configs/css.rb').write
|
|
13
|
+
Ella::Template.new('configs/js.rb').write
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ella
|
|
4
|
+
# Generator for controllers.
|
|
5
|
+
class ControllerGenerator < Generator
|
|
6
|
+
def run
|
|
7
|
+
# In the case of a controller, 'directory' and 'files' corresponds to the
|
|
8
|
+
# views being controlled. Every controller file represents a directory,
|
|
9
|
+
# and every controller route represents a file.
|
|
10
|
+
Ella.find_root
|
|
11
|
+
make_directory
|
|
12
|
+
@template_vars[:name] = @directory
|
|
13
|
+
@template_vars[:files] = @files
|
|
14
|
+
generate_controllers
|
|
15
|
+
generate_tests
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
# The root controller is a special case and does not use the generic template.
|
|
21
|
+
def generate_controllers
|
|
22
|
+
path = "controllers/#{@directory.snake_case}.rb"
|
|
23
|
+
template = (@directory.snake_case == 'root' ? nil : 'controller')
|
|
24
|
+
Ella::Template.new(path, generic_template: template, template_vars: @template_vars).write
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def generate_tests
|
|
28
|
+
make_test_directory
|
|
29
|
+
path = "tests/controllers/#{@directory.snake_case}_test.rb"
|
|
30
|
+
@template_vars[:controller] = true
|
|
31
|
+
Ella::Template.new(path, generic_template: 'test', template_vars: @template_vars).write
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ella
|
|
4
|
+
# This reverses the results of the m/v/c and test generators. Right now it
|
|
5
|
+
# destroys everything of a certain name if found. While that seems fairly
|
|
6
|
+
# blunt, there does not currenlty seem to be a reason to make it more
|
|
7
|
+
# specific.
|
|
8
|
+
# Although this is the opposite of a generator, the initialization requires
|
|
9
|
+
# the exact same things, and it makes sense to have the same interface, so it
|
|
10
|
+
# inherits from Generator.
|
|
11
|
+
class Destroyer < Generator
|
|
12
|
+
def run
|
|
13
|
+
@something_destroyed = false
|
|
14
|
+
|
|
15
|
+
attempt_to_destroy('models')
|
|
16
|
+
attempt_to_destroy('views')
|
|
17
|
+
attempt_to_destroy('controllers')
|
|
18
|
+
# TODO: destroy tests, once rspec is set up
|
|
19
|
+
|
|
20
|
+
Log.info('Nothing to destroy.') unless @something_destroyed
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def destroy_dir(path)
|
|
26
|
+
Log.destroy(path)
|
|
27
|
+
Dir.delete(path)
|
|
28
|
+
@something_destroyed = true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def destroy_file(path)
|
|
32
|
+
Log.destroy(path)
|
|
33
|
+
File.delete(path)
|
|
34
|
+
@something_destroyed = true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def attempt_to_destroy(type)
|
|
38
|
+
dir_path = File.join(Dir.pwd, "#{type}/#{@directory.snake_case}")
|
|
39
|
+
file_path = File.join(Dir.pwd, "#{type}/#{@directory.file_name}")
|
|
40
|
+
destroy_dir(dir_path) if Dir.exist?(dir_path)
|
|
41
|
+
destroy_file(file_path) if File.exist?(file_path)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ella
|
|
4
|
+
# Generates a Gemfile with the necessary dependencies for an ella project, and runs Bundle to
|
|
5
|
+
# install those dependencies.
|
|
6
|
+
class GemfileGenerator < Generator
|
|
7
|
+
def run
|
|
8
|
+
Ella.find_root
|
|
9
|
+
Ella::Template.new('Gemfile').write
|
|
10
|
+
Log.newline
|
|
11
|
+
Log.info('Running Bundle')
|
|
12
|
+
# Log.say(`bundle update`)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ella
|
|
4
|
+
# Generator for models.
|
|
5
|
+
class ModelGenerator < Generator
|
|
6
|
+
def run
|
|
7
|
+
Ella.find_root
|
|
8
|
+
make_directory
|
|
9
|
+
@template_vars[:name] = @directory
|
|
10
|
+
generate_models
|
|
11
|
+
generate_tests
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def generate_models
|
|
17
|
+
path = "models/#{@directory.snake_case}.rb"
|
|
18
|
+
Ella::Template.new(path, generic_template: 'model', template_vars: @template_vars).write
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def generate_tests
|
|
22
|
+
make_test_directory
|
|
23
|
+
path = "tests/models/#{@directory.snake_case}_test.rb"
|
|
24
|
+
Ella::Template.new(path, generic_template: 'test', template_vars: @template_vars).write
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ella
|
|
4
|
+
# This beast of a subclass generates a new Ella project from scratch.
|
|
5
|
+
# --------
|
|
6
|
+
# Ella requires a main project file for almost everything. Consider this,
|
|
7
|
+
# anyone who might want to change the order of this method.
|
|
8
|
+
class ProjectGenerator < Generator
|
|
9
|
+
def run
|
|
10
|
+
Log.yell("Generating New Ella Project: \"#{@directory.human}\"")
|
|
11
|
+
|
|
12
|
+
prepare_project_directory
|
|
13
|
+
create_main_project_file
|
|
14
|
+
initialize_git
|
|
15
|
+
generate_pipeline_directories
|
|
16
|
+
initialize_config
|
|
17
|
+
generate_model_directory
|
|
18
|
+
generate_views
|
|
19
|
+
generate_controllers
|
|
20
|
+
initialize_bundle
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def prepare_project_directory
|
|
26
|
+
if Dir.entries('.').include?(@directory.snake_case)
|
|
27
|
+
Log.error('A directory with that name already exists. Aborting.')
|
|
28
|
+
abort
|
|
29
|
+
end
|
|
30
|
+
Log.newline
|
|
31
|
+
Log.info('Creating project core')
|
|
32
|
+
make_directory(@directory.snake_case)
|
|
33
|
+
Dir.chdir(@directory.snake_case)
|
|
34
|
+
make_directory('temp')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def create_main_project_file
|
|
38
|
+
Ella::Template.new('main.rb', template_vars: { name: @directory }).write
|
|
39
|
+
Log.newline
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def initialize_git
|
|
43
|
+
Log.info('Initializing git')
|
|
44
|
+
`git init`
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def generate_pipeline_directories
|
|
48
|
+
Log.info('Generating pipeline directories')
|
|
49
|
+
make_directory('assets')
|
|
50
|
+
make_directory('assets/css')
|
|
51
|
+
make_directory('assets/js')
|
|
52
|
+
make_directory('public')
|
|
53
|
+
make_directory('public/css')
|
|
54
|
+
make_directory('public/js')
|
|
55
|
+
Log.newline
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def initialize_config
|
|
59
|
+
Log.info('Generating configuration files')
|
|
60
|
+
ConfigGenerator.new.run
|
|
61
|
+
Log.newline
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def generate_model_directory
|
|
65
|
+
make_directory('models')
|
|
66
|
+
Log.newline
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def generate_views
|
|
70
|
+
Log.info('Generating views')
|
|
71
|
+
ViewGenerator.new(templates: ['layout'], template_vars: { name: @directory }).run
|
|
72
|
+
ViewGenerator.new(directory: 'root', templates: ['index']).run
|
|
73
|
+
Log.newline
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def generate_controllers
|
|
77
|
+
Log.info('Generating root controller')
|
|
78
|
+
ControllerGenerator.new(directory: 'root').run
|
|
79
|
+
Log.newline
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def initialize_bundle
|
|
83
|
+
Log.info('Creating Gemfile')
|
|
84
|
+
GemfileGenerator.new.run
|
|
85
|
+
Log.newline
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ella
|
|
4
|
+
# The nature of Sinatra and Puma means that the config.ru file must initialize
|
|
5
|
+
# certain files. To make Ella work, this must be updated before the server is
|
|
6
|
+
# started.
|
|
7
|
+
# This is essentially a hack to deal with the fact that Sinatra was designed,
|
|
8
|
+
# apparently, to run one single controller file.
|
|
9
|
+
class RackfileGenerator < Generator
|
|
10
|
+
def run(mode = 'development')
|
|
11
|
+
@mode = mode
|
|
12
|
+
Ella.find_root
|
|
13
|
+
Log.info('Generating rack.ru...')
|
|
14
|
+
write
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def main_project_file_content
|
|
20
|
+
Ella.abort('Warning: "main.rb" not found. Aborting.') unless File.exist?('main.rb')
|
|
21
|
+
@main_file_content ||= File.open('main.rb').read
|
|
22
|
+
@main_file_content
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# This looks bad, but adds a good deal of flexibility for the user, should they ever be
|
|
26
|
+
# desperate to change the project name of an already-generated project.
|
|
27
|
+
def project_name
|
|
28
|
+
raw_project_name = main_project_file_content.scan(/class (.*) < Ella::Controller/).first.first
|
|
29
|
+
NameFormatter.new(raw_project_name)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_controllers
|
|
33
|
+
@controllers = Dir.entries('controllers').select { |e| e =~ /\.rb$/ }.map { |e| e[0..-4] }
|
|
34
|
+
rescue SystemCallError
|
|
35
|
+
make_directory('controllers')
|
|
36
|
+
retry
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def get_models
|
|
40
|
+
@models = Dir.entries('models').select { |e| e =~ /\.rb$/ }.map { |e| e[0..-4] }
|
|
41
|
+
rescue SystemCallError
|
|
42
|
+
make_directory('models')
|
|
43
|
+
retry
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def require_all_models
|
|
47
|
+
get_models
|
|
48
|
+
@models && @models.map { |e| "require_relative 'models/#{e}'" }.join("\n")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def require_all_controllers
|
|
52
|
+
get_controllers
|
|
53
|
+
@controllers && @controllers.map { |e| "require_relative 'controllers/#{e}'" }.join("\n")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def use_all_controllers
|
|
57
|
+
@controllers && @controllers.map { |e| "use #{e.capitalize}Controller" }.join("\n")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def write
|
|
61
|
+
File.open('rack.ru', 'w') { |f| f.puts(generate) }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def generate
|
|
65
|
+
"# WARNING: This file is autmatically generated by Ella, and may be rewritten\n" \
|
|
66
|
+
"# at any time. Any changes you make here may vanish. The appropriate place for\n" \
|
|
67
|
+
"# general changes is 'main.rb', which will never be overritten by Ella.)\n" \
|
|
68
|
+
"require 'ella'\n\n" \
|
|
69
|
+
"require './main'\n\n" \
|
|
70
|
+
"#{require_all_models}\n" \
|
|
71
|
+
"#{require_all_controllers}\n\n" \
|
|
72
|
+
"#{use_all_controllers}\n\n" \
|
|
73
|
+
"run #{project_name.pascal_case}\n"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ella
|
|
4
|
+
# Generates views for Ella projects.
|
|
5
|
+
class ViewGenerator < Generator
|
|
6
|
+
def run
|
|
7
|
+
Ella.find_root
|
|
8
|
+
make_directory
|
|
9
|
+
@path = "views/#{target_name}#{target_name ? '/' : ''}"
|
|
10
|
+
create_subdirectory if target_name && !Dir.exist?(@path)
|
|
11
|
+
create_files
|
|
12
|
+
copy_templates
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def full_filename(filename)
|
|
18
|
+
"#{@path}#{filename}.erb"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def create_file(filename)
|
|
22
|
+
Ella::Template.new(full_filename(filename), generic_template: :blank).write
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def copy_template(filename)
|
|
26
|
+
Ella::Template.new(full_filename(filename), template_vars: @template_vars).write
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def copy_templates
|
|
30
|
+
@templates.each { |filename| copy_template(filename) } if @templates
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def create_files
|
|
34
|
+
@files.each { |filename| create_file(filename) } if @files
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def create_subdirectory
|
|
38
|
+
Log.create(@path)
|
|
39
|
+
Dir.mkdir(@path)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
data/lib/ella/log.rb
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'logger'
|
|
4
|
+
require 'colorize'
|
|
5
|
+
|
|
6
|
+
module Ella
|
|
7
|
+
# A convenient minor reworking of Ruby's logger.
|
|
8
|
+
class Log
|
|
9
|
+
# The first three methods do not have timestamps and may be colour coded.
|
|
10
|
+
# They should not be anything less trivial than a heads up for the user.
|
|
11
|
+
def self.error(message)
|
|
12
|
+
say('ERROR: '.red + message.bold)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.newline
|
|
16
|
+
say("\n")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.info(message)
|
|
20
|
+
say(" ELLA: ".bold.blue + message.split(' ').map(&:capitalize).join(' ').bold)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.yell(message)
|
|
24
|
+
say(message.bold.blue)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.exit_message(message)
|
|
28
|
+
say(message.bold.yellow)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Misc. It would be best to phase this out in the long run.
|
|
32
|
+
def self.say(message)
|
|
33
|
+
puts message
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.unknown(message)
|
|
37
|
+
log_error.unknown(message)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.fatal(message)
|
|
41
|
+
say('FATAL: '.red + message.bold)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.warn(message)
|
|
45
|
+
log_info.warn(message)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.debug(message)
|
|
49
|
+
log_info.info(message)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.create(message)
|
|
53
|
+
output_str = ' ' * 8 + 'CREATE '.green.bold + message
|
|
54
|
+
say(output_str)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.destroy(message)
|
|
58
|
+
output_str = ' ' * 8 + 'DESTROY '.red.bold + message
|
|
59
|
+
say(output_str)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.log_info
|
|
63
|
+
Logger.new(STDOUT)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def self.log_error
|
|
67
|
+
Logger.new(STDERR)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|