sansom 0.0.7 → 0.1.0

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: d1548d457d044bae13692b07bcb7a8374212be88
4
- data.tar.gz: 13e2ea4214d1b6a3c5b7c2c05421776f20dd9c92
3
+ metadata.gz: 9fe8ba21c0cab848b10f8484f8f38a0454d2f549
4
+ data.tar.gz: dccfd78c121e2b6f6bc5c01f42bce52f8809ea93
5
5
  SHA512:
6
- metadata.gz: e097de2bf1ea1b34754d9fde63983bc374d72e36a9cb446d275302824b1fc04183f1282b944add46b364ce1b5c7241520ce388eb53a4c09b702886748ce8a51e
7
- data.tar.gz: 13503646c81f33fb6ad3cb9004859fa3bd9036781ed5ac7a1b05c5797d0777303575d578b7231353e99803246736ff49ae833ba9c506d053d717b869772dc002
6
+ metadata.gz: 773fded808375146ea57bf266e68feb8ad2c27ee584590e568d98d9517401f24b07a52f6f8dabab5da0e34114617fcce3b610a5683a77c02c17a10f33b59d93b
7
+ data.tar.gz: f004a23139c2dd2b1664868507815e1f149064f0511d35a5804efe818f16eabbb1e199d7afd90aa24f9a4162c090891200d24ff4cb60499a1edda90dea3bdc86
data/README.md CHANGED
@@ -6,14 +6,22 @@ Scientific, philosophical, abstract web 'picowork' named after Sansom street in
6
6
  Philosophy
7
7
  -
8
8
 
9
- *A piece of software should not limit you to one way of thinking.*
9
+ ***A piece of software should not limit you to one way of thinking.***
10
10
 
11
11
  You can write a `Sansomable` for each logical unit of your API, but you also don't have to.
12
12
 
13
- You can also mount existing Rails/Sinatra apps in your `Sansomable`. But you also don't have to.
13
+ You can also mount existing Rails/Sinatra/Rack apps in your `Sansomable`. But you also don't have to.
14
14
 
15
15
  You can write one `Sansomable` for your entire API.
16
16
 
17
+ Fuck it.
18
+
19
+ ***A piece of software should not be a magic box.***
20
+
21
+ A web framework is, however simplistically, a tool to connect code to a URL's path.
22
+
23
+ A web framework doesn't provide an ORM, template rendering, nor change how ruby works to the point where you're not writing Ruby code but instead `Rails` or `Sinatra` code.
24
+
17
25
  Installation
18
26
  -
19
27
 
@@ -160,7 +168,7 @@ Notes
160
168
  -
161
169
 
162
170
  - `Sansom` does not pollute _any_ `Object` methods, including `initialize`
163
- - `Sansom` is under **190** lines of code at the time of writing. This includes
171
+ - `Sansom` is under **250** lines of code at the time of writing. This includes
164
172
  * Rack conformity & the DSL (`sansom.rb`)
165
173
  * Custom tree-based routing (`pine.rb`)
166
174
 
@@ -46,4 +46,10 @@ Here's an example
46
46
  0.0.7
47
47
 
48
48
  - Fixed bug where a wilcard path component would be ignored if it came last in the URL
49
- - Fixed a bug where async responses would be marked as bad by the fastlinter.
49
+ - Fixed a bug where async responses would be marked as bad by the fastlinter.
50
+
51
+ 0.1.0
52
+
53
+ - PUBLIC RELEASE!
54
+ - After block added
55
+ - Improved routing behavior & speed
@@ -4,7 +4,6 @@ require "rack"
4
4
 
5
5
  module Rack
6
6
  class Fastlint
7
- LintError = Class.new StandardError
8
7
  def self.response res
9
8
  return false unless res.kind_of?(Array) && res.count == 3
10
9
 
@@ -21,15 +20,15 @@ module Rack
21
20
  begin
22
21
  headers.each { |k,v|
23
22
  next if key =~ /^rack\..+$/
24
- throw LintError unless k.kind_of? String
25
- throw LintError unless v.kind_of? String
26
- throw LintError if k.downcase == "status"
27
- throw LintError unless k !~ /[:\n]/
28
- throw LintError unless k !~ /[-_]\z/
29
- throw LintError unless k =~ /\A[a-zA-Z][a-zA-Z0-9_-]*\z/
23
+ throw StandardError unless k.kind_of? String
24
+ throw StandardError unless v.kind_of? String
25
+ throw StandardError if k.downcase == "status"
26
+ throw StandardError unless k !~ /[:\n]/
27
+ throw StandardError unless k !~ /[-_]\z/
28
+ throw StandardError unless k =~ /\A[a-zA-Z][a-zA-Z0-9_-]*\z/
30
29
  }
