sinator 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +46 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +33 -0
- data/LICENSE.txt +22 -0
- data/README.md +126 -0
- data/bin/sinator +5 -0
- data/lib/sinator/command.rb +61 -0
- data/lib/sinator/generator.rb +106 -0
- data/lib/sinator/templates/Gemfile.erb +15 -0
- data/lib/sinator/templates/Rakefile.erb +33 -0
- data/lib/sinator/templates/app/routes/home.erb +6 -0
- data/lib/sinator/templates/app/views/home/index.erb +1 -0
- data/lib/sinator/templates/app/views/layout.erb +21 -0
- data/lib/sinator/templates/app.erb +71 -0
- data/lib/sinator/templates/assets/javascripts/app.js +2 -0
- data/lib/sinator/templates/assets/javascripts/main.js +1 -0
- data/lib/sinator/templates/assets/javascripts/plugins.js +24 -0
- data/lib/sinator/templates/assets/stylesheets/app.css.scss +1 -0
- data/lib/sinator/templates/assets/stylesheets/main.css.scss +8 -0
- data/lib/sinator/templates/config/application.rb +7 -0
- data/lib/sinator/templates/config/boot.rb +10 -0
- data/lib/sinator/templates/config/database.yml +8 -0
- data/lib/sinator/templates/config/puma/development.erb +7 -0
- data/lib/sinator/templates/config/puma/production.erb +16 -0
- data/lib/sinator/templates/config.ru.erb +5 -0
- data/lib/sinator/templates/db/migrations/000_example.rb +12 -0
- data/lib/sinator/templates/public/404.html +60 -0
- data/lib/sinator/templates/public/apple-touch-icon.png +0 -0
- data/lib/sinator/templates/public/browserconfig.xml +12 -0
- data/lib/sinator/templates/public/crossdomain.xml +15 -0
- data/lib/sinator/templates/public/favicon.ico +0 -0
- data/lib/sinator/templates/public/humans.txt +15 -0
- data/lib/sinator/templates/public/robots.txt +5 -0
- data/lib/sinator/templates/public/tile-wide.png +0 -0
- data/lib/sinator/templates/public/tile.png +0 -0
- data/lib/sinator/version.rb +3 -0
- data/lib/sinator.rb +1 -0
- data/sinator.gemspec +19 -0
- data/spec/fixtures/app_routes_home.txt +6 -0
- data/spec/fixtures/config/puma/development.txt +7 -0
- data/spec/fixtures/config/puma/production.txt +16 -0
- data/spec/fixtures/config_ru.txt +5 -0
- data/spec/fixtures/with_db/app.txt +50 -0
- data/spec/fixtures/with_db/gemfile.txt +13 -0
- data/spec/fixtures/with_db/rakefile.txt +32 -0
- data/spec/fixtures/without_db/app.txt +31 -0
- data/spec/fixtures/without_db/gemfile.txt +11 -0
- data/spec/fixtures/without_db/rakefile.txt +15 -0
- data/spec/helpers/generator.rb +46 -0
- data/spec/sinator/command_spec.rb +70 -0
- data/spec/sinator/generator_spec.rb +184 -0
- data/spec/sinator_spec.rb +1 -0
- data/spec/spec_helper.rb +29 -0
- metadata +128 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
environment 'production'
|
2
|
+
bind 'unix:///path/to/shared/tmp/sockets/puma.sock'
|
3
|
+
pidfile '/path/to/shared/tmp/pids/puma.pid'
|
4
|
+
ctl_socket = '/path/to/shared/tmp/sockets/pumactl.sock'
|
5
|
+
state_path '/path/to/shared/tmp/sockets/puma.state'
|
6
|
+
activate_control_app 'unix:///path/to/shared/tmp/sockets/pumactl.sock'
|
7
|
+
daemonize
|
8
|
+
quiet
|
9
|
+
|
10
|
+
threads 5, 5
|
11
|
+
workers 2
|
12
|
+
preload_app!
|
13
|
+
|
14
|
+
before_fork do
|
15
|
+
<%= @app_class_name %>::DB.disconnect if defined?(<%= @app_class_name %>::DB)
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# http://sequel.jeremyevans.net/rdoc/files/doc/migration_rdoc.html
|
2
|
+
|
3
|
+
# Sequel.migration do
|
4
|
+
# up do
|
5
|
+
# add_column :artists, :location, String
|
6
|
+
# from(:artists).update(:location=>'Sacramento')
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# down do
|
10
|
+
# drop_column :artists, :location
|
11
|
+
# end
|
12
|
+
# end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<title>Page Not Found</title>
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7
|
+
<style>
|
8
|
+
|
9
|
+
* {
|
10
|
+
line-height: 1.2;
|
11
|
+
margin: 0;
|
12
|
+
}
|
13
|
+
|
14
|
+
html {
|
15
|
+
color: #888;
|
16
|
+
display: table;
|
17
|
+
font-family: sans-serif;
|
18
|
+
height: 100%;
|
19
|
+
text-align: center;
|
20
|
+
width: 100%;
|
21
|
+
}
|
22
|
+
|
23
|
+
body {
|
24
|
+
display: table-cell;
|
25
|
+
vertical-align: middle;
|
26
|
+
margin: 2em auto;
|
27
|
+
}
|
28
|
+
|
29
|
+
h1 {
|
30
|
+
color: #555;
|
31
|
+
font-size: 2em;
|
32
|
+
font-weight: 400;
|
33
|
+
}
|
34
|
+
|
35
|
+
p {
|
36
|
+
margin: 0 auto;
|
37
|
+
width: 280px;
|
38
|
+
}
|
39
|
+
|
40
|
+
@media only screen and (max-width: 280px) {
|
41
|
+
|
42
|
+
body, p {
|
43
|
+
width: 95%;
|
44
|
+
}
|
45
|
+
|
46
|
+
h1 {
|
47
|
+
font-size: 1.5em;
|
48
|
+
margin: 0 0 0.3em;
|
49
|
+
}
|
50
|
+
|
51
|
+
}
|
52
|
+
|
53
|
+
</style>
|
54
|
+
</head>
|
55
|
+
<body>
|
56
|
+
<h1>Page Not Found</h1>
|
57
|
+
<p>Sorry, but the page you were trying to view does not exist.</p>
|
58
|
+
</body>
|
59
|
+
</html>
|
60
|
+
<!-- IE needs 512+ bytes: http://blogs.msdn.com/b/ieinternals/archive/2010/08/19/http-error-pages-in-internet-explorer.aspx -->
|
Binary file
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<!-- Please read: http://msdn.microsoft.com/en-us/library/ie/dn455106.aspx -->
|
3
|
+
<browserconfig>
|
4
|
+
<msapplication>
|
5
|
+
<tile>
|
6
|
+
<square70x70logo src="tile.png"/>
|
7
|
+
<square150x150logo src="tile.png"/>
|
8
|
+
<wide310x150logo src="tile-wide.png"/>
|
9
|
+
<square310x310logo src="tile.png"/>
|
10
|
+
</tile>
|
11
|
+
</msapplication>
|
12
|
+
</browserconfig>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
|
3
|
+
<cross-domain-policy>
|
4
|
+
<!-- Read this: www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html -->
|
5
|
+
|
6
|
+
<!-- Most restrictive policy: -->
|
7
|
+
<site-control permitted-cross-domain-policies="none"/>
|
8
|
+
|
9
|
+
<!-- Least restrictive policy: -->
|
10
|
+
<!--
|
11
|
+
<site-control permitted-cross-domain-policies="all"/>
|
12
|
+
<allow-access-from domain="*" to-ports="*" secure="false"/>
|
13
|
+
<allow-http-request-headers-from domain="*" headers="*" secure="false"/>
|
14
|
+
-->
|
15
|
+
</cross-domain-policy>
|
Binary file
|
Binary file
|
Binary file
|
data/lib/sinator.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# :)
|
data/sinator.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'lib/sinator/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'sinator'
|
5
|
+
s.version = Sinator::VERSION
|
6
|
+
s.date = Date.today.to_s
|
7
|
+
s.summary = "Sinatra application boilerplate generator"
|
8
|
+
s.description = "Sinator provides generator and contains minimal configuration to develop application with Sinatra"
|
9
|
+
s.author = 'Kunto Aji Kristianto'
|
10
|
+
s.email = 'kuntoaji@kaklabs.com'
|
11
|
+
s.files = `git ls-files -z`.split("\x0")
|
12
|
+
s.executables << 'sinator'
|
13
|
+
s.homepage = 'http://github.com/kuntoaji/sinator'
|
14
|
+
s.license = 'MIT'
|
15
|
+
|
16
|
+
s.required_ruby_version = '>= 2.1'
|
17
|
+
s.add_development_dependency 'bundler', '~> 1.7'
|
18
|
+
s.add_development_dependency 'rspec', '3.2.0'
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
environment 'production'
|
2
|
+
bind 'unix:///path/to/shared/tmp/sockets/puma.sock'
|
3
|
+
pidfile '/path/to/shared/tmp/pids/puma.pid'
|
4
|
+
ctl_socket = '/path/to/shared/tmp/sockets/pumactl.sock'
|
5
|
+
state_path '/path/to/shared/tmp/sockets/puma.state'
|
6
|
+
activate_control_app 'unix:///path/to/shared/tmp/sockets/pumactl.sock'
|
7
|
+
daemonize
|
8
|
+
quiet
|
9
|
+
|
10
|
+
threads 5, 5
|
11
|
+
workers 2
|
12
|
+
preload_app!
|
13
|
+
|
14
|
+
before_fork do
|
15
|
+
MyApp::DB.disconnect if defined?(MyApp::DB)
|
16
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
class MyApp < Sinatra::Application
|
4
|
+
use Rack::Session::EncryptedCookie,
|
5
|
+
secret: 'supersecretcookiefromgenerator'
|
6
|
+
|
7
|
+
set :app_file, __FILE__
|
8
|
+
set :server, :puma
|
9
|
+
set :views, Proc.new { File.join(root, "app/views") }
|
10
|
+
set :assets, Sprockets::Environment.new
|
11
|
+
set :assets_manifest, %w(app.js app.css)
|
12
|
+
use Rack::Csrf, raise: true
|
13
|
+
|
14
|
+
configure do
|
15
|
+
Sequel::Database.extension :pagination
|
16
|
+
Sequel::Model.plugin :timestamps
|
17
|
+
Sequel::Model.plugin :auto_validations,
|
18
|
+
not_null: :presence, unique_opts: { only_if_modified: true }
|
19
|
+
|
20
|
+
assets.append_path 'assets/stylesheets'
|
21
|
+
assets.append_path 'assets/javascripts'
|
22
|
+
end
|
23
|
+
|
24
|
+
configure :development do
|
25
|
+
require 'sinatra/reloader'
|
26
|
+
require 'logger'
|
27
|
+
|
28
|
+
register Sinatra::Reloader
|
29
|
+
Sequel.connect YAML.load_file(File.expand_path("../config/database.yml", __FILE__))['development'],
|
30
|
+
loggers: [Logger.new($stdout)]
|
31
|
+
|
32
|
+
get '/assets/*' do
|
33
|
+
env['PATH_INFO'].sub!('/assets', '')
|
34
|
+
settings.assets.call(env)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
configure :test do
|
39
|
+
Sequel.connect YAML.load_file(File.expand_path("../config/database.yml", __FILE__))['test']
|
40
|
+
end
|
41
|
+
|
42
|
+
configure :production do
|
43
|
+
# Serve assets via Nginx or Apache
|
44
|
+
disable :static
|
45
|
+
|
46
|
+
assets.js_compressor = :uglify
|
47
|
+
assets.css_compressor = :sass
|
48
|
+
Sequel.connect YAML.load_file(File.expand_path("../config/database.yml", __FILE__))['production']
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'sinatra', '2.0.0'
|
4
|
+
gem 'sinatra-contrib', '2.0.0', require: false
|
5
|
+
gem 'encrypted_cookie', '0.0.5'
|
6
|
+
gem 'rack_csrf', '2.6.0', require: 'rack/csrf'
|
7
|
+
gem 'puma', '3.11.0'
|
8
|
+
gem 'tux', '0.3.0', require: false
|
9
|
+
gem 'uglifier', '4.1.3', require: false
|
10
|
+
gem 'sass', '3.5.5', require: false
|
11
|
+
gem 'sprockets', '3.7.1'
|
12
|
+
gem 'sequel', '5.4.0'
|
13
|
+
gem 'sequel_pg', '1.8.1', require: 'sequel'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative 'config/boot'
|
2
|
+
require_relative 'my_app'
|
3
|
+
|
4
|
+
namespace :assets do
|
5
|
+
desc "Precompile assets"
|
6
|
+
task :precompile do
|
7
|
+
manifest = ::Sprockets::Manifest.new(MyApp.assets.index, "#{MyApp.public_folder}/assets")
|
8
|
+
manifest.compile(MyApp.assets_manifest)
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Clean assets"
|
12
|
+
task :clean do
|
13
|
+
FileUtils.rm_rf("#{MyApp.public_folder}/assets")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
namespace :db do
|
18
|
+
desc "Run migrations"
|
19
|
+
task :migrate, [:version] do |t, args|
|
20
|
+
Sequel.extension :migration
|
21
|
+
db = Sequel.connect(YAML.load_file("#{Sinator::ROOT}/config/database.yml")[ENV['APP_ENV']])
|
22
|
+
migration_path = "#{Sinator::ROOT}/db/migrations"
|
23
|
+
|
24
|
+
if args[:version]
|
25
|
+
puts "Migrating to version #{args[:version]}"
|
26
|
+
Sequel::Migrator.run(db, migration_path, target: args[:version].to_i)
|
27
|
+
else
|
28
|
+
puts "Migrating to latest"
|
29
|
+
Sequel::Migrator.run(db, migration_path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class MyApp < Sinatra::Application
|
2
|
+
use Rack::Session::EncryptedCookie,
|
3
|
+
secret: 'supersecretcookiefromgenerator'
|
4
|
+
|
5
|
+
set :app_file, __FILE__
|
6
|
+
set :server, :puma
|
7
|
+
set :views, Proc.new { File.join(root, "app/views") }
|
8
|
+
set :assets, Sprockets::Environment.new
|
9
|
+
set :assets_manifest, %w(app.js app.css)
|
10
|
+
use Rack::Csrf, raise: true
|
11
|
+
|
12
|
+
configure do
|
13
|
+
assets.append_path 'assets/stylesheets'
|
14
|
+
assets.append_path 'assets/javascripts'
|
15
|
+
end
|
16
|
+
|
17
|
+
configure :development do
|
18
|
+
get '/assets/*' do
|
19
|
+
env['PATH_INFO'].sub!('/assets', '')
|
20
|
+
settings.assets.call(env)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
configure :production do
|
25
|
+
# Serve assets via Nginx or Apache
|
26
|
+
disable :static
|
27
|
+
|
28
|
+
assets.js_compressor = :uglify
|
29
|
+
assets.css_compressor = :sass
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'sinatra', '2.0.0'
|
4
|
+
gem 'sinatra-contrib', '2.0.0', require: false
|
5
|
+
gem 'encrypted_cookie', '0.0.5'
|
6
|
+
gem 'rack_csrf', '2.6.0', require: 'rack/csrf'
|
7
|
+
gem 'puma', '3.11.0'
|
8
|
+
gem 'tux', '0.3.0', require: false
|
9
|
+
gem 'uglifier', '4.1.3', require: false
|
10
|
+
gem 'sass', '3.5.5', require: false
|
11
|
+
gem 'sprockets', '3.7.1'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'config/boot'
|
2
|
+
require_relative 'my_app'
|
3
|
+
|
4
|
+
namespace :assets do
|
5
|
+
desc "Precompile assets"
|
6
|
+
task :precompile do
|
7
|
+
manifest = ::Sprockets::Manifest.new(MyApp.assets.index, "#{MyApp.public_folder}/assets")
|
8
|
+
manifest.compile(MyApp.assets_manifest)
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Clean assets"
|
12
|
+
task :clean do
|
13
|
+
FileUtils.rm_rf("#{MyApp.public_folder}/assets")
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Helper
|
2
|
+
module Generator
|
3
|
+
def expect_file_eq(file, expected_file)
|
4
|
+
file_content = File.read(file)
|
5
|
+
expected_file_content = File.read(expected_file)
|
6
|
+
|
7
|
+
expect(File.exists?(file)).to be_truthy
|
8
|
+
expect(file_content).to eq(expected_file_content)
|
9
|
+
end
|
10
|
+
|
11
|
+
def expected_default_files(target_dir, expected_value)
|
12
|
+
config_dir = "#{target_dir}/config"
|
13
|
+
assets_dir = "#{target_dir}/assets"
|
14
|
+
public_dir = "#{target_dir}/public"
|
15
|
+
boot = "#{config_dir}/boot.rb"
|
16
|
+
application = "#{config_dir}/application.rb"
|
17
|
+
|
18
|
+
app_dir = "#{target_dir}/app"
|
19
|
+
routes_dir = "#{target_dir}/app/routes"
|
20
|
+
views_dir = "#{target_dir}/app/views"
|
21
|
+
layout = "#{target_dir}/app/views/layout.erb"
|
22
|
+
home_index = "#{target_dir}/app/views/home/index.erb"
|
23
|
+
|
24
|
+
expect(File.exists?(config_dir)).to eq(expected_value)
|
25
|
+
expect(File.exists?("#{config_dir}/boot.rb")).to eq(expected_value)
|
26
|
+
expect(File.exists?("#{config_dir}/application.rb")).to eq(expected_value)
|
27
|
+
expect(File.exists?(assets_dir)).to eq(expected_value)
|
28
|
+
expect(File.exists?(public_dir)).to eq(expected_value)
|
29
|
+
|
30
|
+
expect(Dir.exists?(app_dir)).to eq(expected_value)
|
31
|
+
expect(Dir.exists?(routes_dir)).to eq(expected_value)
|
32
|
+
expect(Dir.exists?(views_dir)).to eq(expected_value)
|
33
|
+
expect(File.exists?(layout)).to eq(expected_value)
|
34
|
+
expect(File.exists?(home_index)).to eq(expected_value)
|
35
|
+
end
|
36
|
+
|
37
|
+
def expected_generated_files_with_db(target_dir, expected_value)
|
38
|
+
sample_migration = "#{target_dir}/db/migrations/000_example.rb"
|
39
|
+
|
40
|
+
expect(Dir.exists?("#{target_dir}/app/models")).to eq(expected_value)
|
41
|
+
expect(File.exists?("#{target_dir}/config/database.yml")).to eq(expected_value)
|
42
|
+
expect(File.exists?(sample_migration)).to eq(expected_value)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require_relative '../../lib/sinator/command'
|
2
|
+
|
3
|
+
describe Sinator::Command do
|
4
|
+
|
5
|
+
describe "parse" do
|
6
|
+
def remove_existing_app_if_exists
|
7
|
+
FileUtils.rm_r "my_app" if Dir.exists?("my_app")
|
8
|
+
FileUtils.rm_r "/tmp/my_app" if Dir.exists?("/tmp/my_app")
|
9
|
+
end
|
10
|
+
|
11
|
+
before do
|
12
|
+
remove_existing_app_if_exists
|
13
|
+
end
|
14
|
+
|
15
|
+
after :all do
|
16
|
+
remove_existing_app_if_exists
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has --help option" do
|
20
|
+
help = Sinator::Command.parse %w(--help)
|
21
|
+
|
22
|
+
expect(help).to include "Usage: sinator [options]"
|
23
|
+
expect(help).to include "Print this help"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "has --version option" do
|
27
|
+
version = Sinator::Command.parse %w(--version)
|
28
|
+
|
29
|
+
expect(version).to include Sinator::VERSION
|
30
|
+
end
|
31
|
+
|
32
|
+
it "has --name option as required option to generate application" do
|
33
|
+
app = Sinator::Command.parse %w(--name my_app)
|
34
|
+
|
35
|
+
expect(app).to include "my_app is successfully generated"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "has --target option as target directory" do
|
39
|
+
app = Sinator::Command.parse %w(-n my_app --target /tmp)
|
40
|
+
|
41
|
+
expect(app).to include "my_app is successfully generated in /tmp"
|
42
|
+
expect(Dir.exists?("/tmp/my_app")).to be_truthy
|
43
|
+
end
|
44
|
+
|
45
|
+
it "has --database option" do
|
46
|
+
app = Sinator::Command.parse %w(-n my_app --target /tmp -d)
|
47
|
+
|
48
|
+
expect(app).to include "my_app is successfully generated in /tmp"
|
49
|
+
expect(Dir.exists?("/tmp/my_app/db")).to be_truthy
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when has no --name option and only --target option" do
|
53
|
+
it "does nothing" do
|
54
|
+
app = Sinator::Command.parse %w(--target /tmp/sinator)
|
55
|
+
|
56
|
+
expect(app).to be_nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when has no option" do
|
61
|
+
it "uses --help option by default" do
|
62
|
+
help = Sinator::Command.parse []
|
63
|
+
|
64
|
+
expect(help).to include "Usage: sinator [options]"
|
65
|
+
expect(help).to include "Print this help"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|