sansom 0.0.2 → 0.0.3

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: 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