cubic 0.1.0
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/Gemfile +4 -0
- data/README.md +141 -0
- data/Rakefile +6 -0
- data/lib/cubic.rb +29 -0
- data/lib/cubic/application.rb +61 -0
- data/lib/cubic/application/configurator.rb +16 -0
- data/lib/cubic/application/controller.rb +48 -0
- data/lib/cubic/application/logable.rb +19 -0
- data/lib/cubic/core_extensions.rb +1 -0
- data/lib/cubic/core_extensions/string.rb +1 -0
- data/lib/cubic/core_extensions/string/parse.rb +17 -0
- data/lib/cubic/engine.rb +49 -0
- data/lib/cubic/generator.rb +42 -0
- data/lib/cubic/generators/app.rb +68 -0
- data/lib/cubic/generators/base.rb +34 -0
- data/lib/cubic/generators/config.rb +67 -0
- data/lib/cubic/generators/controller.rb +64 -0
- data/lib/cubic/generators/gemfile.rb +23 -0
- data/lib/cubic/generators/migrations.rb +24 -0
- data/lib/cubic/generators/model.rb +64 -0
- data/lib/cubic/generators/templates/Rakefile +14 -0
- data/lib/cubic/generators/templates/application.haml +8 -0
- data/lib/cubic/generators/templates/application.rb +14 -0
- data/lib/cubic/generators/templates/boot.rb +4 -0
- data/lib/cubic/generators/templates/config.ru +7 -0
- data/lib/cubic/generators/templates/cubic +6 -0
- data/lib/cubic/generators/templates/database.rb +2 -0
- data/lib/cubic/generators/templates/sitemap.rb +42 -0
- data/lib/cubic/generators/view.rb +27 -0
- data/lib/cubic/middleware/static.rb +34 -0
- data/lib/cubic/render.rb +67 -0
- data/lib/cubic/response.rb +15 -0
- data/lib/cubic/router.rb +85 -0
- data/lib/cubic/version.rb +3 -0
- metadata +180 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Cubic
|
4
|
+
module Generator
|
5
|
+
# App is the last stop in the generation process. Once all generator
|
6
|
+
# instances have successfully dealt with the information given
|
7
|
+
# to them, they are sent here so they can turn that information
|
8
|
+
# into files, which are inserted into the generated application.
|
9
|
+
class App < Base
|
10
|
+
extend FileUtils
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def create(*generators)
|
14
|
+
directories
|
15
|
+
static_files
|
16
|
+
insert_generated_files(generators)
|
17
|
+
extra_files
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Creates default structure of appliction
|
23
|
+
def directories
|
24
|
+
structure = ['/app/views/layout', '/bin', '/config', '/db/migrations',
|
25
|
+
'/public/stylesheets', '/public/javascripts', '/spec']
|
26
|
+
structure.each { |f| mkdir_p(Config[:root_path] + f) }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Calls on all generators to turn their stored data into files
|
30
|
+
def insert_generated_files(generators)
|
31
|
+
generators.each(&:generate)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Fills the application with nondynamic files, which can be
|
35
|
+
# found in the templates directory
|
36
|
+
def static_files
|
37
|
+
wd = File.expand_path('../', __FILE__)
|
38
|
+
|
39
|
+
file_and_path = { 'cubic' => 'bin',
|
40
|
+
'config.ru' => '/',
|
41
|
+
'application.haml' => '/app/views/layout',
|
42
|
+
'application.rb' => '/config',
|
43
|
+
'boot.rb' => '/config',
|
44
|
+
'Rakefile' => '/',
|
45
|
+
'database.rb' => '/db',
|
46
|
+
'application.css' => '/public/stylesheets',
|
47
|
+
'application.js' => '/public/javascripts' }
|
48
|
+
|
49
|
+
file_and_path.keys.each do |k|
|
50
|
+
path = File.join(Config[:root_path], file_and_path[k])
|
51
|
+
if File.exist?("#{wd}/templates/#{k}")
|
52
|
+
FileUtils.cp("#{wd}/templates/#{k}", File.join(path, k))
|
53
|
+
else
|
54
|
+
File.open(File.join(path, k), 'w').close
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Creates Gemfile
|
60
|
+
def extra_files
|
61
|
+
gemfile = Gemfile.new
|
62
|
+
gemfile.design
|
63
|
+
gemfile.generate
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Cubic
|
4
|
+
module Generator
|
5
|
+
# All generators (model, view, controller) inherit from the base class.
|
6
|
+
class Base
|
7
|
+
attr_reader :files
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@files = []
|
11
|
+
end
|
12
|
+
|
13
|
+
# If callback is not defined within a generator, this method
|
14
|
+
# will be called to avoid a 'NoMethodError'.
|
15
|
+
def callback; end
|
16
|
+
|
17
|
+
# Generate takes an array of hashes from each generator,
|
18
|
+
# then creates a file from those params.
|
19
|
+
# If a generator requires a unique file generation,
|
20
|
+
# this method will be overwritten in that file.
|
21
|
+
def generate
|
22
|
+
@files.each do |info|
|
23
|
+
path = File.join(Config[:root_path], info[:path])
|
24
|
+
|
25
|
+
FileUtils.mkdir_p(path) unless File.directory?(path)
|
26
|
+
|
27
|
+
full_path = File.join(path, info[:name])
|
28
|
+
File.open(full_path, 'w') { |f| f.write(info[:content]) }
|
29
|
+
end
|
30
|
+
callback
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Cubic
|
2
|
+
module Generator
|
3
|
+
# Config stores data needed throughout the generation process.
|
4
|
+
class Config
|
5
|
+
|
6
|
+
@settings = {}
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def all
|
11
|
+
@settings
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
all[key] || defaults(key)
|
16
|
+
end
|
17
|
+
|
18
|
+
def root_path(path)
|
19
|
+
@settings[:root_path] = path
|
20
|
+
end
|
21
|
+
|
22
|
+
# Name of the application
|
23
|
+
def name(name)
|
24
|
+
@settings[:name] = name
|
25
|
+
end
|
26
|
+
|
27
|
+
# Prefered testing framework.
|
28
|
+
def test_type(type)
|
29
|
+
@settings[:test_type] = type || 'Rspec'
|
30
|
+
end
|
31
|
+
|
32
|
+
def orm(orm)
|
33
|
+
@settings[:orm] = orm || 'Sequel'
|
34
|
+
end
|
35
|
+
|
36
|
+
def db(db)
|
37
|
+
@settings[:db] = db || 'sqlite3'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Consider renaming to 'template engine'
|
41
|
+
def html_type(type)
|
42
|
+
@settings[:html_type] = type || 'haml'
|
43
|
+
end
|
44
|
+
|
45
|
+
def css_type(type)
|
46
|
+
@settings[:css_type] = type || 'css'
|
47
|
+
end
|
48
|
+
|
49
|
+
# Gems to be added to Gemfile
|
50
|
+
def gems(gems)
|
51
|
+
@settings[:gems] = gems
|
52
|
+
end
|
53
|
+
|
54
|
+
# Default options.
|
55
|
+
def defaults(name)
|
56
|
+
{ root_path: Dir.getwd,
|
57
|
+
name: 'No Name',
|
58
|
+
test_type: 'rspec',
|
59
|
+
orm: 'Sequel',
|
60
|
+
db: 'sqlite3',
|
61
|
+
html_type: 'haml',
|
62
|
+
css_type: 'css' }[name]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Cubic
|
2
|
+
module Generator
|
3
|
+
# Controller fulfils the C in the MVC pattern. Files the Model generator
|
4
|
+
# creates will include a class inheriting from the CubicController.
|
5
|
+
class Controller < Base
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@view = View.new
|
9
|
+
super()
|
10
|
+
end
|
11
|
+
|
12
|
+
# Creates a hash that will be used for file generation purposes
|
13
|
+
def design(name, options = {})
|
14
|
+
if options[:actions] && options[:actions].any?
|
15
|
+
actions = options[:actions]
|
16
|
+
create_views(name, actions)
|
17
|
+
else
|
18
|
+
actions = []
|
19
|
+
end
|
20
|
+
|
21
|
+
@files << { name: "#{name}_controller.rb",
|
22
|
+
path: '/app/controllers/',
|
23
|
+
content: build_controller(name, actions) }
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def create_views(name, actions)
|
30
|
+
actions.each do |a|
|
31
|
+
@view.design(name, a)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Called after the Controller generated has created its files.
|
36
|
+
def callback
|
37
|
+
@view.generate
|
38
|
+
end
|
39
|
+
|
40
|
+
def build_controller(name, actions)
|
41
|
+
"#{controller_name(name)} < Cubic::CubicController\n#{build_actions(name, actions)}\nend"
|
42
|
+
end
|
43
|
+
|
44
|
+
def build_method(name, a)
|
45
|
+
"\n#{tab}get '#{a}' do\n#{tab}\s\shaml '#{name}/#{a}'\n#{tab}end\n"
|
46
|
+
end
|
47
|
+
|
48
|
+
def controller_name(name)
|
49
|
+
"class #{name.to_s.split('_').map(&:capitalize).join('')}Controller"
|
50
|
+
end
|
51
|
+
|
52
|
+
def build_actions(name, actions)
|
53
|
+
actions.map! do |a|
|
54
|
+
build_method(name, a)
|
55
|
+
end
|
56
|
+
"\s\snamespace '#{name}' do\n#{actions.join}\n\s\send"
|
57
|
+
end
|
58
|
+
|
59
|
+
def tab
|
60
|
+
"\s" * 4
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Cubic
|
2
|
+
module Generator
|
3
|
+
# Creates a Gemfiles in the root directory of the generated application.
|
4
|
+
class Gemfile < Base
|
5
|
+
|
6
|
+
# Creates a hash that will be used for file generation purposes
|
7
|
+
def design
|
8
|
+
group = ['source "https://rubygems.org"',
|
9
|
+
'gem "sinatra"',
|
10
|
+
'gem "rake"',
|
11
|
+
'gem "sequel"',
|
12
|
+
'gem "haml"']
|
13
|
+
|
14
|
+
gems = [Config[:gems], Config[:orm], Config[:db]].flatten.compact
|
15
|
+
gems.map! { |gem| "gem '#{gem}'" }
|
16
|
+
|
17
|
+
@files << { name: 'Gemfile',
|
18
|
+
path: '/',
|
19
|
+
content: gems.unshift(group).flatten!.join("\n") }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Cubic
|
2
|
+
module Generator
|
3
|
+
# Generates the migrations for columns and rows attached to a model.
|
4
|
+
class Migrations < Base
|
5
|
+
|
6
|
+
# Creates a hash that will be used for file generation purposes
|
7
|
+
def design(name, options)
|
8
|
+
@files << { name: "create_#{name}.rb",
|
9
|
+
path: '/db/migrations/',
|
10
|
+
content: "DB.create_table :#{name.to_s.concat('s')} do
|
11
|
+
primary_key :id
|
12
|
+
#{pair(options)}
|
13
|
+
end" }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Example: {email: :string} turns into 't.string :email'
|
19
|
+
def pair(options)
|
20
|
+
options.keys.map { |f| "#{options[f].capitalize} :#{f}" }.join("\n")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Cubic
|
2
|
+
module Generator
|
3
|
+
# Model fulfils the M in the MVC pattern. Files the Model generator
|
4
|
+
# creates will include a class inheriting from the class your ORM
|
5
|
+
# suggests.
|
6
|
+
class Model < Base
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@migration = Migrations.new
|
10
|
+
super()
|
11
|
+
end
|
12
|
+
|
13
|
+
# Creates a hash that will be used for file generation purposes
|
14
|
+
def design(name, options = {})
|
15
|
+
@migration.design(name, options)
|
16
|
+
|
17
|
+
@files << { name: "#{name}.rb",
|
18
|
+
path: '/app/models',
|
19
|
+
content: format_model(name) }
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
# Called after a file is successfully generated from hash
|
24
|
+
# created by design method.
|
25
|
+
def callback
|
26
|
+
@migration.generate
|
27
|
+
end
|
28
|
+
|
29
|
+
# Allows user to specify code that should be included in
|
30
|
+
# generated model file.
|
31
|
+
# Example: add('has_many :users')
|
32
|
+
def add(*code)
|
33
|
+
code *= "\n"
|
34
|
+
@files.last[:content] = insert_code(@files.last[:content], code)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def format_model(name)
|
40
|
+
"class #{model_name(name)} < #{orm_class}\n\nend".chomp
|
41
|
+
end
|
42
|
+
|
43
|
+
def model_name(name)
|
44
|
+
name.to_s.split('_').map(&:capitalize).join('')
|
45
|
+
end
|
46
|
+
|
47
|
+
# Inserts code into the file to be generated.
|
48
|
+
def insert_code(model, code)
|
49
|
+
model.split(/(?<=#{orm_class})/).insert(1, code).join("\n")
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns what class should be inherted from based on ORM
|
53
|
+
# specified in sitemap file.
|
54
|
+
def orm_class
|
55
|
+
case Config[:orm]
|
56
|
+
when 'Sequel' || 'sequel'
|
57
|
+
'Sequel::Model'
|
58
|
+
else
|
59
|
+
Config[:orm]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
desc 'migrate database'
|
2
|
+
task :migrate do
|
3
|
+
require './db/database'
|
4
|
+
|
5
|
+
migrations = File.join('.', %w(db migrations *))
|
6
|
+
Dir.glob(migrations).each do |lf|
|
7
|
+
begin
|
8
|
+
require lf
|
9
|
+
puts 'Successfully migrated: '.concat(lf)
|
10
|
+
rescue
|
11
|
+
next
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
APP_PATH = File.expand_path('../..', __FILE__)
|
2
|
+
ENV['NAME'] = 'development'
|
3
|
+
|
4
|
+
require File.join(APP_PATH, 'db/database')
|
5
|
+
|
6
|
+
require 'cubic'
|
7
|
+
|
8
|
+
Cubic.application.load_app
|
9
|
+
|
10
|
+
module TestApp
|
11
|
+
class Application < Cubic::Application
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
Cubic.run do |construct|
|
2
|
+
|
3
|
+
construct.config do |config|
|
4
|
+
# Your configuration block will set the defaults for
|
5
|
+
# your application.These options are not set in stone,
|
6
|
+
# but this file is an easy way to get an overview
|
7
|
+
# of your app, so it is best to try and follow
|
8
|
+
# what you have specified here!
|
9
|
+
|
10
|
+
# Below are the default options when generating your application.
|
11
|
+
#
|
12
|
+
# Your root_path will set the directory you wish
|
13
|
+
# your application generated within.
|
14
|
+
config.root_path = Dir.getwd
|
15
|
+
|
16
|
+
# As of now, only Sequel and ActiveRecord are the only ORMs supported.
|
17
|
+
config.orm = 'Sequel'
|
18
|
+
|
19
|
+
# Select your prefered database.
|
20
|
+
config.db = 'sqlite3'
|
21
|
+
|
22
|
+
# Choose your templating engine.
|
23
|
+
config.html_type = 'haml'
|
24
|
+
config.css_type = 'css'
|
25
|
+
|
26
|
+
# Add gems you will require
|
27
|
+
config.gems = []
|
28
|
+
end
|
29
|
+
|
30
|
+
construct.models do |model|
|
31
|
+
# Create -or 'design'- your models within this block.
|
32
|
+
# model.design(:user, {some: 'structure'}).add('has_secure_password')
|
33
|
+
end
|
34
|
+
|
35
|
+
construct.controllers do |c|
|
36
|
+
# List your controllers to be generated.
|
37
|
+
c.design(:home).routes(:index)
|
38
|
+
c.design(:user).routes(:new)
|
39
|
+
c.design(:sessions)
|
40
|
+
c.design(:static)
|
41
|
+
end
|
42
|
+
end
|