hobby 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c721c77a7b912fa113e730de3ff58cdf8866e06
4
- data.tar.gz: 4590a7005e8597a277cae934955b30b0a981b1b4
3
+ metadata.gz: 42e7f7a0e7818909ac5d95c50484655aab19fac1
4
+ data.tar.gz: 7b0f857a9f4ceb6dfdb0eff86d6d546d2b285a6a
5
5
  SHA512:
6
- metadata.gz: 2bb9aa2ee633d3d06c85a7e41dd1a1b59bb4d870c48de2b351846b7e38566e1f17731bb94894bcec50e917e1fbcfab51d7784d6175ae89db37476918373d3403
7
- data.tar.gz: efa3483ccf3ea59cc6e6e16dd4280713eaef4e7a04b1ac1cd66c07e42344cd42efb6a52ddabab7cf4ed2fee032926264fb6f7224f8750e555976309d29665364
6
+ metadata.gz: d2f3740ca3b95e942af4bf6dc4fb5f8d5acfdd21bd6c48f0544b8f262de0f004856a31547f3739ad440a11195c80a0348e4c4237afb026d4fa566dc6cb138ad2
7
+ data.tar.gz: fe87a3f5ca1be2c5ee1a346cdeb9e26800c642e4de8251217f8461ba91c8dbb63c7b52ea1a208edb35f6851d27b47e385df4bfb153849065e826fc1b2ace1fed
data/Gemfile CHANGED
@@ -1,3 +1,10 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem 'devtools', github: 'mbj/devtools'
4
+ gem 'minitest'
5
+ gem 'minitest-power_assert'
6
+ gem 'rack-test'
7
+ gem 'pry'
8
+ gem 'awesome_print'
9
+
3
10
  gemspec
data/LICENSE CHANGED
@@ -1,4 +1,5 @@
1
1
  Copyright (c) 2013 Patricio Mac Adden
2
+ Copyright (c) 2015 Anatoly Cherno
2
3
 
3
4
  MIT License
4
5
 
data/hobby.gemspec CHANGED
@@ -4,12 +4,11 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'hobby'
7
- spec.version = '0.0.0'
8
- spec.authors = ['Patricio Mac Adden']
9
- spec.email = ['patriciomacadden@gmail.com']
10
- spec.description = %q{A minimalistic microframework built on top of rack}
11
- spec.summary = %q{A minimalistic microframework built on top of rack}
12
- spec.homepage = 'https://github.com/patriciomacadden/hobbit'
7
+ spec.version = '0.0.1'
8
+ spec.authors = ['Anatoly Cherno']
9
+ spec.email = ['anatoly.cherno@gmail.com']
10
+ spec.summary = %q{A minimal DSL over rack}
11
+ spec.homepage = 'https://github.com/ch1c0t/hobby'
13
12
  spec.license = 'MIT'
14
13
 
15
14
  spec.files = `git ls-files`.split($/)
@@ -18,12 +17,4 @@ Gem::Specification.new do |spec|
18
17
  spec.require_paths = ['lib']
19
18
 
20
19
  spec.add_dependency 'rack'
21
- spec.add_dependency 'include_constants'
22
-
23
- spec.add_development_dependency 'bundler', '~> 1.3'
24
- spec.add_development_dependency 'codeclimate-test-reporter'
25
- spec.add_development_dependency 'rack-test'
26
- spec.add_development_dependency 'rake'
27
- spec.add_development_dependency 'minitest'
28
- spec.add_development_dependency 'minitest-power_assert'
29
20
  end
data/lib/hobby/app.rb CHANGED
@@ -1,66 +1,59 @@
1
1
  module Hobby
2
- class App
3
- class << self
4
- def members
5
- @members ||= {}
6
- end
2
+ module App
3
+ def self.included app
4
+ app.extend Singleton
5
+ app.builder, app.router = Rack::Builder.new, Router.new
6
+ app.request, app.response = Rack::Request, Rack::Response
7
+ end
7
8
 
8
- [:builder, :router].each do |member|
9
- define_method member do |&custom_member|
10
- if custom_member
11
- members[member] = custom_member.call
12
- else
13
- members[member] ||= Hobby.const_get(member.capitalize).new
14
- end
15
- end
9
+ module Singleton
10
+ attr_accessor :builder, :router, :request, :response
11
+
12
+ def new (*)
13
+ builder.run super
14
+ builder.to_app
16
15
  end
