busker 0.4.1 → 0.6.0

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: 479d0314b2b96aa30c911d939ad80b2bc8b1df76
4
- data.tar.gz: 7d9aba7ffc423e2c566a7dfab46abcebad2c8925
3
+ metadata.gz: 356d2a430d4617987f16ae6e79c6f1647e9c0621
4
+ data.tar.gz: babff57610dcad7cb004c785b2b5b701482bc30b
5
5
  SHA512:
6
- metadata.gz: 78b54d4eff9e762c78a661791b9539348ec0f4cd44dee41800531881ed78ddd9d9546f7eb4d8f12fd48c41d8b7a2d57fe6f9ff7bcc779c316252b78460378f10
7
- data.tar.gz: 86396ccdde4f1dc4f304842c439a70b2b08292aab40275eb9bbd71005cf7aede2e0bbd52ae87cf88e721db38190176f8bda082a8245b1e76f2a58c06b97a8dd5
6
+ metadata.gz: 38305ab76fc8c86aaa4f6fadb079462ce31c75301ec3637f8ff25ae2c1094f49da5717c7d33c249c3efbef277d0f80ba7d83677fcbc73a15f57ed3732a95bab2
7
+ data.tar.gz: ec4059f506ea03c897490ed6e4dc13c8d18b06c1cc0ca4eab7dc5c4efa209e7eede3a4efc63928872e3de134e317eb832ff559500b287dfb9a6496489b70023e
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --warnings
3
+ --require spec_helper
data/README.md CHANGED
@@ -1,10 +1,18 @@
1
- # Busker
1
+ # Busker :walking::notes:
2
2
 
3
3
  An extremely simple web framework. It's called Busker as a reference to
4
4
  Sinatra. It mimics Sinatra in some aspects while still trying to stay a
5
5
  true wanderer of the streets.
6
6
 
7
- ## Installation
7
+ ## Design principles :page_with_curl:
8
+
9
+ * Small code base that is easily understandable, hackable and embeddable
10
+ * No dependencies except what is in the Ruby Standard Lib
11
+ * Backward compatibility to older Ruby versions
12
+ * Ease of use / Some minor resemblance to Sinatra, hence the name
13
+ * It's not meant as a complete web framework but concentrates on the basics
14
+
15
+ ## Installation :floppy_disk:
8
16
 
9
17
  Add this line to your application's Gemfile:
10
18
 
@@ -18,73 +26,97 @@ Or install it yourself as:
18
26
 
19
27
  $ gem install busker
20
28
 
