cubic 0.1.0

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