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.
@@ -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,8 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %link{ :rel => "stylesheet", :href => "/stylesheets/application.css" }
5
+ %script{ :src => "/javascripts/application.js" }
6
+ %title test
7
+ %body
8
+ = yield
@@ -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,4 @@
1
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
2
+
3
+ require 'bundler/setup'
4
+ Bundler.require(ENV['BUNDLE_GEMFILE'])
@@ -0,0 +1,7 @@
1
+ require File.expand_path('../config/application', __FILE__)
2
+ pathh = File.join(APP_PATH, 'public')
3
+
4
+ # Default middleware
5
+ use Cubic::Static, url: ['/stylesheets', '/javascripts'], root: pathh
6
+
7
+ run Cubic.application
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby.exe
2
+ require 'cubic'
3
+ require_relative '../config/boot.rb'
4
+
5
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
6
+ Cubic::Options.new(ARGV).run
@@ -0,0 +1,2 @@
1
+ require 'sequel'
2
+ DB = Sequel.connect('sqlite://application.db')
@@ -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