21
- ## Usage
22
-
23
- require 'busker'
24
-
25
- Busker::Busker.new do
26
- # minimal route definition
27
- route '/' do
28
- "Busker version: #{Busker::VERSION}"
29
- end
30
-
31
- # respond to multiple HTTP methods, overwrite response content_type
32
- route '/info', [:GET, :POST, :PUT, :DELETE] do |params, request, response|
33
- response.content_type = 'text/plain'
34
- request.inspect
35
- end
36
-
37
- # usage of URL params, render template with variable
38
- route '/template', :GET do |params|
39
- @title = params[:title] || 'no title'
40
- if params[:external]
41
- render './template.erb'
42
- else
43
- render :template
44
- end
45
- end
46
-
47
- # usage of dynamic route params
48
- route '/item/:id' do |params|
49
- "requested item with id: #{params[:id]}"
50
- end
51
-
52
- # list all defined routes
53
- route '/routes' do |params, request, response|
54
- response.content_type = 'text/plain'
55
- @_[:routes].keys.map{|e| e.join("\n")}.join("\n\n")
56
- end
57
- end.start
58
-
59
- __END__
60
- @@ template
61
- <h1><%= @title %></h1>
62
-
63
- ## Design principles
64
-
65
- * Small code base that is easily to understandable and hackable
66
- * Such a tiny code base that you can just copy it into your one-file-project without the need to require a Gem
67
- * No dependencies except what is in the Ruby Standard Lib
68
- * Backward compatibility to older Ruby versions
69
- * Some minor resemblance to Sinatra
70
- * Ease of use
71
- * It's not meant as a complete web framework like Rails but concentrates on the basics
29
+ Or copy the code into your project ... it's tiny!
30
+
31
+ ## Usage :boom:
32
+
33
+ ```ruby
34
+ require 'busker'
35
+
36
+ Busker::Busker.new do
37
+
38
+ # minimal route definition
39
+ route '/' do
40
+ "Busker version: #{Busker::VERSION}"
41
+ end
42
+
43
+ # respond to multiple HTTP methods, overwrite response content_type
44
+ route '/info', [:GET, :POST, :PUT, :DELETE] do |params, request, response|
45
+ response.content_type = 'text/plain'
46
+ request.inspect
47
+ end
48
+
49
+ # usage of URL params, render template with variable
50
+ route '/template', :GET do |params|
51
+ @title = params[:title] || 'no title'
52
+ if params[:external]
53
+ render './template.erb'
54
+ else
55
+ render :template
56
+ end
57
+ end
58
+
59
+ # usage of dynamic route params
60
+ route '/item/:id' do |params|
61
+ "requested item with id: #{params[:id]}"
62
+ end
63
+
64
+ # list all defined routes
65
+ route '/routes', :GET do |params, request, response|
66
+ response.content_type = 'text/plain'
67
+ @_[:routes].keys.map{|k| "#{k[:methods].join('/')} #{k[:path]}"}.join("\n")
68
+ end
69
+
70
+ # implicit route definitions
71
+ route :implicit
72
+ route '/implicit/something'
73
+
74
+ end.start # notice the call to start
75
+
76
+ # inline templates like in Sinatra
77
+ __END__
78
+ @@ template
79
+ <h1><%= @title %></h1>
80
+
81
+ @@ /implicit
82
+ <h1><%= @params.inspect %></h1>
83
+
84
+ @@ /implicit/something
85
+ <h1><%= @request.inspect %></h1>
86
+
87
+ ```
88
+
89
+ ## Questions :grey_question:
90
+
91
+ ### Why not use Sinatra?
92
+
93
+ Sinatra is about 2000 lines of code (nothing you would directly, as in copy the code, embed in your single-file project) while Busker is less than 50 lines of code. Plus Sinatra depends on Rack and Tilt. Both external Gems while one of Buskers design principles is to only rely on modules that are within the Ruby Standard Library.
94
+
95
+ This makes it literally small and deployable enough to be used in a tiny single file project. This is great for toy projects, educational purposes, payloads, embedded projects ...
96
+
97
+ But that all being said, you should probably use Rails or Sinatra for your project.
98
+
99
+ ### When shouldn't I use Busker?
100
+
101
+ **I wouldn't consider Busker to be "production ready" by any means. (WEBrick is not the smartest choice for production environments! [Read here why](http://www.madebymarket.com/blog/dev/ruby-web-benchmark-report.html))** It's something to play around and have fun with. I haven't made exhaustive benchmarks or in depths security checks. And I would love to get honest, constructive opinions (considering the design principles).
72
102
 
73
- ## TODO / Ideas
103
+ ## TODO / Ideas :bulb:
74
104
 
105
+ * More tests! (especially integration tests with Capybara)
75
106
  * Improve render method, allow yield etc
76
107
  * Improve error handling, honor production/development environment?
77
- * Tests? ;)
78
108
  * Auto reload?
109
+ * A fork that doesn't need WEBrick?
79
110
  * Anything cool that doesn't break the design principles ...
80
111
 
81
- ## Contributing
112
+ ## Contributing :construction:
82
113
 
83
114
  1. Fork it
84
115
  2. Create your feature branch (`git checkout -b my-new-feature`)
85
116
  3. Commit your changes (`git commit -am 'Add some feature'`)
86
- 4. Push to the branch (`git push origin my-new-feature`)
87
- 5. Create a new Pull Request
117
+ 4. Don't forget to write- and run tests for your new feature (run rspec)!
118
+ 5. Push to the branch (`git push origin my-new-feature`)
119
+ 6. Create a new Pull Request
88
120
 
89
121
  Or just use GitHubs on page editing ...
90
122
  it will do all of the above for you and is reasonable given the size of the source.
data/Rakefile CHANGED
@@ -1,2 +1 @@
1
1
  require "bundler/gem_tasks"
2
-
data/busker.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["pachacamac@users.noreply.github.com"]
11
11
  spec.summary = %q{An extremely simple web framework}
12
12
  spec.description = %q{An extremely simple web framework. It mimics Sinatra in some aspects while still trying to stay a true wanderer of the streets.}
13
- spec.homepage = ""
13
+ spec.homepage = "https://github.com/pachacamac/busker"
14
14
  spec.license = "MIT"
15
15
  spec.files = `git ls-files -z`.split("\x0")
16
16
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -19,4 +19,5 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.add_development_dependency "bundler", "~> 1.6"
21
21
  spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rspec"
22
23
  end