17
16
 
17
+ extend Forwardable
18
+ delegate [:map, :use] => :builder
19
+
18
20
  Verbs.each do |verb|
19
- define_method verb.downcase do |path, &route|
21
+ define_method verb.downcase do |path = '/', &route|
20
22
  router.add_route verb, path, &route
21
23
  end
22
24
  end
23
-
24
- alias :_new :new
25
- def new *args, &block
26
- builder.run _new(*args, &block)
27
- builder
28
- end
29
-
30
- extend Forwardable
31
- delegate [:map, :use] => :builder
32
25
  end
33
26
 
34
- attr_reader :env, :request, :response
35
-
36
27
  def call env
37
28
  dup.handle env
38
29
  end
39
30
 
40
- def handle env
41
- @env = env
42
- @request = Request.new @env
43
- @response = Response.new
31
+ protected
32
+ def handle env
33
+ route = self.class.router.route_for (@env = env)
44
34
 
45
- catch(:halt) { route_eval }
46
- end
35
+ if route
36
+ response.write instance_exec &route
37
+ else
38
+ response.status = 404
39
+ end
47
40
 
48
- private
41
+ response
42
+ end
49
43
 
50
- def halt response
51
- throw :halt, response
52
- end
44
+ private
45
+ attr_reader :env
53
46
 
54
- def route_eval
55
- route = self.class.router.route_for request
47
+ def request
48
+ @request ||= self.class.request.new env
49
+ end
56
50
 
57
- if route
58
- response.write instance_eval &route
59
- else
60
- response.status = 404
51
+ def response
52
+ @response ||= self.class.response.new
61
53
  end
62
54
 
63
- response.finish
64
- end
55
+ def my
56
+ env.fetch :path_params, {}
57
+ end
65
58
  end
66
59
  end
data/lib/hobby/router.rb CHANGED
@@ -1,29 +1,41 @@
1
1
  module Hobby
2
2
  class Router
3
- require_relative 'router/route'
4
-
5
3
  def initialize
6
- @routes = Hash.new { |hash, key| hash[key] = [] }
4
+ @routes = Routes.new
5
+ end
6
+
7
+ def add_route verb, path, &route
8
+ path = nil if path.eql? '/'
9
+ @routes["#{verb}#{path}"] = route
7
10
  end
8
11
 
9
- def add_route(verb, path, &block)
10
- @routes[verb] << Route.new(path, &block)
11
- self
12
+ def route_for env
13
+ route, params = @routes["#{env['REQUEST_METHOD']}#{env['PATH_INFO']}"]
14
+ env[:path_params] = params if params
15
+ route
12
16
  end
13
17
 
14
- def route_for(request)
15
- route = @routes[request.request_method].detect do |route|
16
- route.compiled_path =~ request.path_info
18
+ class Routes < Hash
19
+ def initialize
20
+ @patterns = {}
21
+ super { |hash, key| hash[key] = find key }
17
22
  end
18
23
 
