cubic 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|