data/lib/busker.rb CHANGED
@@ -6,7 +6,7 @@ require 'erb'
6
6
  module Busker
7
7
  class Busker
8
8
  def initialize(opts={}, &block)
9
- @_ = {:routes => {}}
9
+ @_ = {:routes => {}} #using @_ to store instance variables so they're less likely to get overwritten unintentionally while still allowing easy access when needed
10
10
  instance_eval(&block) if block_given?
11
11
  opts[:Port] ||= opts.delete(:port) || 8080
12
12
  opts[:DocumentRoot] ||= opts.delete(:document_root) || File.expand_path('./')
@@ -14,10 +14,10 @@ module Busker
14
14
  @_[:server].mount_proc '' do |rq, rs| #request, response
15
15
  begin
16
16
  rs.status, rs.content_type, method = nil, 'text/html', rq.request_method.tr('-', '_').upcase
17
- route, handler = @_[:routes].find{|k,v| k.first.include?(method) && k.last.match(rq.path_info)}
17
+ route, handler = @_[:routes].find{|k,v| k[:methods].include?(method) && k[:matcher].match(rq.path_info)}
18
18
  params = Hash[ CGI::parse(rq.query_string||'').map{|k,v| [k.to_sym,v[0]]} + #url params
19
19
  rq.query.map{|k,v| [k.to_sym, v]} + #query params
20
- ($~ ? $~.names.map(&:to_sym).zip($~.captures) : []) ] #dynamic route params
20
+ ($~ ? $~.names.map(&:to_sym).zip($~.captures) : []) ] #dynamic route params. $~ is the info of the last match (see line 17)
21
21
  rs.status, rs.body = route ? [rs.status || 200, handler[:block].call(params, rq, rs)] : [404, 'not found']
22
22
  rescue => e
23
23
  @_[:server].logger.error "#{e.message}\n#{e.backtrace.map{|line| "\t#{line}"}.join("\n")}"
@@ -27,17 +27,20 @@ module Busker
27
27
  end
28
28
 
29
29
  def route(path, methods = ['GET'], opts={}, &block)
30
- methods = (methods.is_a?(Array) ? methods : [methods]).map{|e| e.to_s.tr('-', '_').upcase}
30
+ path = "/#{path}" unless path[0] == '/'
31
+ methods = Array(methods).map{|e| e.to_s.tr('-', '_').upcase}
31
32
  matcher = Regexp.new("\\A#{path.gsub(/(:\w+)/){|m| "(?<#{$1[1..-1]}>\\w+)"}}\\Z")
32
- @_[:routes][[methods, path, matcher]] = {:opts => opts, :block => block}
33
+ block ||= proc{|pa,rq,rs| @params,@request,@response = pa,rq,rs; render path}
34
+ @_[:routes][{:methods => methods, :path => path, :matcher => matcher}] = {:opts => opts, :block => block}
33
35
  end
34
36
 
35
37
  def render(name)
36
38
  @_[:templates] ||= (Hash[DATA.read.split(/^@@\s*(.*\S)\s*$/)[1..-1].map(&:strip).each_slice(2).to_a] rescue {})
37
- ERB.new(@_[:templates][name.to_s] || File.read(name)).result(binding)
39
+ ERB.new(@_[:templates][name.to_s] || File.read(name.to_s)).result(binding)
38
40
  end
39
41
 
40
42
  def start
43
+ trap('INT'){@_[:server].stop}
41
44
  @_[:server].start ensure @_[:server].shutdown
42
45
  end
43
46
  end
@@ -1,3 +1,3 @@
1
1
  module Busker
2
- VERSION = "0.4.1"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'busker'
3
+
4
+ describe Busker do
5
+ it 'has a version' do
6
+ expect(Busker::VERSION).to match(/\d+\.\d+\.\d+/)
7
+ end
8
+ end
9
+
10
+ describe Busker::Busker do
11
+ it 'can define a route via the initialize block' do
12
+ busker = Busker::Busker.new do
13
+ route '/path', :POST do
14
+ 'trallala'
15
+ end
16
+ end
17
+ routes = busker.instance_variable_get('@_')[:routes]
18
+ expect(routes).to be_a Hash
19
+ expect(routes.size).to eql 1
20
+ key, value = routes.first
21
+ expect(key).to be_a Hash
22
+ expect(key[:methods]).to eql ['POST']
23
+ expect(key[:path]).to eql '/path'
24
+ expect(key[:matcher]).to be_a Regexp
25
+ expect(value).to be_a Hash
26
+ expect(value[:opts]).to be_a Hash
27
+ expect(value[:block]).to be_a Proc
28
+ end
29
+
30
+ # TODO: way more tests, including integration tests with capybara
31
+ end
@@ -0,0 +1,78 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
4
+ # file to always be loaded, without a need to explicitly require it in any files.
5
+ #
6
+ # Given that it is always loaded, you are encouraged to keep this file as
7
+ # light-weight as possible. Requiring heavyweight dependencies from this file
8
+ # will add to the boot time of your test suite on EVERY test run, even for an
9
+ # individual file that may not need all of that loaded. Instead, make a
10
+ # separate helper file that requires this one and then use it only in the specs
11
+ # that actually need it.
12
+ #
13
+ # The `.rspec` file also contains a few flags that are not defaults but that
14
+ # users commonly want.
15
+ #
16
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
17
+ RSpec.configure do |config|
18
+ # The settings below are suggested to provide a good initial experience
19
+ # with RSpec, but feel free to customize to your heart's content.
20
+ =begin
21
+ # These two settings work together to allow you to limit a spec run
22
+ # to individual examples or groups you care about by tagging them with
23
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
24
+ # get run.
25
+ config.filter_run :focus
26
+ config.run_all_when_everything_filtered = true
27
+
28
+ # Many RSpec users commonly either run the entire suite or an individual
29
+ # file, and it's useful to allow more verbose output when running an
30
+ # individual spec file.
31
+ if config.files_to_run.one?
32
+ # Use the documentation formatter for detailed output,
33
+ # unless a formatter has already been configured
34
+ # (e.g. via a command-line flag).
35
+ config.default_formatter = 'doc'
36
+ end
37
+
38
+ # Print the 10 slowest examples and example groups at the
39
+ # end of the spec run, to help surface which specs are running
40
+ # particularly slow.
41
+ config.profile_examples = 10
42
+
43
+ # Run specs in random order to surface order dependencies. If you find an
44
+ # order dependency and want to debug it, you can fix the order by providing
45
+ # the seed, which is printed after each run.
46
+ # --seed 1234
47
+ config.order = :random
48
+
49
+ # Seed global randomization in this process using the `--seed` CLI option.
50
+ # Setting this allows you to use `--seed` to deterministically reproduce
51
+ # test failures related to randomization by passing the same `--seed` value
52
+ # as the one that triggered the failure.
53
+ Kernel.srand config.seed
54
+
55
+ # rspec-expectations config goes here. You can use an alternate
56
+ # assertion/expectation library such as wrong or the stdlib/minitest
57
+ # assertions if you prefer.
58
+ config.expect_with :rspec do |expectations|
59
+ # Enable only the newer, non-monkey-patching expect syntax.
60
+ # For more details, see:
61
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
62
+ expectations.syntax = :expect
63
+ end
64
+
65
+ # rspec-mocks config goes here. You can use an alternate test double
66
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
67
+ config.mock_with :rspec do |mocks|
68
+ # Enable only the newer, non-monkey-patching expect syntax.
69
+ # For more details, see:
70
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
71
+ mocks.syntax = :expect
72
+
73
+ # Prevents you from mocking or stubbing a method that does not exist on
74
+ # a real object. This is generally recommended.
75
+ mocks.verify_partial_doubles = true
76
+ end
77
+ =end
78
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: busker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - pachacamac
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-11 00:00:00.000000000 Z
11
+ date: 2014-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: An extremely simple web framework. It mimics Sinatra in some aspects
42
56
  while still trying to stay a true wanderer of the streets.
43
57
  email:
@@ -47,6 +61,7 @@ extensions: []
47
61
  extra_rdoc_files: []
48
62
  files:
49
63
  - ".gitignore"
64
+ - ".rspec"
50
65
  - Gemfile
51
66
  - LICENSE.txt
52
67
  - README.md
@@ -54,7 +69,9 @@ files:
54
69
  - busker.gemspec
55
70
  - lib/busker.rb
56
71
  - lib/busker/version.rb
57
- homepage: ''
72
+ - spec/lib/busker_spec.rb
73
+ - spec/spec_helper.rb
74
+ homepage: https://github.com/pachacamac/busker
58
75
  licenses:
59
76
  - MIT
60
77
  metadata: {}
@@ -78,4 +95,6 @@ rubygems_version: 2.2.2
78
95
  signing_key:
79
96
  specification_version: 4
80
97
  summary: An extremely simple web framework
81
- test_files: []
98
+ test_files:
99
+ - spec/lib/busker_spec.rb
100
+ - spec/spec_helper.rb