19
- if route
20
- $~.captures.each_with_index do |value, index|
21
- param = route.extra_params[index]
22
- request.params[param] = value
24
+ def []= key, route
25
+ if key.include? ?:
26
+ string = key.gsub(/(:\w+)/) { "(?<#{$1[1..-1]}>[^/?#]+)" }
27
+ @patterns[/^#{string}$/] = route
28
+ else
29
+ super and super "#{key}/", route
23
30
  end
24
31
  end
25
32
 
26
- route
33
+ private
34
+
35
+ def find key
36
+ _, route = @patterns.find { |pattern, _| pattern.match key }
37
+ [route, $~.names.map(&:to_sym).zip($~.captures).to_h] if route
38
+ end
27
39
  end
28
40
  end
29
41
  end
@@ -0,0 +1,35 @@
1
+ module Hobby::RSpec
2
+ module Router
3
+ extend self
4
+ SOME_ROUTE = ->{}
5
+
6
+ def env_for path, verb = 'GET'
7
+ {'REQUEST_METHOD' => verb, 'PATH_INFO' => path }
8
+ end
9
+
10
+ def add_routes *routes
11
+ routes.each { |route| subject.add_route 'GET', route, &SOME_ROUTE }
12
+ end
13
+
14
+ extend RSpec::Matchers::DSL
15
+
16
+ define :find_route do |path, verb = 'GET'|
17
+ match do |subject|
18
+ env = env_for path, verb
19
+ route = subject.route_for env
20
+
21
+ params_are_ok = (@params ? (@params.to_a - env[:path_params].to_a).empty? : true)
22
+
23
+ (route == SOME_ROUTE) && params_are_ok
24
+ end
25
+
26
+ chain :and_set_params do |**params|
27
+ @params = params
28
+ end
29
+ end
30
+
31
+ def self.included example_group
32
+ example_group.extend self
33
+ end
34
+ end
35
+ end
data/lib/hobby.rb CHANGED
@@ -1,10 +1,9 @@
1
1
  require 'rack'
2
2
  require 'forwardable'
3
- require 'include_constants'
4
3
 
5
4
  module Hobby
6
5
  Verbs = %w!DELETE GET HEAD OPTIONS PATCH POST PUT!
7
- require 'hobby/app'
8
- autoload :Router, 'hobby/router'
9
- include_constants :Builder, :Request, :Response, from: Rack
10
6
  end
7
+
8
+ require 'hobby/router'
9
+ require 'hobby/app'
data/spec/app_spec.rb ADDED
@@ -0,0 +1,146 @@
1
+ require 'helper'
2
+ require 'rack/test'
3
+
4
+ $sources = {}
5
+
6
+ Dir['spec/apps/*.rb'].each do |file|
7
+ name = File.basename file, '.rb'
8
+
9
+ eval %!
10
+ class #{name}
11
+ class << self
12
+ attr_accessor :app
13
+ end
14
+ end
15
+ !
16
+
17
+ $sources[Object.const_get name] = IO.read file
18
+ end
19
+
20
+ def build_app described_class
21
+ body = $sources[described_class]
22
+
23
+ eval %!
24
+ Class.new do
25
+ include Hobby::App
26
+ #{body}
27
+ end
28
+ !
29
+ end
30
+
31
+ describe Hobby::App do
32
+ include Rack::Test::Methods
33
+
34
+ describe '.new' do
35
+ context 'an app with nested app(s)' do
36
+ let(:subject) { build_app(Nested).new }
37
+ it { should be_a Rack::URLMap }
38
+ end
39
+
40
+ context 'an app without nested app(s)' do
41
+ let(:subject) { build_app(Main).new }
42
+ it { should be_a Hobby::App }
43
+ end
44
+ end
45
+
46
+ describe '#call' do
47
+ def app
48
+ build_app(Main).new
49
+ end
50
+
51
+ context 'when a route was found' do
52
+ it 'evaluates the route' do
53
+ get '/existent'
54
+
55
+ assert { last_response.ok? }
56
+ assert { last_response.body == 'existent' }
57
+ end
58
+ end
59
+
60
+ context 'when a route was not found' do
61
+ it 'responds with 404 status code' do
62
+ get '/nonexistent/route'
63
+
64
+ assert { last_response.not_found? }
65
+ assert { last_response.body.empty? }
66
+ end
67
+ end
68
+
69
+ it 'gives a distinct object to each request' do
70
+ get '/first'
71
+ assert { last_response.body == 'first' }
72
+
73
+ get '/second'
74
+ assert { last_response.body != 'first' }
75
+ assert { last_response.body == 'second' }
76
+ end
77
+ end
78
+
79
+ describe :integration do
80
+ before do
81
+ described_class.app = build_app described_class
82
+ end
83
+
84
+ def app
85
+ described_class.app.new
86
+ end
87
+
88
+ describe Map do
89
+ it 'mounts an application to the rack stack' do
90
+ get '/map'
91
+ assert { last_response.body == 'from map' }
92
+ end
93
+ end
94
+
95
+ describe Use do
96
+ it 'adds a middleware to the rack stack' do
97
+ get '/use'
98
+ assert { last_response.body == 'from use' }
99
+ end
100
+ end
101
+
102
+ describe WithoutPath do
103
+ it 'is accessible as /' do
104
+ get '/'
105
+ assert { last_response.body == 'root' }
106
+ end
107
+ end
108
+
109
+ describe OneRouteRouter do
110
+ it 'returns for any route' do
111
+ get '/'
112
+ assert { last_response.body == 'for any route' }
113
+
114
+ get '/some-other-route'
115
+ assert { last_response.body == 'for any route' }
116
+ end
117
+ end
118
+
119
+ describe Env do
120
+ it do
121
+ get '/query_string?1=2&3=4'
122
+ assert { last_response.body == '1=2&3=4' }
123
+ end
124
+
125
+ it do
126
+ get '/access_params?key=value'
127
+ assert { last_response.body == 'value' }
128
+ end
129
+
130
+ it do
131
+ get '/access_path_params_via_my'
132
+ assert { last_response.body == 'true' }
133
+
134
+ get '/access_path_params_via_env'
135
+ assert { last_response.body == 'true' }
136
+ end
137
+ end
138
+
139
+ describe Nested do
140
+ it do
141
+ get '/nested'
142
+ assert { last_response.body == 'a:b:c' }
143
+ end
144
+ end
145
+ end
146
+ end
data/spec/apps/Env.rb ADDED
@@ -0,0 +1,15 @@
1
+ get '/query_string' do
2
+ env['QUERY_STRING']
3
+ end
4
+
5
+ get '/access_params' do
6
+ request.params['key']
7
+ end
8
+
9
+ get '/access_path_params_via_my' do
10
+ my[:key].nil?
11
+ end
12
+
13
+ get '/access_path_params_via_env' do
14
+ env[:path_params].nil?
15
+ end
data/spec/apps/Main.rb ADDED
@@ -0,0 +1,4 @@
1
+ Hobby::Verbs.each do |verb|
2
+ class_eval "#{verb.downcase}('/') { '#{verb}' }"
3
+ class_eval "#{verb.downcase}('/:name') { my[:name] }"
4
+ end
data/spec/apps/Map.rb ADDED
@@ -0,0 +1,5 @@
1
+ map '/map' do
2
+ run Proc.new { |env| [200, {}, ['from map']] }
3
+ end
4
+
5
+ get('/') { 'hello world' }
@@ -0,0 +1,17 @@
1
+ map('/nested') do
2
+ nested_app = Class.new do
3
+ include Hobby::App
4
+
5
+ def initialize first, second
6
+ @a = first
7
+ @b = second
8
+ @c = yield
9
+ end
10
+
11
+ get do
12
+ "#{@a}:#{@b}:#{@c}"
13
+ end
14
+ end
15
+
16
+ run nested_app.new(:a, :b) { :c }
17
+ end
@@ -0,0 +1,8 @@
1
+ self.router = Class.new {
2
+ def add_route(*)
3
+ end
4
+
5
+ def route_for _request
6
+ -> { 'for any route' }
7
+ end
8
+ }.new
data/spec/apps/Use.rb ADDED
@@ -0,0 +1,15 @@
1
+ middleware = Class.new do
2
+ def initialize(app = nil)
3
+ @app = app
4
+ end
5
+
6
+ def call(env)
7
+ request = Rack::Request.new(env)
8
+ @app.call(env) unless request.path_info == '/use'
9
+ [200, {}, 'from use']
10
+ end
11
+ end
12
+
13
+ use middleware
14
+
15
+ get('/') { 'hello world' }
@@ -0,0 +1,3 @@
1
+ get do
2
+ 'root'
3
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'devtools/spec_helper'
2
+
3
+ require 'hobby'
4
+ require 'hobby/rspec/router'
5
+
6
+ require 'minitest'
7
+ require 'minitest-power_assert'
8
+ Minitest::Assertions.prepend Minitest::PowerAssert::Assertions
9
+
10
+ if defined? Mutant
11
+ class Mutant::Selector::Expression
12
+ def call _subject
13
+ integration.all_tests
14
+ end
15
+ end
16
+ end
17
+
18
+ RSpec.configure do |config|
19
+ config.expect_with :rspec, :minitest
20
+ config.include Hobby::RSpec::Router, type: :router
21
+ end
@@ -0,0 +1,46 @@
1
+ require 'helper'
2
+
3
+ describe Hobby::RSpec::Router do
4
+ before do
5
+ @Group = Class.new do
6
+ def subject
7
+ @router ||= Hobby::Router.new
8
+ end
9
+ end.include described_class
10
+ end
11
+
12
+ it 'contains a few helpers in its singleton' do
13
+ [:env_for, :add_routes, :find_route].each do |name|
14
+ assert { @Group.respond_to? name }
15
+ end
16
+ end
17
+
18
+ describe 'env_for' do
19
+ context 'two arguments passed' do
20
+ it 'returns an environment' do
21
+ env = { "REQUEST_METHOD" => 'POST', "PATH_INFO" => '/some_path' }
22
+ assert { env == (@Group.env_for '/some_path', 'POST') }
23
+ end
24
+ end
25
+
26
+ context 'one argument passed' do
27
+ it 'defaults to GET' do
28
+ env = { "REQUEST_METHOD" => 'GET', "PATH_INFO" => '/some_path' }
29
+ assert { env == (@Group.env_for '/some_path') }
30
+ end
31
+ end
32
+ end
33
+
34
+ describe 'add_routes' do
35
+ it do
36
+ routes = %w! first second third!
37
+ group = @Group.new
38
+
39
+ group.add_routes *routes
40
+
41
+ routes.each do |route|
42
+ expect(group.subject.route_for group.env_for 'first').to be_truthy
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,37 @@
1
+ require 'helper'
2
+
3
+ describe Hobby::Router, type: :router do
4
+ routes = %w!
5
+ /with.dot
6
+ /with-hyphen
7
+ /hello/:name
8
+ /say/:something/to/:someone
9
+ /route/:id.json
10
+ /existent/only/for/GET
11
+ !
12
+
13
+ before { add_routes *routes }
14
+
15
+ it { should find_route '/with.dot' }
16
+ it { should find_route '/with-hyphen' }
17
+ it { should find_route '/with.dot/' }
18
+ it { should find_route '/with-hyphen/' }
19
+
20
+ it { should find_route '/existent/only/for/GET' }
21
+ it { should_not find_route '/nonexistent' }
22
+ it { should_not find_route '/existent/only/for/GET', 'POST' }
23
+
24
+ it { should find_route('/hello/ololo').and_set_params(name: 'ololo') }
25
+ it { should find_route('/route/66.json').and_set_params(id: '66') }
26
+ it do
27
+ should find_route('/say/nothing/to/no_one').
28
+ and_set_params(something: 'nothing', someone: 'no_one')
29
+ end
30
+
31
+
32
+ it 'memoizes requests with params' do
33
+ subject.route_for env_for '/hello/ololo'
34
+
35
+ assert { subject.instance_variable_get(:@routes).include? 'GET/hello/ololo' }
36
+ end
37
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hobby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
- - Patricio Mac Adden
7
+ - Anatoly Cherno
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-16 00:00:00.000000000 Z
11
+ date: 2016-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -24,107 +24,9 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: include_constants
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: bundler
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '1.3'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '1.3'
55
- - !ruby/object:Gem::Dependency
56
- name: codeclimate-test-reporter
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rack-test
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rake
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: minitest
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: minitest-power_assert
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- description: A minimalistic microframework built on top of rack
27
+ description:
126
28
  email:
127
- - patriciomacadden@gmail.com
29
+ - anatoly.cherno@gmail.com
128
30
  executables: []
129
31
  extensions: []
130
32
  extra_rdoc_files: []
@@ -140,11 +42,19 @@ files:
140
42
  - lib/hobby.rb
141
43
  - lib/hobby/app.rb
142
44
  - lib/hobby/router.rb
143
- - lib/hobby/router/route.rb
144
- - test/helper.rb
145
- - test/test_app.rb
146
- - test/test_router.rb
147
- homepage: https://github.com/patriciomacadden/hobbit
45
+ - lib/hobby/rspec/router.rb
46
+ - spec/app_spec.rb
47
+ - spec/apps/Env.rb
48
+ - spec/apps/Main.rb
49
+ - spec/apps/Map.rb
50
+ - spec/apps/Nested.rb
51
+ - spec/apps/OneRouteRouter.rb
52
+ - spec/apps/Use.rb
53
+ - spec/apps/WithoutPath.rb
54
+ - spec/helper.rb
55
+ - spec/router_group_spec.rb
56
+ - spec/router_spec.rb
57
+ homepage: https://github.com/ch1c0t/hobby
148
58
  licenses:
149
59
  - MIT
150
60
  metadata: {}
@@ -164,12 +74,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
74
  version: '0'
165
75
  requirements: []
166
76
  rubyforge_project:
167
- rubygems_version: 2.4.5
77
+ rubygems_version: 2.5.1
168
78
  signing_key:
169
79
  specification_version: 4
170
- summary: A minimalistic microframework built on top of rack
80
+ summary: A minimal DSL over rack
171
81
  test_files:
172
- - test/helper.rb
173
- - test/test_app.rb
174
- - test/test_router.rb
175
- has_rdoc:
82
+ - spec/app_spec.rb
83
+ - spec/apps/Env.rb
84
+ - spec/apps/Main.rb
85
+ - spec/apps/Map.rb
86
+ - spec/apps/Nested.rb
87
+ - spec/apps/OneRouteRouter.rb
88
+ - spec/apps/Use.rb
89
+ - spec/apps/WithoutPath.rb
90
+ - spec/helper.rb
91
+ - spec/router_group_spec.rb
92
+ - spec/router_spec.rb
@@ -1,20 +0,0 @@
1
- class Hobby::Router
2
- class Route
3
- attr_reader :compiled_path, :extra_params, :path
4
- def initialize(path, &block)
5
- @path = path
6
- @block = block
7
-
8
- @extra_params = []
9
- compiled_path = path.gsub(/:\w+/) do |match|
10
- @extra_params << match.gsub(':', '').to_sym
11
- '([^/?#]+)'
12
- end
13
- @compiled_path = /^#{compiled_path}$/
14
- end
15
-
16
- def to_proc
17
- @block
18
- end
19
- end
20
- end
data/test/helper.rb DELETED
@@ -1,5 +0,0 @@
1
- require 'hobby'
2
- require 'rack/test'
3
-
4
- require 'minitest-power_assert'
5
- require 'minitest/autorun'
data/test/test_app.rb DELETED
@@ -1,189 +0,0 @@
1
- require_relative 'helper'
2
-
3
- module Minitest
4
- class Test
5
- include Rack::Test::Methods
6
-
7
- def mock_app(&block)
8
- @app = Class.new(Hobby::App, &block).new
9
- end
10
-
11
- def app
12
- @app
13
- end
14
- end
15
- end
16
-
17
- describe Hobby::App do
18
- describe :main_app do
19
- before do
20
- mock_app do
21
- Hobby::Verbs.each do |verb|
22
- class_eval "#{verb.downcase}('/') { '#{verb}' }"
23
- class_eval "#{verb.downcase}('/route.json') { '#{verb} /route.json' }"
24
- class_eval "#{verb.downcase}('/route/:id.json') { request.params[:id] }"
25
- class_eval "#{verb.downcase}('/:name') { request.params[:name] }"
26
- end
27
- end
28
- end
29
-
30
- Hobby::Verbs.each do |verb|
31
- describe 'when the request matches a route' do
32
- it "matches #{verb} ''" do
33
- send verb.downcase, ''
34
- assert last_response.ok?
35
- assert_equal verb, last_response.body
36
- end
37
-
38
- it 'matches #{verb} /' do
39
- send verb.downcase, '/'
40
- assert last_response.ok?
41
- assert_equal verb, last_response.body
42
- end
43
-
44
- it 'matches #{verb} /route.json' do
45
- send verb.downcase, '/route.json'
46
- assert last_response.ok?
47
- assert_equal "#{verb} /route.json", last_response.body
48
- end
49
-
50
- it 'matches #{verb} /route/:id.json' do
51
- send verb.downcase, '/route/1.json'
52
- assert last_response.ok?
53
- assert_equal '1', last_response.body
54
- end
55
-
56
- it 'matches #{verb} /:name' do
57
- send verb.downcase, '/hobbit'
58
- assert last_response.ok?
59
- assert_equal 'hobbit', last_response.body
60
-
61
- send verb.downcase, '/hello-hobbit'
62
- assert last_response.ok?
63
- assert_equal 'hello-hobbit', last_response.body
64
- end
65
- end
66
-
67
- describe 'when the request not matches a route' do
68
- it 'responds with 404 status code' do
69
- send verb.downcase, '/not/found'
70
- assert last_response.not_found?
71
- assert_equal '', last_response.body
72
- end
73
- end
74
- end
75
- end
76
-
77
- describe :map_app do
78
- before do
79
- mock_app do
80
- map '/map' do
81
- run Proc.new { |env| [200, {}, ['from map']] }
82
- end
83
-
84
- get('/') { 'hello world' }
85
- end
86
- end
87
-
88
- it 'mounts an application to the rack stack' do
89
- get '/map'
90
- assert_equal 'from map', last_response.body
91
- end
92
- end
93
-
94
- describe :use_app do
95
- before do
96
- mock_app do
97
- middleware = Class.new do
98
- def initialize(app = nil)
99
- @app = app
100
- end
101
-
102
- def call(env)
103
- request = Rack::Request.new(env)
104
- @app.call(env) unless request.path_info == '/use'
105
- [200, {}, 'from use']
106
- end
107
- end
108
-
109
- use middleware
110
-
111
- get('/') { 'hello world' }
112
- end
113
- end
114
-
115
- it 'adds a middleware to the rack stack' do
116
- get '/use'
117
- assert_equal 'from use', last_response.body
118
- end
119
- end
120
-
121
- describe :halt_app do
122
- before do
123
- mock_app do
124
- get '/halt' do
125
- response.status = 501
126
- halt response.finish
127
- end
128
-
129
- get '/halt_finished' do
130
- halt [404, {}, ['Not found']]
131
- end
132
- end
133
- end
134
-
135
- it 'halts the execution with a response' do
136
- get '/halt'
137
- assert { last_response.status == 501 }
138
- end
139
-
140
- it 'halts the execution with a finished response' do
141
- get '/halt_finished'
142
- assert { last_response.status == 404 }
143
- end
144
- end
145
-
146
- describe :router_app do
147
- before do
148
- mock_app do
149
- router do
150
- Class.new do
151
- def add_route(*)
152
- end
153
-
154
- def route_for _request
155
- Proc.new { 'for any route' }
156
- end
157
- end.new
158
- end
159
- end
160
- end
161
-
162
- it 'returns for any route' do
163
- get '/'
164
- assert { last_response.body == 'for any route' }
165
-
166
- get '/some-other-route'
167
- assert { last_response.body == 'for any route' }
168
- end
169
- end
170
-
171
- describe :custom_members do
172
- before do
173
- mock_app do
174
- builder { Rack::Builder.new }
175
- Request = Rack::Request
176
- Response = Rack::Response
177
-
178
- get '/' do
179
- 'it works'
180
- end
181
- end
182
- end
183
-
184
- it 'works' do
185
- get '/'
186
- assert { last_response.body == 'it works' }
187
- end
188
- end
189
- end
data/test/test_router.rb DELETED
@@ -1,65 +0,0 @@
1
- require_relative 'helper'
2
-
3
- def request_to path, request_method: 'GET'
4
- Hobby::Request.new Rack::MockRequest.env_for "http://example.com:8080/#{path}", method: request_method
5
- end
6
-
7
- describe Hobby::Router do
8
- before do
9
- @router = Hobby::Router.new
10
- @route = -> { :wrapped }
11
- end
12
-
13
- it 'works' do
14
- @router.add_route 'GET', '/ololo', &@route
15
-
16
- route = @router.route_for request_to 'ololo'
17
- assert { route.to_proc.call == :wrapped }
18
-
19
- route = @router.route_for request_to 'ololo2'
20
- assert { route.nil? }
21
-
22
- route = @router.route_for request_to 'ololo', request_method: 'POST'
23
- assert { route.nil? }
24
- end
25
-
26
- it 'with .' do
27
- @router.add_route 'GET', '/route.json', &@route
28
-
29
- route = @router.route_for request_to 'route.json'
30
- assert { route.to_proc.call == :wrapped }
31
- end
32
-
33
- it 'with -' do
34
- @router.add_route 'GET', '/hello-world', &@route
35
-
36
- route = @router.route_for request_to 'hello-world'
37
- assert { route.to_proc.call == :wrapped }
38
- end
39
-
40
- it 'with params' do
41
- @router
42
- .add_route 'GET', '/hello/:name' do :first end
43
- .add_route 'GET', '/say/:something/to/:someone' do :second end
44
-
45
- request = request_to 'hello/ololo'
46
- route = @router.route_for request
47
- assert { route.to_proc.call == :first }
48
- assert { request.params[:name] == 'ololo'}
49
-
50
- request = request_to 'say/nothing/to/no_one'
51
- route = @router.route_for request
52
- assert { route.to_proc.call == :second }
53
- assert { request.params[:something] == 'nothing'}
54
- assert { request.params[:someone] == 'no_one'}
55
- end
56
-
57
- it 'with . and params' do
58
- @router.add_route 'GET', '/route/:id.json', &@route
59
-
60
- request = request_to 'route/42.json'
61
- route = @router.route_for request
62
- assert { route.to_proc.call == :wrapped }
63
- assert { request.params[:id] == '42' }
64
- end
65
- end