31
30
 
32
- body.each { |part| throw LintError unless part.kind_of? String }
31
+ body.each { |part| throw StandardError unless part.kind_of? String }
33
32
  rescue StandardError
34
33
  return false
35
34
  end
@@ -6,10 +6,10 @@ require_relative "./rack/fastlint.rb"
6
6
 
7
7
  module Sansomable
8
8
  InvalidRouteError = Class.new StandardError
9
- HTTP_VERBS = [:get,:head, :post, :put, :delete, :patch, :options].freeze
10
- HANDLERS = ["puma", "unicorn", "thin", "webrick"].freeze
9
+ HTTP_VERBS = [:get,:head, :post, :put, :delete, :patch, :options, :link, :unlink, :trace].freeze
10
+ RACK_HANDLERS = ["puma", "unicorn", "thin", "webrick"].freeze
11
11
  NOT_FOUND = [404, {}, ["Not found."]].freeze
12
-
12
+
13
13
  def tree
14
14
  if @tree.nil?
15
15
  @tree = Pine::Node.new "ROOT"
@@ -19,49 +19,56 @@ module Sansomable
19
19
  end
20
20
 
21
21
  def call env
22
- return NOT_FOUND if tree.leaf?
22
+ return NOT_FOUND if tree.leaf? && tree.root?
23
23
 
24
24
  r = Rack::Request.new env
25
+ m = tree.match r.path_info, r.request_method
26
+
27
+ return NOT_FOUND if m.nil?
25
28
 
26
- if @before_block
27
- res = @before_block.call r
28
- return res if Rack::Fastlint.response res
29
+ if @before_block && @before_block.arity == 1
30
+ bres = @before_block.call r
31
+ return bres if Rack::Fastlint.response bres
29
32
  end
30
33
 
31
- m = tree.match r.path_info, r.request_method
32
-
33
- if m.nil?
34
- NOT_FOUND
35
- else
36
- if m.url_params.count > 0
37
- q = r.params.merge(m.url_params)
38
- s = q.map { |p| p.join '=' }.join("&")
39
- r.env["rack.request.query_hash"] = q
40
- r.env["rack.request.query_string"] = s
41
- r.env["QUERY_STRING"] = s
42
- r.instance_variable_set "@params", r.POST.merge(q)
43
- end
44
-
45
- if m.item.is_a? Proc
46
- m.item.call r
47
- elsif m.item.respond_to? :call
48
- r.env["PATH_INFO"] = m.remaining_path
49
- m.item.call r.env
50
- else
51
- raise InvalidRouteError, "Route handlers must be blocks or valid rack apps."
52
- end
34
+ if m.url_params.count > 0
35
+ q = r.params.merge m.url_params
36
+ s = q.map { |p| p.join '=' }.join '&'
37
+ r.env["rack.request.query_hash"] = q
38
+ r.env["rack.request.query_string"] = s
39
+ r.env["QUERY_STRING"] = s
40
+ r.instance_variable_set "@params", r.POST.merge(q)
53
41
  end
42
+
43
+ case m.item
44
+ when Proc then res = m.item.call r
45
+ else
46
+ raise InvalidRouteError, "Route handlers must be blocks or valid rack apps." unless m.item.respond_to? :call
47
+ r.env["PATH_INFO"] = m.remaining_path
48
+ res = m.item.call r.env
49
+ end
50
+
51
+ if @after_block && @after_block.arity == 2
52
+ ares = @after_block.call r, res
53
+ return ares if Rack::Fastlint.response ares
54
+ end
55
+
56
+ res
54
57
  end
55
58
 
56
59
  def start port=3001
57
60
  raise NoRoutesError if tree.leaf?
58
- Rack::Handler.pick(HANDLERS).run self, :Port => port
61
+ Rack::Handler.pick(RACK_HANDLERS).run self, :Port => port
59
62
  end
60
63
 
61
64
  def before &block
62
65
  @before_block = block
63
66
  end
64
67
 
68
+ def after &block
69
+ @after_block = block
70
+ end
71
+
65
72
  def method_missing meth, *args, &block
66
73
  path, item = *args.dup.push(block)
