melodiest 0.2.1 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/Gemfile.lock +19 -25
- data/README.md +63 -30
- data/lib/melodiest/command.rb +14 -8
- data/lib/melodiest/generator.rb +42 -9
- data/lib/melodiest/setting.rb +11 -3
- data/lib/melodiest/templates/Rakefile +21 -0
- data/lib/melodiest/templates/config/database.yml.example +8 -0
- data/lib/melodiest/templates/db/migrations/000_example.rb +12 -0
- data/lib/melodiest/version.rb +1 -1
- data/lib/melodiest.rb +3 -4
- data/melodiest.gemspec +5 -5
- data/spec/melodiest/command_spec.rb +23 -6
- data/spec/melodiest/generator_spec.rb +131 -21
- data/spec/melodiest/setting_spec.rb +22 -2
- data/spec/melodiest_spec.rb +0 -10
- data/spec/spec_helper.rb +5 -8
- metadata +16 -28
- data/lib/melodiest/auth/http.rb +0 -19
- data/lib/melodiest/config.yml +0 -1
- data/spec/melodiest/auth/http_spec.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fcb354a2aa73158378af93b4f18bf9d397f6b0da
|
4
|
+
data.tar.gz: b29f697ff27ba0ea4095382e41177bd47354b942
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 951a2c2a88bcbcd9432fa667ac753a98663f88a19805a98564746e9d78bb7752f4f21065e64acb7d4ad6ad4811a1ae9abe57a65e67de5a40adabe707a63a3469
|
7
|
+
data.tar.gz: 5560623ecda83e4834900fffabf61960a3e8ca08a879cb339a39181c571b320857ec6706cc07cde608f72b52c2bf6df95ffbd41a97657f1af847441a189e5e1f
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
0.3.0:
|
2
|
+
|
3
|
+
* remove Melodiest::Auth::Http module, it's better to use sinatra-authorization extension
|
4
|
+
* refactor Melodiest::Setting.setup so that it can be overridden via app and remove thin as dependency
|
5
|
+
* add generator for sequel orm and postgres sql
|
6
|
+
* use encrypted cookie
|
7
|
+
* add generator for Rack::Csrf
|
8
|
+
|
9
|
+
0.2.x:
|
10
|
+
|
11
|
+
* add sinatra application boilerplate generator
|
12
|
+
* add melodiest command to run generator
|
13
|
+
|
14
|
+
0.1.x:
|
15
|
+
|
16
|
+
* add http authorization module
|
17
|
+
* set thin as server
|
data/Gemfile.lock
CHANGED
@@ -2,40 +2,39 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
melodiest (0.2.1)
|
5
|
-
|
5
|
+
encrypted_cookie (= 0.0.4)
|
6
|
+
sinatra (= 1.4.6)
|
6
7
|
sinatra-contrib (= 1.4.2)
|
7
|
-
thin (= 1.6.3)
|
8
8
|
|
9
9
|
GEM
|
10
10
|
remote: https://rubygems.org/
|
11
11
|
specs:
|
12
12
|
backports (3.6.4)
|
13
|
-
daemons (1.1.9)
|
14
13
|
diff-lcs (1.2.5)
|
15
|
-
|
16
|
-
|
17
|
-
multi_json (1.10.1)
|
14
|
+
encrypted_cookie (0.0.4)
|
15
|
+
multi_json (1.11.0)
|
18
16
|
rack (1.6.0)
|
19
17
|
rack-protection (1.5.3)
|
20
18
|
rack
|
21
19
|
rack-test (0.6.3)
|
22
20
|
rack (>= 1.0)
|
23
|
-
rspec (3.
|
24
|
-
rspec-core (~> 3.
|
25
|
-
rspec-expectations (~> 3.
|
26
|
-
rspec-mocks (~> 3.
|
27
|
-
rspec-core (3.
|
28
|
-
rspec-support (~> 3.
|
29
|
-
rspec-expectations (3.1
|
21
|
+
rspec (3.2.0)
|
22
|
+
rspec-core (~> 3.2.0)
|
23
|
+
rspec-expectations (~> 3.2.0)
|
24
|
+
rspec-mocks (~> 3.2.0)
|
25
|
+
rspec-core (3.2.3)
|
26
|
+
rspec-support (~> 3.2.0)
|
27
|
+
rspec-expectations (3.2.1)
|
30
28
|
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
-
rspec-support (~> 3.
|
32
|
-
rspec-mocks (3.1
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
rspec-support (~> 3.2.0)
|
30
|
+
rspec-mocks (3.2.1)
|
31
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
32
|
+
rspec-support (~> 3.2.0)
|
33
|
+
rspec-support (3.2.2)
|
34
|
+
sinatra (1.4.6)
|
36
35
|
rack (~> 1.4)
|
37
36
|
rack-protection (~> 1.4)
|
38
|
-
tilt (
|
37
|
+
tilt (>= 1.3, < 3)
|
39
38
|
sinatra-contrib (1.4.2)
|
40
39
|
backports (>= 2.0)
|
41
40
|
multi_json
|
@@ -43,10 +42,6 @@ GEM
|
|
43
42
|
rack-test
|
44
43
|
sinatra (~> 1.4.0)
|
45
44
|
tilt (~> 1.3)
|
46
|
-
thin (1.6.3)
|
47
|
-
daemons (~> 1.0, >= 1.0.9)
|
48
|
-
eventmachine (~> 1.0)
|
49
|
-
rack (~> 1.0)
|
50
45
|
tilt (1.4.1)
|
51
46
|
|
52
47
|
PLATFORMS
|
@@ -54,7 +49,6 @@ PLATFORMS
|
|
54
49
|
|
55
50
|
DEPENDENCIES
|
56
51
|
bundler (~> 1.7)
|
57
|
-
fakefs (= 0.6.7)
|
58
52
|
melodiest!
|
59
53
|
rack-test (= 0.6.3)
|
60
|
-
rspec (= 3.
|
54
|
+
rspec (= 3.2.0)
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Melodiest
|
2
2
|
|
3
|
-
Melodiest is [Sinatra](http://www.sinatrarb.com/) application boilerplate. It provides generator and
|
3
|
+
Melodiest is [Sinatra](http://www.sinatrarb.com/) application boilerplate. It provides generator and contains minimalist configuration to develop application with Sinatra.
|
4
4
|
|
5
5
|
### Installation
|
6
6
|
|
@@ -16,17 +16,20 @@ gem 'melodiest'
|
|
16
16
|
```
|
17
17
|
|
18
18
|
### How to Use
|
19
|
-
|
20
|
-
generate app in current directory
|
19
|
+
generate app in current directory without database
|
21
20
|
```
|
22
21
|
melodiest -n my_app
|
23
22
|
```
|
24
|
-
generate app in target directory
|
23
|
+
generate app in target directory without database
|
25
24
|
```
|
26
|
-
melodiest -n my_app -
|
25
|
+
melodiest -n my_app -t target/dir
|
26
|
+
```
|
27
|
+
generate app in current directory with database. `-d` option will generate app with `Sequel` orm and PostgreSQL adapter.
|
28
|
+
```
|
29
|
+
melodiest -n my_app -d
|
27
30
|
```
|
28
31
|
|
29
|
-
|
32
|
+
### Melodiest::Application
|
30
33
|
Because Melodiest is already required Sinatra, you don't have to require 'sinatra' anymore, just require 'melodiest'.
|
31
34
|
|
32
35
|
`Melodiest::Application` is subclass from `Sinatra::Application` and by default is using configuration from `Melodiest::Setting.setup` method.
|
@@ -35,41 +38,71 @@ Because Melodiest is already required Sinatra, you don't have to require 'sinatr
|
|
35
38
|
```ruby
|
36
39
|
# my_app.rb
|
37
40
|
|
38
|
-
require 'melodiest/auth/http'
|
39
|
-
|
40
41
|
class App < Melodiest::Application
|
41
|
-
|
42
|
-
|
42
|
+
setup 'this_is_secret_for_encrypted_cookie'
|
43
|
+
...
|
44
|
+
end
|
45
|
+
```
|
46
|
+
### Example Usage
|
47
|
+
This example assume that PostgreSQL is already running and .
|
48
|
+
1. run `melodiest -n my_app -d`
|
49
|
+
2. cd `my_app`
|
50
|
+
3. run `bundle install`
|
51
|
+
4. create `config/database.yml` and configure your database setting
|
52
|
+
5. create file `db/migrations/001_create_artists.rb` and put the following code:
|
53
|
+
```ruby
|
54
|
+
Sequel.migration do
|
55
|
+
up do
|
56
|
+
create_table(:artists) do
|
57
|
+
primary_key :id
|
58
|
+
String :name, :null=>false
|
59
|
+
end
|
43
60
|
end
|
44
61
|
|
45
|
-
|
62
|
+
down do
|
63
|
+
drop_table(:artists)
|
64
|
+
end
|
46
65
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
66
|
+
```
|
67
|
+
6. run `rake db:migrate`
|
68
|
+
7. create file `app/models/Artist.rb` and put the following code:
|
69
|
+
```ruby
|
70
|
+
class Artist < Sequel::Model
|
52
71
|
end
|
72
|
+
```
|
73
|
+
8. create file `app/routes/artists.rb` and put the following code:
|
74
|
+
```ruby
|
75
|
+
class MyApp
|
76
|
+
get '/' do
|
77
|
+
"hello world!"
|
78
|
+
end
|
53
79
|
|
54
|
-
get
|
55
|
-
|
56
|
-
|
80
|
+
get '/artists' do
|
81
|
+
# for example purpose :)
|
82
|
+
artist = Artist.new
|
83
|
+
artist.name = 'Melody'
|
84
|
+
artist.save
|
85
|
+
|
86
|
+
@artists = Artist.all
|
87
|
+
erb :"artists/index"
|
88
|
+
end
|
57
89
|
end
|
58
|
-
|
59
|
-
```
|
60
|
-
#### Run the server
|
61
90
|
```
|
62
|
-
|
91
|
+
9. create file `app/views/artists/index.erb` and put the following code:
|
92
|
+
```erb
|
93
|
+
<h1>List of Artist</h1>
|
94
|
+
<% @artists.each do |artist| %>
|
95
|
+
<li><%= artist.name %></li>
|
96
|
+
<% end %>
|
63
97
|
```
|
98
|
+
10. run the server `bundle exec rackup`
|
99
|
+
11. open url `localhost:9292/artists`
|
64
100
|
|
65
101
|
|
66
102
|
### Default Configuration
|
67
103
|
|
68
104
|
* `Sinatra::Reloader` in development environment only
|
69
|
-
*
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
Available modules from Melodiest
|
74
|
-
|
75
|
-
* `Melodiest::Auth::Http`
|
105
|
+
* `Rack::Session::EncryptedCookie`
|
106
|
+
* `Rack::Csrf`
|
107
|
+
* `Sequel` ORM
|
108
|
+
* `sequel_pg` as PostgreSQL adapter
|
data/lib/melodiest/command.rb
CHANGED
@@ -5,7 +5,7 @@ module Melodiest
|
|
5
5
|
|
6
6
|
class Command
|
7
7
|
def self.parse(options)
|
8
|
-
args = {
|
8
|
+
args = {}
|
9
9
|
result = ""
|
10
10
|
|
11
11
|
option_parser = OptionParser.new do |opts|
|
@@ -23,28 +23,34 @@ module Melodiest
|
|
23
23
|
args[:name] = name
|
24
24
|
end
|
25
25
|
|
26
|
-
opts.on("-
|
27
|
-
args[:
|
26
|
+
opts.on("-tDIR", "--target=DIR", "instead of current directory, generate app in target DIR") do |target|
|
27
|
+
args[:target] = target
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on("-d", "--database", "add sequel orm for postgres sql") do
|
31
|
+
args[:database] = true
|
28
32
|
end
|
29
33
|
|
30
34
|
end
|
31
35
|
|
32
36
|
option_parser.parse! options
|
33
37
|
|
34
|
-
result =
|
38
|
+
result = run(args) unless args[:name].nil?
|
35
39
|
|
36
40
|
result
|
37
41
|
end
|
38
42
|
|
39
|
-
def self.run(
|
40
|
-
generator = Melodiest::Generator.new
|
43
|
+
def self.run(args)
|
44
|
+
generator = Melodiest::Generator.new args[:name],
|
45
|
+
destination: args[:target], with_database: args[:database]
|
41
46
|
|
42
47
|
generator.generate_gemfile
|
43
48
|
generator.generate_bundle_config
|
44
49
|
generator.generate_app
|
50
|
+
generator.copy_templates
|
45
51
|
|
46
|
-
msg = "#{
|
47
|
-
msg << " in #{
|
52
|
+
msg = "#{args[:name]} is successfully generated"
|
53
|
+
msg << " in #{args[:target]}" if args[:target]
|
48
54
|
|
49
55
|
msg
|
50
56
|
end
|
data/lib/melodiest/generator.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'securerandom'
|
2
3
|
require_relative 'version'
|
3
4
|
|
4
5
|
module Melodiest
|
@@ -6,10 +7,12 @@ module Melodiest
|
|
6
7
|
class Generator
|
7
8
|
attr_accessor :destination, :app_name, :app_class_name
|
8
9
|
|
9
|
-
def initialize(app_name,
|
10
|
+
def initialize(app_name, options={})
|
10
11
|
@app_name = app_name
|
11
12
|
@app_class_name = app_name.split("_").map{|s| s.capitalize }.join("")
|
12
|
-
|
13
|
+
|
14
|
+
destination = options[:destination] ? "#{options[:destination]}/#{@app_name}" : @app_name
|
15
|
+
@with_database = options[:with_database]
|
13
16
|
|
14
17
|
unless File.directory?(destination)
|
15
18
|
FileUtils.mkdir_p(destination)
|
@@ -21,7 +24,14 @@ module Melodiest
|
|
21
24
|
def generate_gemfile
|
22
25
|
File.open "#{@destination}/Gemfile", "w" do |f|
|
23
26
|
f.write("source 'https://rubygems.org'\n\n")
|
24
|
-
f.write("gem 'melodiest', '#{Melodiest::VERSION}'")
|
27
|
+
f.write("gem 'melodiest', '#{Melodiest::VERSION}'\n")
|
28
|
+
f.write("gem 'thin'\n")
|
29
|
+
f.write("gem 'rack_csrf', require: 'rack/csrf'")
|
30
|
+
|
31
|
+
if @with_database
|
32
|
+
f.write("\ngem 'sequel'\n")
|
33
|
+
f.write("gem 'sequel_pg', require: 'sequel'")
|
34
|
+
end
|
25
35
|
end
|
26
36
|
end
|
27
37
|
|
@@ -38,25 +48,48 @@ module Melodiest
|
|
38
48
|
|
39
49
|
# https://github.com/sinatra/sinatra-book/blob/master/book/Organizing_your_application.markdown
|
40
50
|
def generate_app
|
51
|
+
content = {}
|
52
|
+
|
53
|
+
if @with_database
|
54
|
+
content[:yaml] = "require 'yaml'\n\n"
|
55
|
+
content[:database] = " Sequel.connect YAML.load_file(File.expand_path(\"../config/database.yml\", __FILE__))[settings.environment.to_s]\n"
|
56
|
+
else
|
57
|
+
content[:yaml] = nil
|
58
|
+
content[:database] = " # Load up database and such\n"
|
59
|
+
end
|
60
|
+
|
41
61
|
File.open "#{@destination}/#{@app_name}.rb", "w" do |f|
|
62
|
+
f.write(content[:yaml])
|
42
63
|
f.write("class #{app_class_name} < Melodiest::Application\n")
|
64
|
+
f.write(" setup '#{SecureRandom.hex(32)}'\n\n")
|
65
|
+
f.write(" set :app_file, __FILE__\n")
|
66
|
+
f.write(" set :views, Proc.new { File.join(root, \"app/views\") }\n\n")
|
67
|
+
f.write(" use Rack::Csrf, raise: true\n\n")
|
43
68
|
f.write(" configure do\n")
|
44
|
-
f.write(
|
69
|
+
f.write(content[:database])
|
45
70
|
f.write(" end\n")
|
46
71
|
f.write("end\n\n")
|
47
|
-
f.write("
|
48
|
-
f.write("Dir[File.
|
49
|
-
f.write("
|
72
|
+
f.write("%w{app/models app/routes}.each do |dir|\n")
|
73
|
+
f.write(" Dir[File.join(dir, '**/*.rb')].each do |file|\n")
|
74
|
+
f.write(" require_relative file\n")
|
75
|
+
f.write(" end\n")
|
50
76
|
f.write("end\n")
|
51
77
|
end
|
52
78
|
|
53
|
-
FileUtils.mkdir_p "#{@destination}/db/migrations"
|
54
|
-
|
55
79
|
app_dir = "#{@destination}/app"
|
56
80
|
["", "/routes", "/models", "/views"].each do |dir|
|
57
81
|
FileUtils.mkdir "#{app_dir}/#{dir}"
|
58
82
|
end
|
59
83
|
end
|
84
|
+
|
85
|
+
def copy_templates
|
86
|
+
FileUtils.cp_r File.expand_path("../templates/config", __FILE__), @destination
|
87
|
+
|
88
|
+
if @with_database
|
89
|
+
FileUtils.cp File.expand_path("../templates/Rakefile", __FILE__), @destination
|
90
|
+
FileUtils.cp_r File.expand_path("../templates/db", __FILE__), @destination
|
91
|
+
end
|
92
|
+
end
|
60
93
|
end
|
61
94
|
|
62
95
|
end
|
data/lib/melodiest/setting.rb
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
module Melodiest
|
2
2
|
module Setting
|
3
|
-
def setup
|
4
|
-
|
5
|
-
|
3
|
+
def setup(cookie_secret, options={})
|
4
|
+
settings = {
|
5
|
+
server: 'thin'
|
6
|
+
}.merge(options)
|
7
|
+
|
8
|
+
settings.each do |key, value|
|
9
|
+
set key, value
|
10
|
+
end
|
11
|
+
|
12
|
+
use Rack::Session::EncryptedCookie,
|
13
|
+
secret: cookie_secret
|
6
14
|
end
|
7
15
|
end
|
8
16
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
env = ENV['RACK_ENV'] || 'development'
|
5
|
+
|
6
|
+
namespace :db do
|
7
|
+
desc "Run migrations"
|
8
|
+
task :migrate, [:version] do |t, args|
|
9
|
+
Sequel.extension :migration
|
10
|
+
db = Sequel.connect(YAML.load_file(File.expand_path("../config/database.yml", __FILE__))[env])
|
11
|
+
migration_path = File.expand_path("../db/migrations", __FILE__)
|
12
|
+
|
13
|
+
if args[:version]
|
14
|
+
puts "Migrating to version #{args[:version]}"
|
15
|
+
Sequel::Migrator.run(db, migration_path, target: args[:version].to_i)
|
16
|
+
else
|
17
|
+
puts "Migrating to latest"
|
18
|
+
Sequel::Migrator.run(db, migration_path)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
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
|
data/lib/melodiest/version.rb
CHANGED
data/lib/melodiest.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
require 'sinatra'
|
2
|
-
require 'sinatra/config_file'
|
1
|
+
require 'sinatra/base'
|
3
2
|
require 'sinatra/reloader'
|
3
|
+
require 'encrypted_cookie'
|
4
4
|
require 'melodiest/setting'
|
5
5
|
|
6
6
|
module Melodiest
|
7
7
|
class Application < Sinatra::Application
|
8
|
-
|
9
|
-
setup
|
8
|
+
register Melodiest::Setting
|
10
9
|
|
11
10
|
# http://www.sinatrarb.com/contrib/reloader.html
|
12
11
|
configure :development do
|
data/melodiest.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |s|
|
|
5
5
|
s.version = Melodiest::VERSION
|
6
6
|
s.date = Date.today.to_s
|
7
7
|
s.summary = "Sinatra application boilerplate"
|
8
|
-
s.description = "Melodiest provides generator and
|
8
|
+
s.description = "Melodiest provides generator and contains minimalist configuration to develop application with Sinatra"
|
9
9
|
s.author = 'Kunto Aji Kristianto'
|
10
10
|
s.email = 'kunto.aji.kr@slackware-id.org'
|
11
11
|
s.files = `git ls-files -z`.split("\x0")
|
@@ -13,11 +13,11 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.homepage = 'http://github.com/kuntoaji/melodiest'
|
14
14
|
s.license = 'MIT'
|
15
15
|
|
16
|
+
s.required_ruby_version = '>= 2.1'
|
16
17
|
s.add_development_dependency 'bundler', '~> 1.7'
|
17
|
-
s.add_development_dependency 'rspec', '3.
|
18
|
+
s.add_development_dependency 'rspec', '3.2.0'
|
18
19
|
s.add_development_dependency 'rack-test', '0.6.3'
|
19
|
-
s.
|
20
|
-
s.add_runtime_dependency 'sinatra', '1.4.5'
|
20
|
+
s.add_runtime_dependency 'sinatra', '1.4.6'
|
21
21
|
s.add_runtime_dependency 'sinatra-contrib', '1.4.2'
|
22
|
-
s.add_runtime_dependency '
|
22
|
+
s.add_runtime_dependency 'encrypted_cookie', '0.0.4'
|
23
23
|
end
|
@@ -1,10 +1,18 @@
|
|
1
1
|
require_relative '../../lib/melodiest/command'
|
2
|
-
require 'fakefs/spec_helpers'
|
3
2
|
|
4
3
|
describe Melodiest::Command do
|
5
|
-
include FakeFS::SpecHelpers
|
6
4
|
|
7
5
|
describe "parse" do
|
6
|
+
before do
|
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
|
+
after :all do
|
12
|
+
FileUtils.rm_r "my_app" if Dir.exists?("my_app")
|
13
|
+
FileUtils.rm_r "/tmp/my_app" if Dir.exists?("/tmp/my_app")
|
14
|
+
end
|
15
|
+
|
8
16
|
it "has --help option" do
|
9
17
|
help = Melodiest::Command.parse %w(--help)
|
10
18
|
|
@@ -24,19 +32,28 @@ describe Melodiest::Command do
|
|
24
32
|
expect(app).to include "my_app is successfully generated"
|
25
33
|
end
|
26
34
|
|
27
|
-
it "has --
|
28
|
-
app = Melodiest::Command.parse %w(-n my_app --
|
35
|
+
it "has --target option as target directory" do
|
36
|
+
app = Melodiest::Command.parse %w(-n my_app --target /tmp)
|
29
37
|
|
30
38
|
expect(app).to include "my_app is successfully generated in /tmp"
|
31
39
|
expect(Dir.exists?("/tmp/my_app")).to be_truthy
|
32
40
|
end
|
33
41
|
|
34
|
-
|
42
|
+
it "has --database option" do
|
43
|
+
app = Melodiest::Command.parse %w(-n my_app --target /tmp -d)
|
44
|
+
|
45
|
+
puts `ls /tmp/my_app`
|
46
|
+
expect(app).to include "my_app is successfully generated in /tmp"
|
47
|
+
expect(Dir.exists?("/tmp/my_app/db")).to be_truthy
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when has no --name option and only --target option" do
|
35
51
|
it "does nothing" do
|
36
|
-
app = Melodiest::Command.parse %w(--
|
52
|
+
app = Melodiest::Command.parse %w(--target /tmp/melodiest)
|
37
53
|
|
38
54
|
expect(app).to be_empty
|
39
55
|
end
|
40
56
|
end
|
41
57
|
end
|
58
|
+
|
42
59
|
end
|
@@ -1,15 +1,29 @@
|
|
1
1
|
require_relative '../../lib/melodiest/generator'
|
2
|
-
require 'fakefs/spec_helpers'
|
3
2
|
|
4
3
|
describe Melodiest::Generator do
|
5
|
-
|
4
|
+
let(:generator) { Melodiest::Generator.new @app, destination: @dest }
|
5
|
+
let(:generator_with_db) { Melodiest::Generator.new @app, destination: @dest_with_db, with_database: true }
|
6
|
+
let(:target_dir) { "#{@dest}/#{@app}" }
|
7
|
+
let(:target_dir_with_db) { "#{@dest_with_db}/#{@app}" }
|
8
|
+
|
9
|
+
before :all do
|
10
|
+
@dest = "/tmp/melodiest"
|
11
|
+
@dest_with_db = "#{@dest}_with_db"
|
12
|
+
@app = "my_app"
|
13
|
+
end
|
6
14
|
|
7
|
-
|
8
|
-
|
9
|
-
|
15
|
+
before :all do
|
16
|
+
FileUtils.rm_r @dest if Dir.exists?(@dest)
|
17
|
+
FileUtils.rm_r @dest_with_db if Dir.exists?(@dest_with_db)
|
18
|
+
end
|
19
|
+
|
20
|
+
after :all do
|
21
|
+
FileUtils.rm_r @dest
|
22
|
+
FileUtils.rm_r @dest_with_db
|
23
|
+
end
|
10
24
|
|
11
25
|
it "sets app_name" do
|
12
|
-
expect(generator.app_name).to eq app
|
26
|
+
expect(generator.app_name).to eq @app
|
13
27
|
end
|
14
28
|
|
15
29
|
it "sets app_class_name" do
|
@@ -17,28 +31,45 @@ describe Melodiest::Generator do
|
|
17
31
|
end
|
18
32
|
|
19
33
|
it "has default destination path app_name" do
|
20
|
-
expect(Melodiest::Generator.new(app).destination).to eq File.expand_path(app)
|
34
|
+
expect(Melodiest::Generator.new(@app).destination).to eq File.expand_path(@app)
|
21
35
|
end
|
22
36
|
|
23
37
|
it "sets new destination path even if it's not exist yet" do
|
24
|
-
expect("/tmp/melodiest/my_app").to eq
|
38
|
+
expect("/tmp/melodiest/my_app").to eq target_dir
|
25
39
|
end
|
26
40
|
|
27
41
|
describe "#generate_gemfile" do
|
28
|
-
|
42
|
+
context "without database" do
|
43
|
+
let(:gemfile) { "#{target_dir}/Gemfile" }
|
44
|
+
|
45
|
+
it "should generate Gemfile without sequel" do
|
46
|
+
generator.generate_gemfile
|
47
|
+
file_content = File.read(gemfile)
|
48
|
+
|
49
|
+
expect(File.exists?(gemfile)).to be_truthy
|
50
|
+
expect(file_content).to include "source 'https://rubygems.org'"
|
51
|
+
expect(file_content).to include "gem 'melodiest', '#{Melodiest::VERSION}'"
|
52
|
+
expect(file_content).to include "gem 'thin'"
|
53
|
+
expect(file_content).to include "gem 'rack_csrf', require: 'rack/csrf'"
|
54
|
+
expect(file_content).to_not include "gem 'sequel'"
|
55
|
+
expect(file_content).to_not include "gem 'sequel_pg'"
|
56
|
+
end
|
57
|
+
end
|
29
58
|
|
30
|
-
|
31
|
-
|
32
|
-
file_content = File.read(gemfile)
|
59
|
+
context "with database" do
|
60
|
+
let(:gemfile) { "#{target_dir_with_db}/Gemfile" }
|
33
61
|
|
34
|
-
|
35
|
-
|
36
|
-
|
62
|
+
it "should generate Gemfile with sequel" do
|
63
|
+
generator_with_db.generate_gemfile
|
64
|
+
file_content = File.read(gemfile)
|
65
|
+
expect(file_content).to include "gem 'sequel'"
|
66
|
+
expect(file_content).to include "gem 'sequel_pg'"
|
67
|
+
end
|
37
68
|
end
|
38
69
|
end
|
39
70
|
|
40
71
|
describe "#generate_bundle_config" do
|
41
|
-
let(:bundle_config) { "#{
|
72
|
+
let(:bundle_config) { "#{target_dir}/config.ru" }
|
42
73
|
|
43
74
|
it "should generate config.ru with correct content" do
|
44
75
|
generator.generate_bundle_config
|
@@ -55,9 +86,11 @@ describe Melodiest::Generator do
|
|
55
86
|
end
|
56
87
|
|
57
88
|
describe "#generate_app" do
|
58
|
-
let(:
|
89
|
+
let(:secret) { "supersecretcookiefromgenerator" }
|
90
|
+
before { allow(SecureRandom).to receive(:hex).with(32).and_return(secret) }
|
59
91
|
|
60
92
|
it "generates <app_name>.rb" do
|
93
|
+
FileUtils.rm_r @dest if Dir.exists?(@dest)
|
61
94
|
generator.generate_app
|
62
95
|
app_file = "#{target_dir}/my_app.rb"
|
63
96
|
file_content = File.read(app_file)
|
@@ -65,25 +98,102 @@ describe Melodiest::Generator do
|
|
65
98
|
expected_file_content =
|
66
99
|
<<DOC
|
67
100
|
class MyApp < Melodiest::Application
|
101
|
+
setup '#{secret}'
|
102
|
+
|
103
|
+
set :app_file, __FILE__
|
104
|
+
set :views, Proc.new { File.join(root, "app/views") }
|
105
|
+
|
106
|
+
use Rack::Csrf, raise: true
|
107
|
+
|
68
108
|
configure do
|
69
109
|
# Load up database and such
|
70
110
|
end
|
71
111
|
end
|
72
112
|
|
73
|
-
|
74
|
-
Dir[File.
|
75
|
-
|
113
|
+
%w{app/models app/routes}.each do |dir|
|
114
|
+
Dir[File.join(dir, '**/*.rb')].each do |file|
|
115
|
+
require_relative file
|
116
|
+
end
|
76
117
|
end
|
77
118
|
DOC
|
78
119
|
|
79
120
|
expect(File.exists?(app_file)).to be_truthy
|
80
121
|
expect(file_content).to eq expected_file_content
|
81
|
-
expect(Dir.exists?("#{target_dir}/db/migrations")).to be_truthy
|
82
122
|
expect(Dir.exists?("#{target_dir}/app")).to be_truthy
|
83
123
|
expect(Dir.exists?("#{target_dir}/app/routes")).to be_truthy
|
84
124
|
expect(Dir.exists?("#{target_dir}/app/models")).to be_truthy
|
85
125
|
expect(Dir.exists?("#{target_dir}/app/views")).to be_truthy
|
86
126
|
end
|
127
|
+
|
128
|
+
context "with sequel" do
|
129
|
+
it "has sequel database connector" do
|
130
|
+
FileUtils.rm_r @dest_with_db if Dir.exists?(@dest_with_db)
|
131
|
+
generator_with_db.generate_app
|
132
|
+
app_file = "#{target_dir_with_db}/my_app.rb"
|
133
|
+
file_content = File.read(app_file)
|
134
|
+
|
135
|
+
expected_file_content =
|
136
|
+
<<DOC
|
137
|
+
require 'yaml'
|
138
|
+
|
139
|
+
class MyApp < Melodiest::Application
|
140
|
+
setup '#{secret}'
|
141
|
+
|
142
|
+
set :app_file, __FILE__
|
143
|
+
set :views, Proc.new { File.join(root, "app/views") }
|
144
|
+
|
145
|
+
use Rack::Csrf, raise: true
|
146
|
+
|
147
|
+
configure do
|
148
|
+
Sequel.connect YAML.load_file(File.expand_path("../config/database.yml", __FILE__))[settings.environment.to_s]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
%w{app/models app/routes}.each do |dir|
|
153
|
+
Dir[File.join(dir, '**/*.rb')].each do |file|
|
154
|
+
require_relative file
|
155
|
+
end
|
156
|
+
end
|
157
|
+
DOC
|
158
|
+
|
159
|
+
expect(file_content).to eq expected_file_content
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "#copy_templates" do
|
165
|
+
context "when generating without database" do
|
166
|
+
let(:config_dir) { "#{target_dir}/config" }
|
167
|
+
let(:without_db_rakefile) { "#{target_dir}/Rakefile" }
|
168
|
+
let(:without_db_sample_migration) { "#{target_dir}/db_migrations/000_example.rb" }
|
169
|
+
|
170
|
+
it "copies config dir" do
|
171
|
+
expect(File.exists?(config_dir)).to be_falsey
|
172
|
+
expect(File.exists?("#{config_dir}/database.yml.example")).to be_falsey
|
173
|
+
expect(File.exists?(without_db_rakefile)).to be_falsey
|
174
|
+
expect(File.exists?(without_db_sample_migration)).to be_falsey
|
175
|
+
generator.copy_templates
|
176
|
+
|
177
|
+
expect(File.exists?(config_dir)).to be_truthy
|
178
|
+
expect(File.exists?("#{config_dir}/database.yml.example")).to be_truthy
|
179
|
+
expect(File.exists?(without_db_rakefile)).to be_falsey
|
180
|
+
expect(File.exists?(without_db_sample_migration)).to be_falsey
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context "when generating with database" do
|
185
|
+
let(:with_db_rakefile) { "#{target_dir_with_db}/Rakefile" }
|
186
|
+
let(:with_db_sample_migration) { "#{target_dir_with_db}/db/migrations/000_example.rb" }
|
187
|
+
|
188
|
+
it "copies Rakefile" do
|
189
|
+
expect(File.exists?(with_db_rakefile)).to be_falsey
|
190
|
+
expect(File.exists?(with_db_sample_migration)).to be_falsey
|
191
|
+
generator_with_db.copy_templates
|
192
|
+
|
193
|
+
expect(File.exists?(with_db_rakefile)).to be_truthy
|
194
|
+
expect(File.exists?(with_db_sample_migration)).to be_truthy
|
195
|
+
end
|
196
|
+
end
|
87
197
|
end
|
88
198
|
|
89
199
|
end
|
@@ -1,5 +1,25 @@
|
|
1
1
|
describe Melodiest::Setting do
|
2
|
-
|
3
|
-
|
2
|
+
describe ".setup" do
|
3
|
+
let(:my_app) do
|
4
|
+
class MyApp < Melodiest::Application
|
5
|
+
setup 'mysupersecretcookie', server: 'puma'
|
6
|
+
end
|
7
|
+
|
8
|
+
MyApp
|
9
|
+
end
|
10
|
+
|
11
|
+
it "set thin as server" do
|
12
|
+
expect(app.settings.server).to eq("thin")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "overrides default setting" do
|
16
|
+
expect(my_app.settings.server).to eq("puma")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "use encrypted cookie" do
|
20
|
+
expect(my_app.instance_variable_get("@middleware")).to include
|
21
|
+
[Rack::Session::EncryptedCookie, [{:secret => "mysupersecretcookie"}], nil]
|
22
|
+
end
|
23
|
+
|
4
24
|
end
|
5
25
|
end
|
data/spec/melodiest_spec.rb
CHANGED
@@ -1,14 +1,4 @@
|
|
1
1
|
describe Melodiest::Application do
|
2
|
-
it "has config.yml" do
|
3
|
-
expect(File.exists?(File.expand_path('../../lib/melodiest/config.yml', __FILE__))).to be_truthy
|
4
|
-
end
|
5
|
-
|
6
|
-
context ".settings" do
|
7
|
-
it "use thin as server" do
|
8
|
-
expect(Melodiest::Application.settings.server).to eq("thin")
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
2
|
context ".extensions" do
|
13
3
|
it "has reloader extension" do
|
14
4
|
expect(app.extensions.include?(Sinatra::Reloader)).to be_truthy
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
ENV['RACK_ENV'] = 'test'
|
2
2
|
require 'rack/test'
|
3
3
|
require_relative '../lib/melodiest'
|
4
|
-
require_relative '../lib/melodiest/auth/http'
|
5
4
|
|
6
5
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
6
|
RSpec.configure do |config|
|
@@ -79,14 +78,12 @@ RSpec.configure do |config|
|
|
79
78
|
end
|
80
79
|
end
|
81
80
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
Melodiest::Application.get "/protected" do
|
86
|
-
authorized!
|
87
|
-
end
|
81
|
+
class SpecApp < Melodiest::Application
|
82
|
+
setup 'supersecretcookiespec'
|
83
|
+
end
|
88
84
|
|
89
|
-
|
85
|
+
def app
|
86
|
+
SpecApp
|
90
87
|
end
|
91
88
|
|
92
89
|
def gem_root_path
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: melodiest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kunto Aji Kristianto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 3.
|
33
|
+
version: 3.2.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 3.
|
40
|
+
version: 3.2.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rack-test
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,34 +52,20 @@ dependencies:
|
|
52
52
|
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 0.6.3
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: fakefs
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - '='
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 0.6.7
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - '='
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: 0.6.7
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: sinatra
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - '='
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version: 1.4.
|
61
|
+
version: 1.4.6
|
76
62
|
type: :runtime
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
66
|
- - '='
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version: 1.4.
|
68
|
+
version: 1.4.6
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: sinatra-contrib
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,20 +81,21 @@ dependencies:
|
|
95
81
|
- !ruby/object:Gem::Version
|
96
82
|
version: 1.4.2
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
84
|
+
name: encrypted_cookie
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
87
|
- - '='
|
102
88
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
89
|
+
version: 0.0.4
|
104
90
|
type: :runtime
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
94
|
- - '='
|
109
95
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
111
|
-
description: Melodiest provides generator and
|
96
|
+
version: 0.0.4
|
97
|
+
description: Melodiest provides generator and contains minimalist configuration to
|
98
|
+
develop application with Sinatra
|
112
99
|
email: kunto.aji.kr@slackware-id.org
|
113
100
|
executables:
|
114
101
|
- melodiest
|
@@ -117,20 +104,21 @@ extra_rdoc_files: []
|
|
117
104
|
files:
|
118
105
|
- ".gitignore"
|
119
106
|
- ".rspec"
|
107
|
+
- CHANGELOG.md
|
120
108
|
- Gemfile
|
121
109
|
- Gemfile.lock
|
122
110
|
- LICENSE.txt
|
123
111
|
- README.md
|
124
112
|
- bin/melodiest
|
125
113
|
- lib/melodiest.rb
|
126
|
-
- lib/melodiest/auth/http.rb
|
127
114
|
- lib/melodiest/command.rb
|
128
|
-
- lib/melodiest/config.yml
|
129
115
|
- lib/melodiest/generator.rb
|
130
116
|
- lib/melodiest/setting.rb
|
117
|
+
- lib/melodiest/templates/Rakefile
|
118
|
+
- lib/melodiest/templates/config/database.yml.example
|
119
|
+
- lib/melodiest/templates/db/migrations/000_example.rb
|
131
120
|
- lib/melodiest/version.rb
|
132
121
|
- melodiest.gemspec
|
133
|
-
- spec/melodiest/auth/http_spec.rb
|
134
122
|
- spec/melodiest/command_spec.rb
|
135
123
|
- spec/melodiest/generator_spec.rb
|
136
124
|
- spec/melodiest/setting_spec.rb
|
@@ -148,7 +136,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
148
136
|
requirements:
|
149
137
|
- - ">="
|
150
138
|
- !ruby/object:Gem::Version
|
151
|
-
version: '
|
139
|
+
version: '2.1'
|
152
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
141
|
requirements:
|
154
142
|
- - ">="
|
data/lib/melodiest/auth/http.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
module Melodiest
|
2
|
-
module Auth
|
3
|
-
|
4
|
-
# http://www.sinatrarb.com/faq.html#auth
|
5
|
-
module Http
|
6
|
-
def authorized!(username="admin", password="admin")
|
7
|
-
return if authorized?(username, password)
|
8
|
-
headers['WWW-Authenticate'] = 'Basic realm="Restricted Area"'
|
9
|
-
halt 401, "Not authorized\n"
|
10
|
-
end
|
11
|
-
|
12
|
-
def authorized?(username, password)
|
13
|
-
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
14
|
-
@auth.provided? and @auth.basic? and @auth.credentials and @auth.credentials == [username, password]
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
data/lib/melodiest/config.yml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
server: thin
|
@@ -1,25 +0,0 @@
|
|
1
|
-
describe Melodiest::Auth::Http do
|
2
|
-
it "respond to authorized!" do
|
3
|
-
expect(Melodiest::Auth::Http.method_defined?(:authorized!)).to be_truthy
|
4
|
-
end
|
5
|
-
|
6
|
-
it "respond to authorized?" do
|
7
|
-
expect(Melodiest::Auth::Http.method_defined?(:authorized?)).to be_truthy
|
8
|
-
end
|
9
|
-
|
10
|
-
it "returns 401 status code without authentication" do
|
11
|
-
get "/protected"
|
12
|
-
expect(last_response.status).to eq 401
|
13
|
-
end
|
14
|
-
|
15
|
-
it "returns 401 status code with bad authentication" do
|
16
|
-
get "/protected"
|
17
|
-
expect(last_response.status).to eq 401
|
18
|
-
end
|
19
|
-
|
20
|
-
it "returns 200 status code with good authentication" do
|
21
|
-
authorize "admin", "admin"
|
22
|
-
get "/protected"
|
23
|
-
expect(last_response.status).to eq 200
|
24
|
-
end
|
25
|
-
end
|