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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b579b11889dfcee9922093cab10b487bf65dc88
4
- data.tar.gz: 723d68077098c8218a7c75e6df36caa9550e9b9f
3
+ metadata.gz: fcb354a2aa73158378af93b4f18bf9d397f6b0da
4
+ data.tar.gz: b29f697ff27ba0ea4095382e41177bd47354b942
5
5
  SHA512:
6
- metadata.gz: 25f1d75cdd945a882798146c6e10942ce5bf5dba2cafdbc6dab8a84a63a6ba44b9eb524090980a92cea6cf59952743e5e91949232e10de02cdcb58415e5f006f
7
- data.tar.gz: b9c15805e704306bf1e2566dcdfa65b3f8e935b0dc5b782f85e27ede43f5b2f1ebfd4f212df256574f5a04e2315cf343b44d0f8df6a6eaa0eaa1ebae936a96ea
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
- sinatra (= 1.4.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
- eventmachine (1.0.7)
16
- fakefs (0.6.7)
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.1.0)
24
- rspec-core (~> 3.1.0)
25
- rspec-expectations (~> 3.1.0)
26
- rspec-mocks (~> 3.1.0)
27
- rspec-core (3.1.7)
28
- rspec-support (~> 3.1.0)
29
- rspec-expectations (3.1.2)
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.1.0)
32
- rspec-mocks (3.1.3)
33
- rspec-support (~> 3.1.0)
34
- rspec-support (3.1.2)
35
- sinatra (1.4.5)
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 (~> 1.3, >= 1.3.4)
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.1.0)
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 useful modules for developing application.
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
- #### Command
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 -d target/dir
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
- #### Example Code
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
- configure do
42
- # Load up database and such
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
- helpers Melodiest::Auth::Http
62
+ down do
63
+ drop_table(:artists)
64
+ end
46
65
  end
47
-
48
- # app/routes/my_routes.rb
49
-
50
- get "/" do
51
- "hello world!"
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 "/protected" do
55
- authorized! "myhttpauthusername", "myhttpauthpassword"
56
- "welcome!"
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
- bundle exec rackup
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
- * See [melodiest/config.yml](https://github.com/kuntoaji/melodiest/blob/master/lib/melodiest/config.yml)
70
-
71
- ### Modules
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
@@ -5,7 +5,7 @@ module Melodiest
5
5
 
6
6
  class Command
7
7
  def self.parse(options)
8
- args = {name: nil, dir: nil}
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("-dDIR", "--dir=DIR", "instead of current directory, generate app in target DIR") do |dir|
27
- args[:dir] = dir
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 = Command.run(args[:name], args[:dir]) unless args[:name].nil?
38
+ result = run(args) unless args[:name].nil?
35
39
 
36
40
  result
37
41
  end
38
42
 
39
- def self.run(app_name, target_dir)
40
- generator = Melodiest::Generator.new app_name, target_dir
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 = "#{app_name} is successfully generated"
47
- msg << " in #{target_dir}" if target_dir
52
+ msg = "#{args[:name]} is successfully generated"
53
+ msg << " in #{args[:target]}" if args[:target]
48
54
 
49
55
  msg
50
56
  end
@@ -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, destination=nil)
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
- destination = destination ? "#{destination}/#{@app_name}" : @app_name
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(" # Load up database and such\n")
69
+ f.write(content[:database])
45
70
  f.write(" end\n")
46
71
  f.write("end\n\n")
47
- f.write("# Load all route files\n")
48
- f.write("Dir[File.dirname(__FILE__) + \"/app/routes/**\"].each do |route|\n")
49
- f.write(" require route\n")
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
@@ -1,8 +1,16 @@
1
1
  module Melodiest
2
2
  module Setting
3
- def setup
4
- register Sinatra::ConfigFile
5
- config_file File.expand_path('../config.yml', __FILE__)
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,8 @@
1
+ # http://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html
2
+ #
3
+ # development:
4
+ # adapter: mysql2
5
+ # host: localhost
6
+ # database: exampledb_development
7
+ # user: exampleuser
8
+ # password: examplepassword
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Melodiest
2
- VERSION = '0.2.1'
2
+ VERSION = '0.3.0'
3
3
  end
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
- extend Setting
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 useful modules for your Sinatra application"
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.1.0'
18
+ s.add_development_dependency 'rspec', '3.2.0'
18
19
  s.add_development_dependency 'rack-test', '0.6.3'
19
- s.add_development_dependency 'fakefs', '0.6.7'
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 'thin', '1.6.3'
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 --directory option as target directory" do
28
- app = Melodiest::Command.parse %w(-n my_app --dir /tmp)
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
- context "when has no --name option and only --dir option" do
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(--dir /tmp/melodiest)
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
- include FakeFS::SpecHelpers
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
- let(:dest) { "/tmp/melodiest" }
8
- let(:app) { "my_app" }
9
- let(:generator) { Melodiest::Generator.new app, dest }
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 "#{dest}/#{app}"
38
+ expect("/tmp/melodiest/my_app").to eq target_dir
25
39
  end
26
40
 
27
41
  describe "#generate_gemfile" do
28
- let(:gemfile) { "#{dest}/#{app}/Gemfile" }
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
- it "should generate Gemfile with correct content" do
31
- generator.generate_gemfile
32
- file_content = File.read(gemfile)
59
+ context "with database" do
60
+ let(:gemfile) { "#{target_dir_with_db}/Gemfile" }
33
61
 
34
- expect(File.exists?(gemfile)).to be_truthy
35
- expect(file_content).to include "source 'https://rubygems.org'"
36
- expect(file_content).to include "gem 'melodiest', '#{Melodiest::VERSION}'"
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) { "#{dest}/#{app}/config.ru" }
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(:target_dir) { "#{dest}/#{app}" }
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
- # Load all route files
74
- Dir[File.dirname(__FILE__) + "/app/routes/**"].each do |route|
75
- require route
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
- it "respond to setup" do
3
- expect(Melodiest::Setting.method_defined?(:setup)).to be_truthy
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
@@ -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
- def app
83
- Melodiest::Application.helpers Melodiest::Auth::Http
84
-
85
- Melodiest::Application.get "/protected" do
86
- authorized!
87
- end
81
+ class SpecApp < Melodiest::Application
82
+ setup 'supersecretcookiespec'
83
+ end
88
84
 
89
- Melodiest::Application
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.2.1
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-04-21 00:00:00.000000000 Z
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.1.0
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.1.0
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.5
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.5
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: thin
84
+ name: encrypted_cookie
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
87
  - - '='
102
88
  - !ruby/object:Gem::Version
103
- version: 1.6.3
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: 1.6.3
111
- description: Melodiest provides generator and useful modules for your Sinatra application
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: '0'
139
+ version: '2.1'
152
140
  required_rubygems_version: !ruby/object:Gem::Requirement
153
141
  requirements:
154
142
  - - ">="
@@ -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
@@ -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