immanence 0.0.2 → 0.1.1
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 +8 -8
- data/README.md +7 -5
- data/Rakefile +9 -0
- data/lib/immanence.rb +65 -42
- data/lib/immanence/version.rb +1 -1
- data/spec/immanence_spec.rb +49 -0
- data/spec/spec_helper.rb +3 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MTZkMWFhOGNhODAxOGMyNzYyNTcwNDBhMmEzZWVjNTc3ZTk4ODJlYQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YTA5MWZmZDk3NjY2NTc4ZmVhMmNkMjk0Yzg1ZGIwMzVhMDVkMDMzNg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTUzNjdjMTQ1NmI5NmNiYjdlYTdkNmVhNWJlMzVkNjMzYjEwMGY0MjdlNDk5
|
10
|
+
NzQwYzU5ODZkNmIxYTM2N2I5MWRhMjM3OGYwODExYzJhZmQ4ZWZmZWZmZjA4
|
11
|
+
Yzg3NjI4NDc5M2YwYjA0N2ZiYjZkZDQ3NjBiNmNmYjZiOGFhNDk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
Zjk3ZGJmZmI4YjA3OTljMjBkNmU2ZDBmNjJlNzgwNjE4ZGJmZGI0NDEwNzQy
|
14
|
+
YjFiMzE1MDgyNWRmNzE0Mjc5ZjYyMzcxYTg2YWQ3OWY3MTg2OWY2ZWM0NjEw
|
15
|
+
OGI4MjUzYjU1MTlhMzVlZDdlZmJjNjYwNGQ0NmEyZDMyOTc0NDE=
|
data/README.md
CHANGED
@@ -9,18 +9,20 @@
|
|
9
9
|
>
|
10
10
|
> —Arakawa and Madeline Gins
|
11
11
|
|
12
|
-
**Immanence** is a DSL for handling web requests in Ruby, built on top of Rack. To execute routes it calculates the [Levenshtein distance](http://en.wikipedia.org/wiki/Levenshtein_distance) between incoming requests and routes defined
|
12
|
+
**Immanence** is a DSL for handling web requests in Ruby, built on top of Rack. To execute routes it calculates the [Levenshtein distance](http://en.wikipedia.org/wiki/Levenshtein_distance) between incoming requests and routes defined through the DSL then executes the most likely candidate. *Something will always be executed.* Objects are rendered by calling `→` (alias `render`) with the object to be rendered as the argument. Object responses are encoded as JSON. Incoming JSON is automatically parsed and available in as the `input` object.
|
13
13
|
|
14
|
-
|
14
|
+
What does it mean to discard transparent precision in favor of immanent promiscuity?
|
15
15
|
|
16
16
|
```ruby
|
17
|
-
|
17
|
+
# encoding: UTF-8
|
18
|
+
|
19
|
+
class Application < Immanent::Control
|
18
20
|
route :get, "/fields/:id" do
|
19
|
-
|
21
|
+
→ Field.find(params[:id])
|
20
22
|
end
|
21
23
|
|
22
24
|
route :post, "/fields" do
|
23
|
-
|
25
|
+
→ Field.create(input)
|
24
26
|
end
|
25
27
|
end
|
26
28
|
```
|
data/Rakefile
CHANGED
@@ -4,3 +4,12 @@ desc "Open an irb session preloaded with this library"
|
|
4
4
|
task :console do
|
5
5
|
sh "irb -rubygems -I lib -r immanence.rb"
|
6
6
|
end
|
7
|
+
|
8
|
+
desc "Run specs"
|
9
|
+
task :spec do
|
10
|
+
require "rspec/core/rake_task"
|
11
|
+
|
12
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
13
|
+
spec.rspec_opts = %w{--colour --format progress}
|
14
|
+
end
|
15
|
+
end
|
data/lib/immanence.rb
CHANGED
@@ -8,77 +8,98 @@ require "core_ext/hash"
|
|
8
8
|
require "core_ext/object"
|
9
9
|
|
10
10
|
module Immanence
|
11
|
-
class Request
|
11
|
+
class Request
|
12
|
+
attr_reader :input
|
13
|
+
|
14
|
+
def initialize(request, input)
|
15
|
+
@__request__ = request
|
16
|
+
@input = input
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(method, *args, &block)
|
20
|
+
@__request__.send(method, *args, &block)
|
21
|
+
end
|
22
|
+
end # Request
|
12
23
|
|
13
24
|
class Control
|
14
25
|
I = λ { |i| Oj.load(i) }
|
15
26
|
O = λ { |o| Oj.dump(o, mode: :compat) }
|
16
27
|
|
17
|
-
LEVENSHTEIN = λ
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
28
|
+
LEVENSHTEIN = λ do |a, b|
|
29
|
+
[(0..a.size).to_a].tap { |mx|
|
30
|
+
(1..b.size).each do |j|
|
31
|
+
mx << [j] + [0] * (a.size)
|
32
|
+
end
|
23
33
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
+
(1..b.size).each do |i|
|
35
|
+
(1..a.size).each do |j|
|
36
|
+
if a[j-1] == b[i-1]
|
37
|
+
mx[i][j] = mx[i-1][j-1]
|
38
|
+
else
|
39
|
+
mx[i][j] = [
|
40
|
+
mx[i-1][j],
|
41
|
+
mx[i][j-1],
|
42
|
+
mx[i-1][j-1]
|
43
|
+
].min + 1
|
44
|
+
end
|
34
45
|
end
|
35
46
|
end
|
36
|
-
|
37
|
-
|
38
|
-
mx[-1][-1]
|
39
|
-
}
|
47
|
+
}[-1][-1]
|
48
|
+
end
|
40
49
|
|
41
50
|
class << self
|
42
|
-
|
43
|
-
body = O[body]
|
51
|
+
alias_method :delegate_to, :send
|
44
52
|
|
45
|
-
|
53
|
+
# Convenience methods
|
54
|
+
def request() @request end
|
55
|
+
def input() request.input end
|
56
|
+
def params() ascertain(receiver, request.path).reverse_merge!(request.params) end
|
57
|
+
|
58
|
+
# Naive implementation
|
59
|
+
def before(&blk) yield end
|
46
60
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
})
|
61
|
+
# Interface with Rack
|
62
|
+
def call(env)
|
63
|
+
@request = Request.new(Rack::Request.new(env), I[env["rack.input"]])
|
51
64
|
|
52
|
-
|
65
|
+
delegate_to receiver
|
66
|
+
rescue => ε
|
67
|
+
→ ({ error: ε }),
|
68
|
+
{ status: 500, headers:
|
69
|
+
{ "X-Message" => "[...] from a problem to the accidents that condition and resolve it." } }
|
53
70
|
end
|
54
71
|
|
72
|
+
# Define routes in the application
|
55
73
|
def route(verb, path, &blk)
|
56
74
|
meta_def(conjugate(verb, path)) { instance_eval &blk }
|
57
75
|
end
|
58
76
|
|
59
|
-
|
60
|
-
|
61
|
-
|
77
|
+
# Render responses
|
78
|
+
def render(body=:ok, options={})
|
79
|
+
options.reverse_merge!({ status: 200 })
|
62
80
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
81
|
+
options[:headers] ||= {}
|
82
|
+
options[:headers].reverse_merge!({
|
83
|
+
"Content-Type" => "text/json", "X-Framework" => "Immanence" })
|
84
|
+
|
85
|
+
Rack::Response.new(O[body], options[:status], options[:headers]).finish
|
67
86
|
end
|
68
87
|
|
88
|
+
alias_method :→, :render
|
89
|
+
|
69
90
|
private
|
70
91
|
|
71
92
|
def conjugate(verb, path) # :nodoc:
|
72
93
|
"immanent_#{verb}_#{path}"
|
73
94
|
end
|
74
95
|
|
75
|
-
# @return [Hash] Hash of request
|
96
|
+
# @return [Hash] Hash of parameters gleaned from request signature
|
76
97
|
def ascertain(method, path)
|
77
98
|
[method.to_s.gsub(/immanent_\w*_/, ""), path].
|
78
99
|
|
79
100
|
map { |path| path.split("/")[1..-1] }.
|
80
101
|
let { |x, y| x.zip(y) }.
|
81
|
-
select { |x,
|
102
|
+
select { |x, _| x[0] == ":" }.
|
82
103
|
map { |x, y| { x[1..-1] => y } }.
|
83
104
|
|
84
105
|
reduce({}, :merge).
|
@@ -88,9 +109,11 @@ module Immanence
|
|
88
109
|
# @return [String] most likely candidate method to invoke based on incoming route
|
89
110
|
def receiver
|
90
111
|
@receiver ||= methods.grep(/immanent_/).map { |method|
|
91
|
-
{ method: method, Δ: LEVENSHTEIN[method, conjugate(
|
112
|
+
{ method: method, Δ: LEVENSHTEIN[method, conjugate(request.request_method, request.path)] }
|
92
113
|
}.min_by { |x| x[:Δ] }[:method]
|
93
114
|
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
115
|
+
end # self
|
116
|
+
end # Control
|
117
|
+
end # Immanence
|
118
|
+
|
119
|
+
Immanent = Immanence
|
data/lib/immanence/version.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
|
4
|
+
|
5
|
+
describe "Immanent" do
|
6
|
+
before do
|
7
|
+
class Application < Immanent::Control
|
8
|
+
route :get, "/resource/:id" do
|
9
|
+
render ({ no: :future })
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should calculate the Levenshtein difference between two strings (0)" do
|
15
|
+
Immanent::Control::LEVENSHTEIN["kitten", "sitten"].should eq 1
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should calculate the Levenshtein difference between two strings (1)" do
|
19
|
+
Immanent::Control::LEVENSHTEIN["sitten", "sittin"].should eq 1
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should calculate the Levenshtein difference between two strings (2)" do
|
23
|
+
Immanent::Control::LEVENSHTEIN["sittin", "sitting"].should eq 1
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should conjugate a verb and path into a method name" do
|
27
|
+
Immanent::Control.send(:conjugate, :get, "/resource/:id").should eq "immanent_get_/resource/:id"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should extract parameters out of the request path" do
|
31
|
+
Immanent::Control.send(:ascertain, "immanent_get_/resource/:id", "/resource/1000").should eq({ id: "1000" })
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should be able to extract multiple parameters out of the request path" do
|
35
|
+
Immanent::Control.send(:ascertain, "immanent_get_/resource/:resource_id/child/:id", "/resource/1000/child/10").should eq({ resource_id: "1000", id: "10" })
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should provide a DSL for defining routes" do
|
39
|
+
Application.methods.include?(:"immanent_get_/resource/:id").should be_true
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should have a default response" do
|
43
|
+
Application.render[0].should eq(Rack::Response.new("\"ok\"").finish[0])
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should respond with the route definition, a JSON string" do
|
47
|
+
Application.send("immanent_get_/resource/:id").last.body.should eq(["{\"no\":\"future\"}"])
|
48
|
+
end
|
49
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: immanence
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dzucconi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -97,6 +97,8 @@ files:
|
|
97
97
|
- lib/core_ext/object.rb
|
98
98
|
- lib/immanence.rb
|
99
99
|
- lib/immanence/version.rb
|
100
|
+
- spec/immanence_spec.rb
|
101
|
+
- spec/spec_helper.rb
|
100
102
|
homepage: http://github.com/dzucconi/immanence
|
101
103
|
licenses:
|
102
104
|
- CC0
|
@@ -121,5 +123,7 @@ rubygems_version: 2.0.6
|
|
121
123
|
signing_key:
|
122
124
|
specification_version: 4
|
123
125
|
summary: A framework
|
124
|
-
test_files:
|
126
|
+
test_files:
|
127
|
+
- spec/immanence_spec.rb
|
128
|
+
- spec/spec_helper.rb
|
125
129
|
has_rdoc:
|