67
74
  return super unless path && item
@@ -4,35 +4,28 @@
4
4
 
5
5
  module Pine
6
6
  Result = Struct.new :item, :remaining_path, :url_params
7
-
7
+
8
8
  class Content
9
- attr_accessor :items, :map
9
+ attr_reader :items, :map
10
10
 
11
11
  def initialize
12
12
  @items = []
13
13
  @map = {}
14
14
  end
15
-
16
- def []= k,v
15
+
16
+ def set k,v
17
17
  @items << v if k == :map
18
18
  @map[k] = v unless k == :map
19
19
  end
20
-
21
- def [] k
22
- @items[k] if Numeric === k
23
- @map[k] unless Numeric === k
24
- end
25
20
  end
26
21
 
27
22
  class Node
28
- attr_reader :name, :parent
29
- attr_accessor :content
30
-
31
- def initialize name, content=Content.new
23
+ attr_reader :name, :parent, :content
24
+
25
+ def initialize name
32
26
  @name = name
33
- @content = content
27
+ @content = Content.new
34
28
  @children = {}
35
- @parent = nil
36
29
  end
37
30
 
38
31
  def root?
@@ -48,45 +41,33 @@ module Pine
48
41
  end
49
42
 
50
43
  def [] k
51
- child = @children[k]
52
- return child unless child.nil?
53
- child = @children.values.first
54
- return child if child.wildcard?
55
- nil
56
- # return @children[k] || @children.values.first
57
- end
58
-
59
- def create_and_save comp
60
- child = self.class.new comp
61
- child.instance_variable_set "@parent", self
62
- @children[comp] = child
63
- child
44
+ return @children[k] if @children.member? k
45
+ c = @children.values.first
46
+ return c if (c.wildcard? rescue false)
64
47
  end
65
48
 
66
49
  def << comp
67
- if comp.start_with? ":"
68
- @children.clear
69
- create_and_save comp
70
- else
71
- child = @children[comp]
72
- child = create_and_save comp if !child || (!child && child.leaf? && !child.wildcard?)
73
- child
50
+ child = self[comp]
51
+
52
+ if child.nil?
53
+ child = self.class.new comp
54
+ child.instance_variable_set "@parent", self
55
+ @children.reject!(&:leaf?) if child.wildcard?
56
+ @children[comp] = child
74
57
  end
75
- end
76
58
 
77
- def parse_path path, include_root=true
59
+ child
60
+ end
61
+
62
+ def parse_path path
78
63
  c = path.split "/"
79
- if include_root
80
- c[0] = '/'
81
- else
82
- c.delete_at(0) if c[0].empty?
83
- end
64
+ c[0] = '/'
84
65
  c.delete_at(-1) if c[-1].empty?
85
66
  c
86
67
  end
87
68
 
88
69
  def map_path path, item, key
89
- parse_path(path).inject(self) { |node, comp| node << comp }.content[key] = item
70
+ parse_path(path).inject(self) { |node, comp| node << comp }.content.set key, item
90
71
  path
91
72
  end
92
73
 
@@ -95,15 +76,18 @@ module Pine
95
76
  matched_params = {}
96
77
 
97
78
  walk = parse_path(path).inject self do |node, comp|
98
- next node[comp] if node.name == "ROOT"
99
- matched_comps << comp unless node.leaf?
100
- child = node[comp]
101
- matched_params[child.name[1..-1]] = comp if child.wildcard?
102
- child
79
+ break node if node.leaf?
80
+ next node[comp] if node.root?
81
+
82
+ c = node[comp]
83
+ break node if c.nil?
84
+ matched_comps << comp
85
+ matched_params[c.name[1..-1]] = comp if c.wildcard?
86
+ c
103
87
  end
104
88
 
105
89
  return nil if walk.nil?
106
- return nil if walk.root? #rescue true
90
+ return nil if walk.root?
107
91
 
108
92
  c = walk.content
109
93
  subpath = path.sub "/#{matched_comps.join("/")}", ""
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "sansom"
7
- s.version = "0.0.7"
7
+ s.version = "0.1.0"
8
8
  s.authors = ["Nathaniel Symer"]
9
9
  s.email = ["nate@natesymer.com"]
10
10
  s.summary = "Scientific, philosophical, abstract web 'picowork' named after Sansom street in Philly, near where it was made."
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.7
4
+ version: 0.1.0
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-08-01 00:00:00.000000000 Z
11
+ date: 2014-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler