sansom 0.0.2 → 0.0.3

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: 7c54015af146ba89239c6199fa38f6d32674f274
4
- data.tar.gz: 01b09122f5014d586311449942d84962a51b1a89
3
+ metadata.gz: 83d66dba113385fce6c56f322029124339fd7b95
4
+ data.tar.gz: b8bd60af145d70fa86659611cbb68cfc7b406377
5
5
  SHA512:
6
- metadata.gz: 806566785d4903fb29413b9c4606f259b154b2f6dc946139e20341ed69a08385c533818bbd1a5eab8553c3622387a22e51261a910b309e0e22810c0eba4f6733
7
- data.tar.gz: 5805d9c95195d8b5b9ce80f20b0dbee5df425877f28ff63dba3f34dee3198969fd3ce4ee57282ec84e8f2c5f82aca291aa71be03fd8df5bc1aedb6542b4d3914
6
+ metadata.gz: 848745905809706be2a7fe194f017249053296ddd858b6f380425ed9d5c89bd92eab1049c9b33b4a00b7cf943d311d2ea6ffce33e1efb641dca4c26518495fda
7
+ data.tar.gz: 566b2bf914317d9c64df03cef8518be605d7b26835bf10602f0883ce960ec62ccc45072434d177acdebcb411c2e55f77a5f3ba2efc9ff719af9de46cdc5a436a
data/changelog.md ADDED
@@ -0,0 +1,30 @@
1
+ Changelog
2
+ =
3
+
4
+ 0.0.1
5
+
6
+ (yanked due to bad name in Gemfile)
7
+
8
+ 0.0.2
9
+
10
+ - Initial release
11
+
12
+ 0.0.3
13
+
14
+ - Wrote custom tree implementation called Pine to replace RubyTree
15
+ - Added `before` block
16
+
17
+ Here's an example
18
+
19
+ s = Sansom.new
20
+
21
+ s.before do |r|
22
+ # Caveat: routes are mapped before this block is called
23
+ # Code executed before mapped route
24
+ end
25
+
26
+ s.get "/" do |r|
27
+ [200, {}, ["Hello!"]]
28
+ end
29
+
30
+ s.start 2000
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/sansom"
4
+
5
+ s = Sansom.new
6
+
7
+ s.before do |r|
8
+ puts "(#{s.class.to_s}) #{r.request_method.upcase} #{r.path_info}"
9
+ [200, {}, ["Hijacked by before!"]] if Random.new.rand(2) == 1
10
+ end
11
+
12
+ s.get "/" do |r|
13
+ [200, { "Content-Type" => "text/plain"}, ["root"]]
14
+ end
15
+
16
+ s.get "/something" do |r|
17
+ [200, { "Content-Type" => "text/plain" }, ["something"]]
18
+ end
19
+
20
+ s.start 2000
data/examples/generic.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "json"
4
- require "sansom"
4
+ #require "sansom"
5
+ require_relative "../lib/sansom"
5
6
 
6
7
  class Sansom
7
8
  def food_response r
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Path routing tree
4
+
5
+ # Custom tree implementation for path routing
6
+
7
+ # Custom features:
8
+ # 1. Trimming: Limit a node to a single element
9
+
10
+ module Pine
11
+ class Node
12
+ attr_reader :name
13
+ attr_accessor :content
14
+ attr_accessor :parent
15
+
16
+ def initialize name, content=Content.new
17
+ @name = name
18
+ @content = content
19
+ @children = {}
20
+ @parent = nil
21
+ @trimmed = false
22
+ end
23
+
24
+ # returns a node for chaining
25
+ def <<(node)
26
+ if trimmed?
27
+ # Add to first child
28
+ children.first << node
29
+ else
30
+ node.parent = self
31
+ @children[node.name] = node
32
+ node
33
+ end
34
+ end
35
+
36
+ def create_if_necessary name
37
+ unless @children.keys.include? name
38
+ child = self.class.new name
39
+ child.parent = self
40
+ @children[name] = child
41
+ end
42
+ @children[name]
43
+ end
44
+
45
+ def root
46
+ n = self
47
+ n = n.parent while !n.root?
48
+ n
49
+ end
50
+
51
+ def children
52
+ @children.values
53
+ end
54
+
55
+ def trim(node)
56
+ @trimmed = true
57
+ @children.clear
58
+ @children[node.name] = node
59
+ self
60
+ end
61
+
62
+ def []=(k,v)
63
+ self << Node.new(k, v)
64
+ end
65
+
66
+ def [](k)
67
+ @children[k]
68
+ end
69
+
70
+ def root?
71
+ @parent.nil?
72
+ end
73
+
74
+ def leaf?
75
+ @children.count == 0
76
+ end
77
+
78
+ def trimmed?
79
+ @trimmed
80
+ end
81
+
82
+ def inspect(level=0)
83
+ if root?
84
+ print "*"
85
+ else
86
+ print "|" unless parent.parent.children.last == parent rescue false
87
+ print(' ' * level * 4)
88
+ print(parent.children.last == self ? "+" : "|")
89
+ print "---"
90
+ print(leaf? ? ">" : "+")
91
+ end
92
+
93
+ puts " #{name} #{content.map rescue "fuck"}"
94
+
95
+ children.each { |child| child.inspect(level + 1) if child } # Child might be 'nil'
96
+ end
97
+ end
98
+
99
+ class Content
100
+ attr_accessor :items
101
+ attr_accessor :map
102
+
103
+ def initialize
104
+ @items = []
105
+ @map = {}
106
+ end
107
+
108
+ def []=(k,v)
109
+ @items << v if k == :map
110
+ @map[k] = v unless k == :map
111
+ end
112
+
113
+ def [](k)
114
+ @items[k] if Numeric === k
115
+ @map[k] unless Numeric === k
116
+ end
117
+ end
118
+ end
data/lib/sansom.rb CHANGED
@@ -1,73 +1,55 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "rack"
4
- require "tree" # rubytree
4
+ require_relative "./sansom/pine"
5
5
 
6
6
  module Sansomable
7
- class TreeContent
8
- attr_accessor :items
9
- def initialize
10
- @items = []
11
- @map = {}
12
- end
13
-
14
- def []=(k,v)
15
- @items << v if k == :map
16
- @map[k] = v unless k == :map
17
- end
18
-
19
- def [](k)
20
- @items[k] if Numeric === k
21
- @map[k] unless Numeric === k
22
- end
23
- end
24
-
25
7
  InvalidRouteError = Class.new StandardError
26
- NoRoutesError = Class.new StandardError
27
- InclusionError = Class.new StandardError
28
8
 
29
- HTTP_VERBS = ["GET","HEAD","POST","PUT","DELETE","PATCH","OPTIONS"].freeze
9
+ HTTP_VERBS = [:get,:head, :post, :put, :delete, :patch, :options].freeze
30
10
  HANDLERS = ["puma", "unicorn", "thin", "webrick"].freeze
31
11
  NOT_FOUND = [404, {"Content-Type" => "text/plain"}, ["Not found."]].freeze
32
12
 
33
13
  def tree
34
14
  @tree ||= nil
35
15
  if @tree.nil?
36
- @tree = Tree::TreeNode.new("ROOT", "ROOT")
16
+ @tree = Pine::Node.new("ROOT", nil)
37
17
  template if respond_to? :template
38
18
  end
39
19
  @tree
40
20
  end
21
+
22
+ def before_block
23
+ @before_block ||= nil
24
+ end
41
25
 
42
- def match http_method, path
26
+ def match verb, path
43
27
  components = s_parse_path(path)
44
28
  matched_components = []
29
+ matched_parameters = {}
45
30
 
46
- walk = components.inject(tree) do |node, component|
47
- child = node[component]
48
-
49
- if child.nil?
31
+ walk = components.inject(tree) do |node, component|
32
+ if node.leaf?
50
33
  node
51
34
  else
52
35
  matched_components << component unless component == "/"
53
- child
36
+ node[component]
54
37
  end
55
38
  end
56
-
57
- tc = walk.content
58
-
59
- return nil if tc == "ROOT"
60
39
 
40
+ return nil if walk.root?
41
+
42
+ c = walk.content
61
43
  matched_path = "/" + matched_components.join("/")
62
44
 
63
- match = tc[http_method] # Check for route
64
- match ||= tc.items.select(&method(:sansom?)).reject { |item| item.match(http_method, s_truncate_path(path, matched_path)).nil? }.first rescue nil # Check subsansoms
65
- match ||= tc.items.reject(&method(:sansom?)).first rescue nil # Check for mounted rack apps
45
+ match = c[verb.downcase.to_sym] # Check for route
46
+ match ||= c.items.select(&method(:sansom?)).reject { |item| item.match(verb, path.sub(matched_path, "")).nil? }.first rescue nil # Check subsansoms
47
+ match ||= c.items.reject(&method(:sansom?)).first rescue nil # Check for mounted rack apps
66
48
  [match, matched_path]
67
49
  end
68
50
 
69
51
  def call env
70
- return NOT_FOUND if tree.children.empty?
52
+ return NOT_FOUND if tree.leaf?
71
53
 
72
54
  r = Rack::Request.new env
73
55
 
@@ -76,12 +58,20 @@ module Sansomable
76
58
 
77
59
  if item.nil?
78
60
  NOT_FOUND
79
- elsif Proc === item
80
- item.call r
81
- elsif sansom? item
82
- item.call(env.dup.merge({ "PATH_INFO" => s_truncate_path(r.path_info, m.last) }))
83
61
  else
84
- raise InvalidRouteError, "Invalid route handler, it must be a block (proc/lambda) or a subclass of Sansom."
62
+ if before_block
63
+ res = before_block.call r
64
+ return res if res[0].is_a?(Numeric) && res[1].is_a?(Hash) && res[2].respond_to?(:each) rescue false
65
+ end
66
+
67
+ if item.is_a? Proc
68
+ item.call r
69
+ elsif sansom? item
70
+ r.path_info.sub! m[1], ""
71
+ item.call(r.env)
72
+ else
73
+ raise InvalidRouteError, "Invalid route handler, it must be a block (proc/lambda) or a subclass of Sansom."
74
+ end
85
75
  end
86
76
  end
87
77
 
@@ -90,49 +80,31 @@ module Sansomable
90
80
  Rack::Handler.pick(HANDLERS).run self, :Port => port
91
81
  end
92
82
 
83
+ def before(&block)
84
+ @before_block = block
85
+ end
86
+
93
87
  def method_missing(meth, *args, &block)
94
- _args = args.dup.push block
95
- super unless _args.count >= 2
96
-
97
- path = _args[0].dup
98
- item = _args[1].dup
99
-
88
+ path, item = *args.dup.push(block)
89
+ return super unless path && item
100
90
  return super if item == self
91
+ return super unless HTTP_VERBS.include?(meth) || meth == :map
101
92
 
102
- verb = meth.to_s.strip.upcase
103
- return super unless HTTP_VERBS.include?(verb) || meth == :map
104
- verb = :map if meth == :map
105
-
106
- components = s_parse_path path
107
- components.each_with_index.inject(tree) do |node,(component, idx)|
108
- child = node[component]
109
-
110
- if child.nil?
111
- newvalue = Tree::TreeNode.new(component, TreeContent.new)
112
- node << newvalue
113
- child = newvalue
114
- end
115
-
116
- child.content[verb] = item if idx == components.count-1
117
- child
118
- end
93
+ n = s_parse_path(path).inject(tree) { |node, comp| node.create_if_necessary comp }
94
+ n.content[meth] = item
119
95
  end
120
96
 
121
97
  private
122
98
 
123
99
  def sansom? obj
124
- return true if Sansom === obj
100
+ return true if obj.is_a? Sansom
125
101
  return true if obj.class.included_modules.include? Sansomable
126
102
  false
127
103
  end
128
-
104
+
129
105
  def s_parse_path path
130
106
  path.split("/").reject(&:empty?).unshift("/")
131
107
  end
132
-
133
- def s_truncate_path truncated, truncator
134
- "/" + s_parse_path(truncated)[s_parse_path(truncator).count..-1].join("/")
135
- end
136
108
  end
137
109
 
138
110
  Sansom = Class.new Object
data/sansom.gemspec CHANGED
@@ -1,23 +1,21 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'sansom/version'
5
4
 
6
- Gem::Specification.new do |spec|
7
- spec.name = "sansom"
8
- spec.version = Sansom::VERSION
9
- spec.authors = ["Nathaniel Symer"]
10
- spec.email = ["nate@natesymer.com"]
11
- spec.summary = %q{Flexible, versatile, light web framework named after Sansom street in Philly.}
12
- spec.description = %q{Flexible, versatile, light web framework named after Sansom street in Philly. It's under 140 lines of code & and it's lightning fast.}
13
- spec.homepage = "http://github.com/fhsjaagshs/sansom"
14
- spec.license = "MIT"
5
+ Gem::Specification.new do |s|
6
+ s.name = "sansom"
7
+ s.version = "0.0.3"
8
+ s.authors = ["Nathaniel Symer"]
9
+ s.email = ["nate@natesymer.com"]
10
+ s.summary = "Flexible, versatile, light web framework named after Sansom street in Philly."
11
+ s.description = s.summary + "It's under 140 lines of code & and it's lightning fast. It uses tree-based route resolution."
12
+ s.homepage = "http://github.com/fhsjaagshs/sansom"
13
+ s.license = "MIT"
15
14
 
16
- spec.files = `git ls-files -z`.split("\x0")
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
15
+ s.files = `git ls-files -z`.split("\x0")
16
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
+ s.require_paths = ["lib"]
20
19
 
21
- spec.add_development_dependency "bundler", "~> 1.6"
22
- spec.add_dependency "rubytree", "~> 0.9"
20
+ s.add_development_dependency "bundler", "~> 1.6"
23
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sansom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathaniel Symer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-29 00:00:00.000000000 Z
11
+ date: 2014-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,22 +24,9 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.6'
27
- - !ruby/object:Gem::Dependency
28
- name: rubytree
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '0.9'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '0.9'
41
27
  description: Flexible, versatile, light web framework named after Sansom street in
42
- Philly. It's under 140 lines of code & and it's lightning fast.
28
+ Philly.It's under 140 lines of code & and it's lightning fast. It uses tree-based
29
+ route resolution.
43
30
  email:
44
31
  - nate@natesymer.com
45
32
  executables: []
@@ -50,10 +37,12 @@ files:
50
37
  - Gemfile
51
38
  - LICENSE.txt
52
39
  - README.md
40
+ - changelog.md
41
+ - examples/before.rb
53
42
  - examples/generic.rb
54
43
  - examples/mixin.rb
55
44
  - lib/sansom.rb
56
- - lib/sansom/version.rb
45
+ - lib/sansom/pine.rb
57
46
  - sansom.gemspec
58
47
  homepage: http://github.com/fhsjaagshs/sansom
59
48
  licenses:
@@ -1,3 +0,0 @@
1
- module Sansom
2
- VERSION = "0.0.2"
3
- end