tobi 1.0.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.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/
5
+ vendor/
6
+ Sample/
7
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ # Specify your gem's dependencies in tobi.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,6 @@
1
+ guard 'rspec', cli: '-c', all_after_pass: false, all_on_start: false do
2
+ watch(%r{spec/.+_spec\.rb$})
3
+ watch(%r{^lib/tobi/(.+)\.rb$}) {|m| "spec/#{m[1]}_spec.rb"}
4
+ watch(%r{^lib/tobi\.rb}) { "spec" }
5
+ end
6
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 masaxsny
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # Tobi
2
+
3
+ Simple sinatra application generator.
4
+
5
+ ## Installation
6
+
7
+ $ gem install tobi
8
+
9
+ ## Usage
10
+
11
+ $ tobi --help
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/tobi ADDED
@@ -0,0 +1,66 @@
1
+ #! /usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'tobi'
4
+ require 'optparse'
5
+
6
+ opt = OptionParser.new
7
+ options = {}
8
+
9
+ msg = <<MSG
10
+ Tobi is a simple sinatra application generator.
11
+
12
+ Usage:
13
+ tobi [options] APP_NAME
14
+
15
+ View templates which can be specified:
16
+ #{Tobi::enum_in_sentence(Tobi::OPT_VALUES[:ViewTemplate])}
17
+ CSS templates which can be specified:
18
+ #{Tobi::enum_in_sentence(Tobi::OPT_VALUES[:CssTemplate])}
19
+ Test frameworks which can be specified:
20
+ #{Tobi::enum_in_sentence(Tobi::OPT_VALUES[:TestFramework])}
21
+
22
+ Options:
23
+ MSG
24
+ opt.banner = msg
25
+
26
+ opt.on('-m', 'Application is generated in a modular style.') do |modular_style|
27
+ options[:ModularStyle] = modular_style
28
+ end
29
+
30
+ opt.on('-r', 'Rackup file is generated.') do |rackup|
31
+ options[:Rackup] = rackup
32
+ end
33
+
34
+ opt.on('-v TEMPLATE', 'View template is specified. (default haml)') do |template|
35
+ options[:ViewTemplate] = template
36
+ end
37
+
38
+ opt.on('-c TEMPLATE', 'CSS template is specified. (default scss)') do |template|
39
+ options[:CssTemplate] = template
40
+ end
41
+
42
+ opt.on('-t TEST_FRAMEWORK', 'Test framework is specified.') do |test_framework|
43
+ options[:TestFramework] = test_framework
44
+ end
45
+
46
+ opt.on('--version', 'Display current version.') do
47
+ puts "tobi #{Tobi::VERSION}"
48
+ exit(0)
49
+ end
50
+
51
+ begin
52
+ opt.parse!
53
+ rescue => e
54
+ puts e.message
55
+ exit(0)
56
+ end
57
+
58
+ if ARGV.length == 0
59
+ puts 'Application name is not specified.'
60
+ exit(0)
61
+ end
62
+
63
+ cfg = Tobi::Config.new(ARGV[0], options)
64
+ gen = Tobi::Generator.new(cfg)
65
+ gen.generate
66
+
@@ -0,0 +1,69 @@
1
+ # coding: utf-8
2
+
3
+ module Tobi
4
+ # アプリケーション設定情報の保持と設定値のチェック
5
+ class Config
6
+ # アプリケーション名(String)
7
+ attr_reader :app_name
8
+ # 各種設定(Hash)
9
+ attr_reader :options
10
+
11
+ # アプリケーション設定情報の作成とチェックを行う。
12
+ #
13
+ # app_name - アプリケーション名(Stirng)
14
+ # opts - 各種設定(Hash)
15
+ def initialize(app_name, opts = {})
16
+ @app_name = app_name
17
+ @options = merge_options(opts)
18
+ check
19
+ end
20
+
21
+ private
22
+
23
+ # 各種設定情報のデフォルト値と指定値をマージする。
24
+ #
25
+ # opts - 指定値(Hash)
26
+ #
27
+ # 戻り値: マージされた各種設定情報(Hash)
28
+ def merge_options(opts)
29
+ DEFAULT_OPTS.merge(opts)
30
+ end
31
+
32
+ # アプリケーション設定情報の値が正しいかチェックする。
33
+ #
34
+ # 戻り値: なし
35
+ def check
36
+ check_app_name(@app_name)
37
+ @options.each {|k, v| check_opt_value(k, v)}
38
+ end
39
+
40
+ # アプリケーション名が不正であればプログラムを終了する。
41
+ #
42
+ # アプリケーション名(String)
43
+ #
44
+ # 戻り値: なし
45
+ def check_app_name(str)
46
+ unless /^[a-zA-Z]+/ =~ str
47
+ msg = "Application name `#{str}` is invalid."
48
+ msg << 'The heading charactar should specify the alphabet.'
49
+ puts msg
50
+ exit(0)
51
+ end
52
+ end
53
+
54
+ # 各種設定の値が不正であればプログラムを終了する。
55
+ #
56
+ # key - 設定キー
57
+ # value - 設定値
58
+ #
59
+ # 戻り値: なし
60
+ def check_opt_value(key, value)
61
+ return unless value
62
+ unless OPT_VALUES[key].include?(value)
63
+ puts "The Value `#{value}` set as the key `#{key}` is invalid."
64
+ exit(0)
65
+ end
66
+ end
67
+ end
68
+ end
69
+
@@ -0,0 +1,180 @@
1
+ # coding: utf-8
2
+ require 'erb'
3
+
4
+ module Tobi
5
+ # アプリケーション設定情報からアプリケーションのソースコードを生成する。
6
+ class Generator
7
+ # アプリケーション名(String)
8
+ attr_reader :app_name
9
+ # 各種設定情報(Hash)
10
+ attr_reader :config
11
+ # 埋め込みソースコード(Hash)
12
+ attr_reader :src
13
+
14
+ # アプリケーション設定情報の読み込みと、
15
+ # 埋め込みソースコードのデフォルト設定をする。
16
+ #
17
+ # cfg - アプリケーション設定情報(Tobi::Config)
18
+ def initialize(cfg)
19
+ @app_name = cfg.app_name
20
+ @app_path = File.join(Dir.pwd, @app_name)
21
+ @config = cfg.options
22
+ @src = DEFAULT_SRC.dup
23
+ end
24
+
25
+ # アプリケーションのソースコードを生成する。
26
+ #
27
+ # 戻り値: なし
28
+ def generate
29
+ set_source_code
30
+ begin
31
+ output_app_files
32
+ rescue => e
33
+ msg = "ファイルの出力に失敗しました。: #{e.message}"
34
+ STDERR.puts msg
35
+ exit(1)
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ # 埋め込みソースコードを設定する。
42
+ #
43
+ # 戻り値: なし
44
+ def set_source_code
45
+ # app.rb
46
+ @src[:base_require] = @config[:ModularStyle] ? 'sinatra/base' : 'sinatra'
47
+ @src[:app_run] = if @config[:Rackup]
48
+ nil
49
+ else
50
+ "#{@app_name.capitalize}::App.run! if $0 == __FILE__"
51
+ end
52
+
53
+ # config.ru
54
+ if @config[:Rackup]
55
+ @src[:cnf_run] = if @config[:ModularStyle]
56
+ "run #{@app_name.capitalize}::App"
57
+ else
58
+ 'run Sinatra::Application'
59
+ end
60
+ end
61
+
62
+ # ビューテンプレート関連
63
+ vt = @config[:ViewTemplate]
64
+ @src[:view_template_require] = "require '#{vt}'"
65
+ @src[:view_template] = vt
66
+ @src[:gems] << vt unless vt == 'erb'
67
+ if %w(liquid radius).include?(vt)
68
+ @src[:locals] = ", locals: { app_name: '#{@app_name}', ua: @ua }"
69
+ end
70
+
71
+ # CSSテンプレート関連
72
+ ct = @config[:CssTemplate]
73
+ if ct == 'scss'
74
+ @src[:css_template_require] = "require 'sass'"
75
+ @src[:gems] << 'sass'
76
+ else
77
+ @src[:css_template_require] = "require '#{ct}'"
78
+ @src[:gems] << ct
79
+ end
80
+ @src[:css_template] = ct
81
+ @src[:gems] << 'therubyracer' if ct == "less"
82
+
83
+ # テストフレームワーク関連
84
+ if @config[:TestFramework]
85
+ tf = @config[:TestFramework]
86
+ @src[:test_framework] = tf
87
+ @src[:gems] << tf if tf != 'testunit'
88
+ @src[:test_run] = if @config[:ModularStyle]
89
+ "#{@app_name.capitalize}::App"
90
+ else
91
+ 'Sinatra::Application'
92
+ end
93
+ end
94
+ end
95
+
96
+ # アプリケーションのファイルを出力する。
97
+ #
98
+ # 戻り値: なし
99
+ def output_app_files
100
+ # アプリケーションのルートディレクトリ
101
+ Dir.mkdir(@app_path) unless File.exists?(@app_path)
102
+
103
+ # app.rb
104
+ buf = read_template_file(@config[:ModularStyle] ? "mod_app.rb" : "app.rb")
105
+ write_file(buf, "app.rb")
106
+
107
+ # views/index.*
108
+ dir = "views"
109
+ ext = @config[:ViewTemplate] == "markaby" ? "mab" : @config[:ViewTemplate]
110
+ fn = "index.#{ext}"
111
+ mkdir_and_output(dir, fn)
112
+
113
+ # views/style.*
114
+ dir = "views"
115
+ fn = "style.#{@config[:CssTemplate]}"
116
+ mkdir_and_output(dir, fn)
117
+
118
+ # Gemfile
119
+ unless @src[:gems].empty?
120
+ buf = read_template_file("Gemfile")
121
+ write_file(buf, "Gemfile")
122
+ end
123
+
124
+ # config.ru
125
+ if @config[:Rackup]
126
+ buf = read_template_file("config.ru")
127
+ write_file(buf, "config.ru")
128
+ end
129
+
130
+ # app_test.rb, app_spec.rb
131
+ if @src[:test_framework] == "testunit"
132
+ dir = "test"
133
+ fn = "app_test.rb"
134
+ mkdir_and_output(dir, fn)
135
+ elsif @src[:test_framework] == "rspec"
136
+ dir = "spec"
137
+ fn = "app_spec.rb"
138
+ mkdir_and_output(dir, fn)
139
+ end
140
+ end
141
+
142
+ # ディレクトリの生成とファイル入出力
143
+ #
144
+ # d - ディレクトリ
145
+ # f - ファイル名
146
+ #
147
+ # 戻り値: なし
148
+ def mkdir_and_output(d, f)
149
+ unless File.exists?(File.join("#{@app_path}", "#{d}"))
150
+ Dir.mkdir(File.join("#{@app_path}", "#{d}"))
151
+ end
152
+ buf = read_template_file(File.join("#{d}", "#{f}"))
153
+ write_file(buf, File.join("#{d}", "#{f}"))
154
+ end
155
+
156
+ # テンプレートerbファイルを読み込み、結果を返す。
157
+ #
158
+ # fname - erbファイルパス
159
+ #
160
+ # 戻り値: 指定されたerbファイルの変換結果
161
+ def read_template_file(fname)
162
+ fpath = File.join(File.dirname(__FILE__), 'templates', "#{fname}")
163
+ erb = ERB.new(File.read(fpath), nil, '-')
164
+ erb.result(binding)
165
+ end
166
+
167
+ # 指定したデータを指定されたファイルへ出力する。
168
+ #
169
+ # data - データ
170
+ # fname - 出力ファイルパス
171
+ #
172
+ # 戻り値: なし
173
+ def write_file(data, fname)
174
+ File.open(File.join("#{@app_path}", "#{fname}"), "w") do |f|
175
+ f.write(data)
176
+ end
177
+ end
178
+ end
179
+ end
180
+
@@ -0,0 +1,13 @@
1
+ source :rubygems
2
+
3
+ gem 'sinatra'
4
+ <%- @src[:gems].each do |g| -%>
5
+ <%= "gem '#{g}'" %>
6
+ <%- end -%>
7
+
8
+ <%- if @src[:test_framework] -%>
9
+ <%= "group :test do" %>
10
+ <%= " gem 'rack-test'" %>
11
+ <%= "end" %>
12
+ <%- end -%>
13
+
@@ -0,0 +1,15 @@
1
+ require "<%= @src[:base_require] %>"
2
+ <%= @src[:view_template_require] %>
3
+ <%= @src[:css_template_require] %>
4
+
5
+ get '/' do
6
+ @ua = request.user_agent
7
+ <%= @src[:view_template] %> :index<%= @src[:locals] %>
8
+ end
9
+
10
+ <% if @src[:css_template] -%>
11
+ get '*.css' do |path|
12
+ <%= @src[:css_template] %> path.to_sym
13
+ end
14
+ <% end %>
15
+
@@ -0,0 +1,4 @@
1
+ require "./app.rb"
2
+
3
+ <%= @src[:cnf_run] %>
4
+
@@ -0,0 +1,21 @@
1
+ require "<%= @src[:base_require] %>"
2
+ <%= @src[:view_template_require] %>
3
+ <%= @src[:css_template_require] %>
4
+
5
+ module <%= @app_name.capitalize %>
6
+ class App < Sinatra::Base
7
+ get '/' do
8
+ @ua = request.user_agent
9
+ <%= @src[:view_template] %> :index<%= @src[:locals] %>
10
+ end
11
+ <% if @src[:css_template] %>
12
+ get '*.css' do |path|
13
+ <%= @src[:css_template] %> path.to_sym
14
+ end
15
+ <% end %>
16
+ end
17
+ end
18
+
19
+ <% if @src[:app_run] -%>
20
+ <%= @src[:app_run] %>
21
+ <% end -%>
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + "/../")
2
+ require "app.rb"
3
+ require "rack/test"
4
+
5
+ describe "App" do
6
+ include Rack::Test::Methods
7
+
8
+ def app
9
+ <%= @src[:test_run] %>
10
+ end
11
+
12
+ describe "last_response.body" do
13
+ before { get '/' }
14
+ subject { last_response.body }
15
+ it { should match /<h1>Hello!<\/h1>/ }
16
+ end
17
+ end
18
+
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + "/../")
2
+ require "app.rb"
3
+ require "test/unit"
4
+ require "rack/test"
5
+
6
+ class MyAppTest < Test::Unit::TestCase
7
+ include Rack::Test::Methods
8
+
9
+ def app
10
+ <%= @src[:test_run] %>
11
+ end
12
+
13
+ def test_root
14
+ get '/'
15
+ assert_match /<h1>Hello!<\/h1>/, last_response.body
16
+ end
17
+ end
18
+
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+ <link rel="stylesheet" href="style.css" type="text/css" />
6
+ <title><%= @app_name %></title>
7
+ </head>
8
+ <body>
9
+ <h1>Hello!</h1>
10
+ <p><%%= @ua %></p>
11
+ </body>
12
+ </html>
13
+
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+ <link rel="stylesheet" href="style.css" type="text/css" />
6
+ <title><%= @app_name %></title>
7
+ </head>
8
+ <body>
9
+ <h1>Hello!</h1>
10
+ <p><%%= @ua %></p>
11
+ </body>
12
+ </html>
13
+
@@ -0,0 +1,10 @@
1
+ !!! XML
2
+ !!!
3
+ %html
4
+ %head
5
+ %link{rel: "stylesheet", href: "style.css", type: "text/css"}
6
+ %title <%= @app_name %>
7
+ %body
8
+ %h1 Hello!
9
+ %p= @ua
10
+
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+ <link rel="stylesheet" href="style.css" type="text/css" />
6
+ <title>{{ :app_name }}</title>
7
+ </head>
8
+ <body>
9
+ <h1>Hello!</h1>
10
+ <p>{{ :ua }}</p>
11
+ </body>
12
+ </html>
13
+
@@ -0,0 +1,11 @@
1
+ xhtml_strict do
2
+ head do
3
+ link(rel: "stylesheet", href: "style.css", type: "text/css")
4
+ title "<%= @app_name %>"
5
+ end
6
+ body do
7
+ h1 "Hello!"
8
+ p @ua
9
+ end
10
+ end
11
+
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+ <link rel="stylesheet" href="style.css" type="text/css" />
6
+ <title><r:app_name /></title>
7
+ </head>
8
+ <body>
9
+ <h1>Hello!</h1>
10
+ <p><r:ua /></p>
11
+ </body>
12
+ </html>
13
+
@@ -0,0 +1,10 @@
1
+ doctype transitional
2
+ html
3
+ head
4
+ meta http-equiv="Content-Type" content="text/html; charset=utf-8"
5
+ link rel="stylesheet" href="style.css" type="text/css"
6
+ title <%= @app_name %>
7
+ body
8
+ h1 Hello!
9
+ p = @ua
10
+
@@ -0,0 +1,8 @@
1
+ h1 {
2
+ color: #5a5
3
+ }
4
+
5
+ p {
6
+ color: #aaa
7
+ }
8
+
@@ -0,0 +1,6 @@
1
+ h1
2
+ color: #5a5
3
+
4
+ p
5
+ color: #aaa
6
+
@@ -0,0 +1,8 @@
1
+ h1 {
2
+ color: #5a5
3
+ }
4
+
5
+ p {
6
+ color: #aaa
7
+ }
8
+
@@ -0,0 +1,3 @@
1
+ module Tobi
2
+ VERSION = "1.0.0"
3
+ end
data/lib/tobi.rb ADDED
@@ -0,0 +1,45 @@
1
+ require 'tobi/version'
2
+ require 'tobi/config'
3
+ require 'tobi/generator'
4
+
5
+ module Tobi
6
+ # オプションのデフォルト値
7
+ DEFAULT_OPTS = { ModularStyle: false,
8
+ Rackup: false,
9
+ ViewTemplate: 'haml',
10
+ CssTemplate: 'scss',
11
+ TestFramework: nil }
12
+
13
+ # オプションのとるべき値
14
+ OPT_VALUES = { ModularStyle: [false, true],
15
+ Rackup: [false, true],
16
+ ViewTemplate: %w(haml erb erubis liquid radius markaby slim),
17
+ CssTemplate: %w(sass scss less),
18
+ TestFramework: %w(testunit rspec) }
19
+
20
+ # ソースコード情報のデフォルト値
21
+ DEFAULT_SRC = { gems: [],
22
+ rackup_run: nil,
23
+ app_run: nil,
24
+ locals: nil }
25
+
26
+ # 配列の値を英文の列挙表現にして返す。
27
+ #
28
+ # enum - 配列(Array)
29
+ #
30
+ # 戻り値: 列挙表現(String)
31
+ def self.enum_in_sentence(enum)
32
+ str = ''
33
+ len = enum.length
34
+ enum.each_with_index do |v, i|
35
+ if i > 0
36
+ link = i == len - 1 ? ' and ' : ', '
37
+ str << "#{link}#{v.to_s}"
38
+ else
39
+ str << v.to_s
40
+ end
41
+ end
42
+ return str
43
+ end
44
+ end
45
+
@@ -0,0 +1,44 @@
1
+ # coding: utf-8
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'tobi'
4
+
5
+ shared_examples_for 'invalid value' do |key|
6
+ before { cfg.instance_eval('@options')[key] = 'xxxx' }
7
+ context 'プログラムは終了すること' do
8
+ it { lambda { cfg.instance_eval('check') }.should raise_error(SystemExit) }
9
+ end
10
+ end
11
+
12
+ describe Tobi::Config do
13
+ context 'オプション指定なしのとき' do
14
+ cfg = Tobi::Config.new('Sample')
15
+ describe 'options' do
16
+ context 'はデフォルト値である' do
17
+ it { cfg.options.should eq Tobi::DEFAULT_OPTS }
18
+ end
19
+ end
20
+ end
21
+
22
+ context 'オプション指定ありのとき' do
23
+ opt = { ModularStyle: true,
24
+ Rackup: false,
25
+ ViewTemplate: 'slim',
26
+ CssTemplate: 'sass',
27
+ TestFramework: 'rspec' }
28
+ cfg = Tobi::Config.new('Sample', opt)
29
+ describe 'options' do
30
+ context 'は指定された値である' do
31
+ it { cfg.options.should eq opt }
32
+ end
33
+ end
34
+ end
35
+
36
+ context '不正な値が指定されたとき' do
37
+ before { STDOUT.stub(:puts).and_return(nil) }
38
+ let(:cfg){ Tobi::Config.new('Sample') }
39
+ Tobi::DEFAULT_OPTS.each do |k, v|
40
+ it_behaves_like 'invalid value', k
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,223 @@
1
+ # coding: utf-8
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'tobi'
4
+
5
+ APP_NAME = 'Sample'
6
+
7
+ shared_examples_for 'view template' do |v|
8
+ cfg = Tobi::Config.new(APP_NAME, {ViewTemplate: v})
9
+ let(:gen){ Tobi::Generator.new(cfg) }
10
+
11
+ before do
12
+ gen.instance_eval('@src[:gems]').clear
13
+ gen.generate
14
+ end
15
+
16
+ describe 'src[:view_template_require]' do
17
+ context "は`require '#{v}'`であること" do
18
+ it { gen.src[:view_template_require].should eq "require '#{v}'" }
19
+ end
20
+ end
21
+
22
+ describe 'src[:view_template]' do
23
+ context "は`#{v}`であること" do
24
+ it { gen.src[:view_template].should eq v }
25
+ end
26
+ end
27
+
28
+ if v == 'erb'
29
+ describe 'src[:gems]' do
30
+ context "は`#{v}`が含まれていないこと" do
31
+ it { gen.src[:gems].should_not include v }
32
+ end
33
+ end
34
+ else
35
+ describe 'src[:gems]' do
36
+ context "は`#{v}`が含まれていること" do
37
+ it { gen.src[:gems].should include v }
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ shared_examples_for 'css template' do |v|
44
+ cfg = Tobi::Config.new(APP_NAME, {CssTemplate: v})
45
+ let(:gen){ Tobi::Generator.new(cfg) }
46
+ before do
47
+ gen.instance_eval('@src[:gems]').clear
48
+ gen.generate
49
+ end
50
+
51
+ describe 'src[:css_template_require]' do
52
+ if v == 'scss'
53
+ context "は`require 'sass'`であること" do
54
+ it { gen.src[:css_template_require].should eq "require 'sass'" }
55
+ end
56
+ else
57
+ context "は`require '#{v}'`であること" do
58
+ it { gen.src[:css_template_require].should eq "require '#{v}'" }
59
+ end
60
+ end
61
+ end
62
+
63
+ describe 'src[:css_template]' do
64
+ context "は`#{v}`であること" do
65
+ it { gen.src[:css_template].should eq v }
66
+ end
67
+ end
68
+
69
+ describe 'src[:gems]' do
70
+ if v == 'scss'
71
+ context "は`sass`が含まれていること" do
72
+ it { gen.src[:gems].should include 'sass' }
73
+ end
74
+ else
75
+ context "は#{v}が含まれていること" do
76
+ it { gen.src[:gems].should include v }
77
+ if v == 'less'
78
+ context "は'therubyracer'が含まれていること" do
79
+ it { gen.src[:gems].should include 'therubyracer' }
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ shared_examples_for 'test framework' do |v, m|
88
+ cfg = Tobi::Config.new(APP_NAME, {TestFramework: v, ModularStyle: m})
89
+ let(:gen){ Tobi::Generator.new(cfg) }
90
+ before do
91
+ gen.instance_eval('@src[:gems]').clear
92
+ gen.generate
93
+ end
94
+
95
+ describe 'src[:test_framework]' do
96
+ context "は`#{v}`であること" do
97
+ it { gen.src[:test_framework].should eq v }
98
+ end
99
+ end
100
+
101
+ describe 'src[:gems]' do
102
+ if v != 'testunit'
103
+ context "は#{v}が含まれていること" do
104
+ it { gen.src[:gems].should include v }
105
+ end
106
+ end
107
+ end
108
+
109
+ describe 'src[:test_run]' do
110
+ if m
111
+ context "は`#{APP_NAME}::App`であること" do
112
+ it { gen.src[:test_run].should eq "#{gen.app_name}::App" }
113
+ end
114
+ else
115
+ context 'は`Sinatra::Application`であること' do
116
+ it { gen.src[:test_run].should eq 'Sinatra::Application' }
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ describe Tobi::Generator do
123
+ context 'ModularStyleがfalseのとき' do
124
+ cfg = Tobi::Config.new(APP_NAME, {ModularStyle: false})
125
+ let(:gen){ Tobi::Generator.new(cfg) }
126
+ before { gen.generate }
127
+
128
+ describe 'src[:base_require]' do
129
+ context 'は`sinatra`であること' do
130
+ it { gen.src[:base_require].should eq 'sinatra' }
131
+ end
132
+ end
133
+ end
134
+
135
+ context 'ModularStyleがtrueのとき' do
136
+ cfg = Tobi::Config.new(APP_NAME, {ModularStyle: true})
137
+ let(:gen){ Tobi::Generator.new(cfg) }
138
+ before { gen.generate }
139
+
140
+ describe 'src[:base_require]' do
141
+ context 'は`sinatra/base`であること' do
142
+ it { gen.src[:base_require].should eq 'sinatra/base' }
143
+ end
144
+ end
145
+ end
146
+
147
+ context 'Rackupがfalseのとき' do
148
+ cfg = Tobi::Config.new(APP_NAME, {Rackup: false})
149
+ let(:gen){ Tobi::Generator.new(cfg) }
150
+ before { gen.generate }
151
+
152
+ describe 'src[:cnf_run]' do
153
+ context 'は`nil`であること' do
154
+ it { gen.src[:cnf_run].should eq nil }
155
+ end
156
+ end
157
+
158
+ describe 'src[:app_run]' do
159
+ context "は`???::App.run! if $0 == __FILE__`であること" do
160
+ it { gen.src[:app_run].should eq "#{gen.app_name}::App.run! if $0 == __FILE__" }
161
+ end
162
+ end
163
+ end
164
+
165
+ context 'Rackupがtrue' do
166
+ context 'かつModularStyleがfalseのとき' do
167
+ cfg = Tobi::Config.new(APP_NAME, {Rackup: true, ModularStyle: false})
168
+ let(:gen){ Tobi::Generator.new(cfg) }
169
+ before { gen.generate }
170
+
171
+ describe 'src[:cnf_run]' do
172
+ context 'は`run Sinatra::Application`であること' do
173
+ it { gen.src[:cnf_run].should eq 'run Sinatra::Application' }
174
+ end
175
+ end
176
+
177
+ describe 'src[:app_run]' do
178
+ context "は`nil`であること" do
179
+ it { gen.src[:app_run].should eq nil }
180
+ end
181
+ end
182
+ end
183
+
184
+ context 'かつModularStyleがtrueのとき' do
185
+ cfg = Tobi::Config.new(APP_NAME, {Rackup: true, ModularStyle: true})
186
+ let(:gen){ Tobi::Generator.new(cfg) }
187
+ before { gen.generate }
188
+
189
+ describe 'src[:cnf_run]' do
190
+ context 'は`run ???::App`であること' do
191
+ it { gen.src[:cnf_run].should eq "run #{gen.app_name}::App" }
192
+ end
193
+ end
194
+
195
+ describe 'src[:app_run]' do
196
+ context "は`nil`であること" do
197
+ it { gen.src[:app_run].should eq nil }
198
+ end
199
+ end
200
+ end
201
+ end
202
+
203
+ Tobi::OPT_VALUES[:ViewTemplate].each do |v|
204
+ context "ViewTemplateが#{v}のとき" do
205
+ it_behaves_like 'view template', v
206
+ end
207
+ end
208
+
209
+ Tobi::OPT_VALUES[:CssTemplate].each do |v|
210
+ context "CssTemplateが#{v}のとき" do
211
+ it_behaves_like 'css template', v
212
+ end
213
+ end
214
+
215
+ Tobi::OPT_VALUES[:TestFramework].each do |v|
216
+ context "TestFrameworkが#{v}のとき" do
217
+ [true, false].each do |modular_style|
218
+ it_behaves_like 'test framework', v, modular_style
219
+ end
220
+ end
221
+ end
222
+ end
223
+
data/tobi.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tobi/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "tobi"
8
+ gem.version = Tobi::VERSION
9
+ gem.authors = ["masaxsny"]
10
+ gem.email = ["masaxsny@gmail.com"]
11
+ gem.description = %q{Simple sinatra application generator.}
12
+ gem.summary = %q{Simple sinatra application generator.}
13
+ gem.homepage = "https://github.com/masaxsny/tobi"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_development_dependency "rspec"
21
+ gem.add_development_dependency "guard"
22
+ gem.add_development_dependency "guard-rspec"
23
+ gem.add_development_dependency "rb-fsevent"
24
+ # gem.add_runtime_dependency "***"
25
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tobi
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - masaxsny
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: guard
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard-rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rb-fsevent
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: Simple sinatra application generator.
79
+ email:
80
+ - masaxsny@gmail.com
81
+ executables:
82
+ - tobi
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitignore
87
+ - Gemfile
88
+ - Guardfile
89
+ - LICENSE.txt
90
+ - README.md
91
+ - Rakefile
92
+ - bin/tobi
93
+ - lib/tobi.rb
94
+ - lib/tobi/config.rb
95
+ - lib/tobi/generator.rb
96
+ - lib/tobi/templates/Gemfile
97
+ - lib/tobi/templates/app.rb
98
+ - lib/tobi/templates/config.ru
99
+ - lib/tobi/templates/mod_app.rb
100
+ - lib/tobi/templates/spec/app_spec.rb
101
+ - lib/tobi/templates/test/app_test.rb
102
+ - lib/tobi/templates/views/index.erb
103
+ - lib/tobi/templates/views/index.erubis
104
+ - lib/tobi/templates/views/index.haml
105
+ - lib/tobi/templates/views/index.liquid
106
+ - lib/tobi/templates/views/index.mab
107
+ - lib/tobi/templates/views/index.radius
108
+ - lib/tobi/templates/views/index.slim
109
+ - lib/tobi/templates/views/style.less
110
+ - lib/tobi/templates/views/style.sass
111
+ - lib/tobi/templates/views/style.scss
112
+ - lib/tobi/version.rb
113
+ - spec/config_spec.rb
114
+ - spec/generator_spec.rb
115
+ - tobi.gemspec
116
+ homepage: https://github.com/masaxsny/tobi
117
+ licenses: []
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 1.8.23
137
+ signing_key:
138
+ specification_version: 3
139
+ summary: Simple sinatra application generator.
140
+ test_files:
141
+ - spec/config_spec.rb
142
+ - spec/generator_spec.rb