rhail 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +77 -0
  4. data/bin/rhail +78 -0
  5. data/generator_folders/.DS_Store +0 -0
  6. data/generator_folders/json/.DS_Store +0 -0
  7. data/generator_folders/json/.ruby-version +1 -0
  8. data/generator_folders/json/Gemfile +6 -0
  9. data/generator_folders/json/Gemfile.lock +17 -0
  10. data/generator_folders/json/config.ru +61 -0
  11. data/generator_folders/json/db/database.sqlite3 +0 -0
  12. data/generator_folders/json/db/seed.rb +31 -0
  13. data/generator_folders/json/public/.DS_Store +0 -0
  14. data/generator_folders/json/public/img/.DS_Store +0 -0
  15. data/generator_folders/json/public/img/favicon.png +0 -0
  16. data/generator_folders/json/settings.yml +1 -0
  17. data/generator_folders/plain/.DS_Store +0 -0
  18. data/generator_folders/plain/.ruby-version +1 -0
  19. data/generator_folders/plain/Gemfile +6 -0
  20. data/generator_folders/plain/Gemfile.lock +17 -0
  21. data/generator_folders/plain/config.ru +59 -0
  22. data/generator_folders/plain/db/database.sqlite3 +0 -0
  23. data/generator_folders/plain/db/seed.rb +31 -0
  24. data/generator_folders/plain/public/.DS_Store +0 -0
  25. data/generator_folders/plain/public/css/styles.css +123 -0
  26. data/generator_folders/plain/public/html/example_one.html +35 -0
  27. data/generator_folders/plain/public/html/example_three.html +75 -0
  28. data/generator_folders/plain/public/html/example_two.html +50 -0
  29. data/generator_folders/plain/public/html/foot.html +22 -0
  30. data/generator_folders/plain/public/html/head.html +51 -0
  31. data/generator_folders/plain/public/html/home.html +29 -0
  32. data/generator_folders/plain/public/img/favicon.png +0 -0
  33. data/generator_folders/plain/public/img/jumbotron.jpg +0 -0
  34. data/generator_folders/spa/.DS_Store +0 -0
  35. data/generator_folders/spa/.ruby-version +1 -0
  36. data/generator_folders/spa/Gemfile +6 -0
  37. data/generator_folders/spa/Gemfile.lock +17 -0
  38. data/generator_folders/spa/config.ru +49 -0
  39. data/generator_folders/spa/db/database.sqlite3 +0 -0
  40. data/generator_folders/spa/db/seed.rb +31 -0
  41. data/generator_folders/spa/public/.DS_Store +0 -0
  42. data/generator_folders/spa/public/css/styles.css +123 -0
  43. data/generator_folders/spa/public/html/index.html +186 -0
  44. data/generator_folders/spa/public/img/favicon.png +0 -0
  45. data/generator_folders/spa/public/img/jumbotron.jpg +0 -0
  46. data/generator_folders/spa/public/js/another-component.js +72 -0
  47. data/generator_folders/spa/public/js/app.js +16 -0
  48. data/lib/rhail.rb +13 -0
  49. data/lib/rhail/generator.rb +46 -0
  50. data/lib/rhail/helper.rb +117 -0
  51. data/lib/rhail/main.rb +8 -0
  52. data/rhail.gemspec +46 -0
  53. metadata +123 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 056abf1008fba20421c9ba46138ed29b6e5bf034
4
+ data.tar.gz: 05716cad7a09486017c33edc8b8a818bbb6150f7
5
+ SHA512:
6
+ metadata.gz: 64da155c38b307723f7233a7801a65b78d48041208b74b3a71f422d2fbd2a452cfd1a19afd2cfaabc9fd8e4b76dcdbc1942d62de8edd08eeb38a359f795858c4
7
+ data.tar.gz: 9a6d19cffba546c95747eb6613c7b48fe4b51786581e91f68ed97606f1fd9e1f10f75e07663544012bf7720604d0f5f5f0ffcc09e5fe08b064c50ce5ea1df89a
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 Maksim Sundukov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # Ruby Hail
2
+
3
+ ## About
4
+
5
+ Ruby Hail is Rack-based nano framework. It's the fastest-by-design Rack-based framework. It requires less learning (besides Rack, you suppose to know it by this time) than any other framework. It works great for simple dynamic web-sites, single-page web-apps and microservices.
6
+
7
+
8
+ ## Why
9
+
10
+ I was looking for balance between simplicity and development speed. If you go bellow Rack it's a lot of extra work for simple things. If you put a lot of abstractions on top of Rack then you loose track of what's going on under the hood and with high probability slowing things down.
11
+
12
+ I believe in right tool for the right job. If you look for fully-featured framework you might need Rails, something simpler - Sinatra, static site - Jekyll, blog - Wordpress. When you need simple web app or API that can do just couple of things really fast and easy - go Ruby Hail.
13
+
14
+ It was born when I was looking for web frameworks for Go and people advocated to not to use any except for the very basic ones. Otherwise you can't get the performance you're aiming for. So I took this concept to my favorite language - Ruby. I wanted to use as bare metal approach much as possible and to implement only the most necessary things so everyone can solve one task per app with high efficiency.
15
+
16
+ ## Use
17
+
18
+ ```
19
+ gem install rhail
20
+ rhail generate <plain|json|spa> path/to/folder # it will create directory with app structure
21
+ cd path/to/folder
22
+ # Install ruby via rvm if needed
23
+ gem install bundler
24
+ bundle install
25
+ bundle exec rackup # Go to http://127.0.0.1:9292 or wherever output tells you.
26
+ ```
27
+
28
+ To run it in production treat it as any other Rack-based (Rails or Sinatra) app. For example Passenger should be ponted to `<the folder>/public`.
29
+
30
+ Enjoy!
31
+
32
+ ## Generators
33
+
34
+ ### Plain
35
+
36
+ ```
37
+ rhail generate plain path/to/folder
38
+ ```
39
+
40
+ Traditional server-side-based web-app, with example of (relatively secured) form, database and very simple html templating. You can chain htmls and utilize ruby string interpolation.
41
+
42
+ ### JSON
43
+
44
+ ```
45
+ rhail generate json path/to/folder
46
+ ```
47
+
48
+ JSON Web-API with authentication.
49
+
50
+ #### Play with it
51
+
52
+ ```
53
+ curl -i -H 'Authorization: Token token="afbadb4ff8485c0adcba486b4ca90cc4"' http://127.0.0.1:9292/
54
+ curl -i -H 'Authorization: Token token="afbadb4ff8485c0adcba486b4ca90cc4"' http://127.0.0.1:9292/example_one
55
+ curl -i -H 'Authorization: Token token="afbadb4ff8485c0adcba486b4ca90cc4"' -H "Content-Type: application/json" -X POST -d '{"city":"asd","state":"asd","zipcode":"123","name":"asd"}' http://127.0.0.1:9292/example_two
56
+ ```
57
+
58
+ ### SPA
59
+
60
+ ```
61
+ rhail generate spa path/to/folder
62
+ ```
63
+
64
+ Single-page app based on Ruby Hail with VueJS. VueJS has a lot of similarities to AngularJS 1, minus performance issues.
65
+
66
+ ## Custom code
67
+
68
+ Once you play with automatically generated code you will want to extend it with your real functionality.
69
+
70
+ ```
71
+ RhailHelper.render_json(response_structure: {}, headers: {}
72
+ RhailHelper.render_html files: %w(head body foot), local_vars: {}, headers: {}
73
+ ```
74
+
75
+ ## Benchmarks
76
+
77
+ [In another repo](https://github.com/E-Xor/rhail-benchmark "Ruby Hail Benchmark")
data/bin/rhail ADDED
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rhail'
4
+
5
+ ##
6
+ # Exception in the bin/rhail for the case when user specifies wrong arguments for the rhail command.
7
+ #
8
+ class ArgError < StandardError; end
9
+
10
+ begin
11
+ case ARGV[0]
12
+ when 'g', 'gen', 'generate'
13
+ type = ARGV[1]
14
+ raise ArgError unless type
15
+
16
+ puts
17
+ gen = Rhail::Generator.new(type: type, folder: ARGV[2])
18
+ puts 'Creating file structure ...'
19
+ gen.create_folder_with_app
20
+
21
+ install_dependencies = false # Later get from parameter
22
+ if type == 'json'
23
+ further_instructions = %Q( Test it\n\tcurl -i -H 'Authorization: Token token="afbadb4ff8485c0adcba486b4ca90cc4"' http://127.0.0.1:9292/\n)
24
+ else
25
+ further_instructions = " Go to http://127.0.0.1:9292 or wherever output tells you."
26
+ end
27
+
28
+ if install_dependencies
29
+ puts 'Installing dependencies ...'
30
+ gen.install_dependencies
31
+ done_message = %Q(
32
+
33
+ \e[32mDone!
34
+
35
+ What to do next?
36
+
37
+ $ cd #{gen.folder}/#{gen.type}
38
+ $ bundle exec rackup
39
+
40
+ #{further_instructions}
41
+
42
+ Enjoy!
43
+
44
+ \e[0m
45
+
46
+ )
47
+ else
48
+ done_message = %Q(
49
+
50
+ \e[32mDone!
51
+
52
+ What to do next?
53
+
54
+ $ cd #{gen.folder}/#{gen.type}
55
+ $ gem install bundler
56
+ $ bundle install
57
+ $ bundle exec rackup
58
+
59
+ #{further_instructions}
60
+
61
+ Enjoy!
62
+
63
+ \e[0m
64
+
65
+ )
66
+ end
67
+
68
+ puts done_message
69
+
70
+ else
71
+ raise ArgError
72
+ end
73
+ rescue ArgError => e
74
+ puts Rhail::USAGE
75
+ rescue => e
76
+ puts "\e[31mError happened: #{e.message}\e[0m"
77
+ raise e
78
+ end
Binary file
Binary file
@@ -0,0 +1 @@
1
+ ruby-2.3.0@rhail_json
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rack', '~> 2.0.1'
4
+ gem 'sequel', '~> 4.41.0'
5
+ gem 'sqlite3', '~> 1.3.12'
6
+ gem 'rhail', path: '/Users/maksim/other-apps/rhail/'
@@ -0,0 +1,17 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ rack (2.0.1)
5
+ sequel (4.41.0)
6
+ sqlite3 (1.3.12)
7
+
8
+ PLATFORMS
9
+ ruby
10
+
11
+ DEPENDENCIES
12
+ rack (~> 2.0.1)
13
+ sequel (~> 4.41.0)
14
+ sqlite3 (~> 1.3.12)
15
+
16
+ BUNDLED WITH
17
+ 1.13.7
@@ -0,0 +1,61 @@
1
+ require 'rhail/helper'
2
+ require 'yaml'
3
+ require 'sequel'
4
+
5
+ use Rack::Static, :urls => ['/img'], :root => 'public' # http://www.rubydoc.info/github/rack/rack/Rack/Static
6
+
7
+ SETTINGS = YAML.load_file(File.expand_path('../settings.yml',__FILE__))
8
+ TOKEN_VALUE = SETTINGS['token']
9
+ DB = Sequel.sqlite('db/database.sqlite3')
10
+
11
+ class WebApi
12
+
13
+ def self.call(env)
14
+ req = Rack::Request.new(env)
15
+
16
+ case
17
+ when req.get? && req.path_info == '/'
18
+
19
+ h = {
20
+ one: '584c5915f896067cb0927bd6',
21
+ two: 0,
22
+ three: 'f5ef49a3-2b82-46f5-aa8f-1180f7dbef98',
23
+ four: true,
24
+ five: '$2,343.28',
25
+ six: 33,
26
+ seven: 'blue',
27
+ eight: 'dot'
28
+ }
29
+ Rhail::Helper.token_auth(env['HTTP_AUTHORIZATION'], TOKEN_VALUE) do |t|
30
+ Rhail::Helper.render_json(response_structure: h)
31
+ end
32
+
33
+ when req.get? && req.path_info == '/example_one'
34
+ Rhail::Helper.token_auth(env['HTTP_AUTHORIZATION'], TOKEN_VALUE) do |t|
35
+ people_with_addresses = DB[:people].left_join(:addresses, id: :address_id).select(:name, :city, :state, :zipcode).all
36
+ Rhail::Helper.render_json(response_structure: people_with_addresses)
37
+ end
38
+
39
+ when req.post? && req.path_info == '/example_two'
40
+ Rhail::Helper.token_auth(env['HTTP_AUTHORIZATION'], TOKEN_VALUE) do |t|
41
+ params = Rhail::Helper.params_from_json_request(req)
42
+
43
+ address_id = DB[:addresses].insert(city: params['city'], state: params['state'], zipcode: params['zipcode'])
44
+ DB[:people].insert(name: params['name'], address_id: address_id)
45
+
46
+ people_with_addresses = DB[:people].left_join(:addresses, id: :address_id).select(:name, :city, :state, :zipcode).all
47
+ Rhail::Helper.render_json(response_structure: people_with_addresses)
48
+ end
49
+ end
50
+
51
+ rescue => e
52
+ Rhail::Helper.render_json(response_structure: {status: '500', code: 'Internal Server Error', detail: e.message}, status: 500)
53
+ end
54
+
55
+ end
56
+
57
+ run WebApi
58
+
59
+ # curl -i -H 'Authorization: Token token="afbadb4ff8485c0adcba486b4ca90cc4"' http://127.0.0.1:9292/
60
+ # curl -i -H 'Authorization: Token token="afbadb4ff8485c0adcba486b4ca90cc4"' http://127.0.0.1:9292/example_one
61
+ # curl -i -H 'Authorization: Token token="afbadb4ff8485c0adcba486b4ca90cc4"' -H "Content-Type: application/json" -X POST -d '{"city":"asd","state":"asd","zipcode":"123","name":"asd"}' http://127.0.0.1:9292/example_two
@@ -0,0 +1,31 @@
1
+ require 'sequel'
2
+
3
+ DB = Sequel.sqlite('db/database.sqlite3')
4
+
5
+ DB.run "DROP TABLE IF EXISTS addresses"
6
+ DB.run "DROP TABLE IF EXISTS people"
7
+
8
+ DB.create_table :addresses do
9
+ primary_key :id
10
+ String :street_1, :size => 255
11
+ String :street_2, :size => 255
12
+ String :city
13
+ String :state, :size => 2
14
+ String :zipcode, :size => 5
15
+ end
16
+
17
+ DB.run "INSERT INTO addresses(city, state, zipcode) VALUES('Atlanta', 'GA', '30305')"
18
+ DB.run "INSERT INTO addresses(city, state, zipcode) VALUES('Houston', 'TX', '77001')"
19
+ DB.run "INSERT INTO addresses(city, state, zipcode) VALUES('Fargo', 'ND', '58102')"
20
+
21
+
22
+ DB.create_table :people do
23
+ primary_key :id
24
+ String :name, :size => 255
25
+ Integer :address_id
26
+ end
27
+
28
+ DB.run "INSERT INTO people(name, address_id) VALUES('George', 1)"
29
+ DB.run "INSERT INTO people(name, address_id) VALUES('Thomas', 2)"
30
+ DB.run "INSERT INTO people(name, address_id) VALUES('Douglas', 3)"
31
+
@@ -0,0 +1 @@
1
+ token: 'afbadb4ff8485c0adcba486b4ca90cc4'
Binary file
@@ -0,0 +1 @@
1
+ ruby-2.3.0@rhail_plain
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rack', '~> 2.0.1'
4
+ gem 'sequel', '~> 4.41.0'
5
+ gem 'sqlite3', '~> 1.3.12'
6
+ gem 'rhail', path: '/Users/maksim/other-apps/rhail/'
@@ -0,0 +1,17 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ rack (2.0.1)
5
+ sequel (4.41.0)
6
+ sqlite3 (1.3.12)
7
+
8
+ PLATFORMS
9
+ ruby
10
+
11
+ DEPENDENCIES
12
+ rack (~> 2.0.1)
13
+ sequel (~> 4.41.0)
14
+ sqlite3 (~> 1.3.12)
15
+
16
+ BUNDLED WITH
17
+ 1.13.6
@@ -0,0 +1,59 @@
1
+ require 'rhail/helper'
2
+ require 'sequel'
3
+ require 'securerandom'
4
+
5
+ use Rack::Static, :urls => ['/img', '/css'], :root => 'public' # http://www.rubydoc.info/github/rack/rack/Rack/Static
6
+ use Rack::Session::Pool
7
+
8
+ DB = Sequel.sqlite('db/database.sqlite3')
9
+
10
+ class RhailPlain
11
+ def self.call(env)
12
+
13
+ req = Rack::Request.new(env)
14
+
15
+ case
16
+ when req.get? && req.path_info == '/'
17
+
18
+ Rhail::Helper.render_html files: %w(head home foot), local_vars: {page: 'home'}
19
+
20
+ when req.get? && req.path_info == '/example_one'
21
+
22
+ Rhail::Helper.render_html files: %w(head example_one foot), local_vars: {page: 'example_one'}
23
+
24
+ when req.get? && req.path_info == '/example_two'
25
+
26
+ Rhail::Helper.render_html files: %w(head example_two foot), local_vars: {page: 'example_two'}
27
+
28
+ when req.post? && req.path_info == '/example_two' # post
29
+
30
+ Rhail::Helper.render_html files: %w(head example_two foot), local_vars: {page: 'example_two', results: req.params}
31
+
32
+ when req.get? && req.path_info == '/example_three'
33
+
34
+ req.session['csrf.token'] = SecureRandom.urlsafe_base64(32)
35
+
36
+ people_with_addresses = DB[:people].left_join(:addresses, id: :address_id).select(:name, :city, :state, :zipcode).all
37
+
38
+ Rhail::Helper.render_html files: %w(head example_three foot), local_vars: {page: 'example_three', results: people_with_addresses, csrf_token: env['rack.session']['csrf.token']}
39
+
40
+ when req.post? && req.path_info == '/example_three' # post
41
+
42
+ params = req.params
43
+
44
+ if params['csrf_token'] == req.session['csrf.token']
45
+
46
+ address_id = DB[:addresses].insert(city: params['city'], state: params['state'], zipcode: params['zipcode'])
47
+ DB[:people].insert(name: params['name'], address_id: address_id)
48
+
49
+ else
50
+ puts "CSRF check failed."
51
+ end
52
+
53
+ [302, {'Location' => '/example_three', 'Content-Type' => 'text/html'}, ['302 found']]
54
+ end
55
+
56
+ end
57
+ end
58
+
59
+ run RhailPlain
@@ -0,0 +1,31 @@
1
+ require 'sequel'
2
+
3
+ DB = Sequel.sqlite('db/database.sqlite3')
4
+
5
+ DB.run "DROP TABLE IF EXISTS addresses"
6
+ DB.run "DROP TABLE IF EXISTS people"
7
+
8
+ DB.create_table :addresses do
9
+ primary_key :id
10
+ String :street_1, :size => 255
11
+ String :street_2, :size => 255
12
+ String :city
13
+ String :state, :size => 2
14
+ String :zipcode, :size => 5
15
+ end
16
+
17
+ DB.run "INSERT INTO addresses(city, state, zipcode) VALUES('Atlanta', 'GA', '30305')"
18
+ DB.run "INSERT INTO addresses(city, state, zipcode) VALUES('Houston', 'TX', '77001')"
19
+ DB.run "INSERT INTO addresses(city, state, zipcode) VALUES('Fargo', 'ND', '58102')"
20
+
21
+
22
+ DB.create_table :people do
23
+ primary_key :id
24
+ String :name, :size => 255
25
+ Integer :address_id
26
+ end
27
+
28
+ DB.run "INSERT INTO people(name, address_id) VALUES('George', 1)"
29
+ DB.run "INSERT INTO people(name, address_id) VALUES('Thomas', 2)"
30
+ DB.run "INSERT INTO people(name, address_id) VALUES('Douglas', 3)"
31
+