mvcli 0.0.1 → 0.0.2
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 +4 -4
- data/lib/mvcli/actions.rb +7 -4
- data/lib/mvcli/app.rb +8 -4
- data/lib/mvcli/erb.rb +40 -0
- data/lib/mvcli/loader.rb +15 -0
- data/lib/mvcli/renderer.rb +16 -0
- data/lib/mvcli/router.rb +26 -15
- data/lib/mvcli/version.rb +1 -1
- data/spec/mvcli/actions_spec.rb +2 -3
- data/spec/mvcli/erb_spec.rb +14 -0
- data/spec/mvcli/loader_spec.rb +13 -0
- data/spec/mvcli/router_spec.rb +15 -37
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d38bca7cf98c3cad670fe5df941fd17c8d8cd267
|
4
|
+
data.tar.gz: a1438f4ab557e0f083b9eca8875b67a2b9b12a27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b707863564e785f0fe67fe47712a2ba416214708a4ae6fce7d9500e5d5347b6c2bc0b2112186bade3fda1baf1b7f1426c2eb0199189615e59d2b90e3b3969dd4
|
7
|
+
data.tar.gz: 1add93e30613c13ba50b798543e76975df840a4f4b563cb83af8988118848994fdedfdd8e08c2772cc39e3f2e95f2a6864e074212bd02c5e7033fc9f30ded21d
|
data/lib/mvcli/actions.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
require_relative "loader"
|
2
|
+
require_relative "renderer"
|
3
|
+
|
1
4
|
module MVCLI
|
2
5
|
class Actions
|
3
|
-
def initialize(loader, renderer)
|
4
|
-
@loader = loader
|
5
|
-
@renderer = renderer
|
6
|
+
def initialize(root, loader = nil, renderer = nil)
|
7
|
+
@loader = loader || Loader.new(root)
|
8
|
+
@renderer = renderer || Renderer.new(root)
|
6
9
|
end
|
7
10
|
|
8
11
|
def [](key)
|
@@ -20,10 +23,10 @@ module MVCLI
|
|
20
23
|
|
21
24
|
def call(command)
|
22
25
|
controller = @loader.load :controller, @controller
|
23
|
-
fail LoadError, "no such controller: #{@controller}" unless controller
|
24
26
|
context = controller.send @method
|
25
27
|
path = [@controller, @method].join('/')
|
26
28
|
@renderer.render command.output, path, context
|
29
|
+
return 0
|
27
30
|
end
|
28
31
|
end
|
29
32
|
end
|
data/lib/mvcli/app.rb
CHANGED
@@ -1,23 +1,27 @@
|
|
1
1
|
require_relative "middleware"
|
2
2
|
require_relative "command"
|
3
|
+
require_relative "actions"
|
3
4
|
require_relative "router"
|
4
5
|
|
5
6
|
module MVCLI
|
6
7
|
class App
|
7
|
-
|
8
8
|
def initialize
|
9
|
-
@
|
10
|
-
@
|
9
|
+
@router = Router.new Actions.new root
|
10
|
+
@router.instance_eval route_file.read, route_file.to_s, 1
|
11
11
|
end
|
12
12
|
|
13
13
|
def call(command)
|
14
|
-
@
|
14
|
+
@router.call command
|
15
15
|
end
|
16
16
|
|
17
17
|
def root
|
18
18
|
self.class.root or fail "Invalid App: undefined application root directory"
|
19
19
|
end
|
20
20
|
|
21
|
+
def route_file
|
22
|
+
root.join 'app/routes.rb'
|
23
|
+
end
|
24
|
+
|
21
25
|
class << self
|
22
26
|
attr_accessor :root
|
23
27
|
end
|
data/lib/mvcli/erb.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require "erb"
|
2
|
+
|
3
|
+
module MVCLI
|
4
|
+
class ERB
|
5
|
+
def initialize
|
6
|
+
@compiler = ::ERB::Compiler.new("<>")
|
7
|
+
@compiler.pre_cmd = [""]
|
8
|
+
@compiler.put_cmd = "@_erbout <<"
|
9
|
+
@compiler.insert_cmd = "@_erbout <<"
|
10
|
+
@compiler.post_cmd = ["nil"]
|
11
|
+
end
|
12
|
+
|
13
|
+
def compile(string, filename = '(erb)')
|
14
|
+
code, enc = @compiler.compile string
|
15
|
+
Template.new code, enc, filename
|
16
|
+
end
|
17
|
+
|
18
|
+
class Template
|
19
|
+
def initialize(code, enc, filename)
|
20
|
+
@code, @enc, @filename = code, enc, filename
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(context, output)
|
24
|
+
binding = context.instance_eval do
|
25
|
+
@_erbout = output
|
26
|
+
Kernel.binding
|
27
|
+
end
|
28
|
+
eval @code, binding, @filename, 1
|
29
|
+
ensure
|
30
|
+
context.remove_instance_variable(:@_erbout)
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_proc
|
34
|
+
proc do |context, output|
|
35
|
+
call context, output
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/mvcli/loader.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module MVCLI
|
2
|
+
class Loader
|
3
|
+
def initialize(path)
|
4
|
+
@path = path
|
5
|
+
end
|
6
|
+
|
7
|
+
def load(type, name)
|
8
|
+
pathname = "#{name}_#{type}"
|
9
|
+
filename = File.join(@path, "app/#{type}s", pathname)
|
10
|
+
require filename
|
11
|
+
classname = pathname.capitalize.gsub(/_(\w)/) {|m| m[1].upcase}
|
12
|
+
Object.const_get(classname).new
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'mvcli/erb'
|
2
|
+
|
3
|
+
module MVCLI
|
4
|
+
class Renderer
|
5
|
+
def initialize(root)
|
6
|
+
@root = root
|
7
|
+
end
|
8
|
+
|
9
|
+
def render(output, path, context)
|
10
|
+
filename = @root.join('app/views', path + '.txt.erb').to_s
|
11
|
+
compiler = MVCLI::ERB.new
|
12
|
+
template = compiler.compile File.read(filename), filename
|
13
|
+
template.call(context, output)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/mvcli/router.rb
CHANGED
@@ -7,28 +7,39 @@ module MVCLI
|
|
7
7
|
|
8
8
|
def initialize(actions = nil)
|
9
9
|
@actions = actions || Map.new
|
10
|
-
@
|
10
|
+
@routes = []
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
action = options
|
15
|
-
|
16
|
-
|
17
|
-
@root[verb] = action
|
18
|
-
end
|
13
|
+
def match(options)
|
14
|
+
pattern, action = options.first
|
15
|
+
options.delete pattern
|
16
|
+
@routes << Route.new(pattern, @actions, action, options)
|
19
17
|
end
|
20
18
|
|
21
19
|
def call(command)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
if route = @routes.find {|r| r.matches? command}
|
21
|
+
return route.call command
|
22
|
+
end
|
23
|
+
fail RoutingError, "no route matches '#{command.argv.join ' '}'"
|
24
|
+
end
|
25
|
+
|
26
|
+
class Route
|
27
|
+
def initialize(pattern, actions, action, options = {})
|
28
|
+
@pattern, @actions, @action, @options = pattern.to_s, actions, action, options
|
29
|
+
end
|
30
|
+
|
31
|
+
def matches?(command)
|
32
|
+
segments = @pattern.split /\s+/
|
33
|
+
segments.each_with_index do |s, i|
|
34
|
+
return false unless command.argv[i] && s.to_s == command.argv[i]
|
29
35
|
end
|
36
|
+
return true
|
37
|
+
end
|
38
|
+
|
39
|
+
def call(command)
|
40
|
+
action = @actions[@action] or fail "no action found for #{@action}"
|
41
|
+
action.call command
|
30
42
|
end
|
31
|
-
fail RoutingError, "#{path.join(':')} does not respond to #{verb}"
|
32
43
|
end
|
33
44
|
end
|
34
45
|
end
|
data/lib/mvcli/version.rb
CHANGED
data/spec/mvcli/actions_spec.rb
CHANGED
@@ -4,11 +4,10 @@ require "mvcli/actions"
|
|
4
4
|
describe "MVCLI::Actions" do
|
5
5
|
Given(:loader) {mock(:Loader)}
|
6
6
|
Given(:renderer) {mock(:Renderer, :render => true)}
|
7
|
-
Given(:actions) {MVCLI::Actions.new loader, renderer}
|
7
|
+
Given(:actions) {MVCLI::Actions.new '/root', loader, renderer}
|
8
8
|
|
9
9
|
context "when the loader cannot find an appropriate controller" do
|
10
|
-
Given {loader.stub(:load)}
|
11
|
-
|
10
|
+
Given {loader.stub(:load) {fail LoadError}}
|
12
11
|
When(:action) {actions['foo']}
|
13
12
|
Then {action.should_not be_nil}
|
14
13
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "mvcli/erb"
|
3
|
+
|
4
|
+
describe "MVCLI::ERB" do
|
5
|
+
Given(:erb) {MVCLI::ERB.new}
|
6
|
+
context "when I compile a template" do
|
7
|
+
Given(:output) {""}
|
8
|
+
Given(:template) {erb.compile "name: <%= name %>"}
|
9
|
+
context "and call it with a context" do
|
10
|
+
When {template.call mock(:Context, :name => 'Charles'), output}
|
11
|
+
Then {output.should eql "name: Charles"}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "mvcli/loader"
|
3
|
+
|
4
|
+
describe "MVCLI::Loader" do
|
5
|
+
|
6
|
+
Given {class ::TotallyAwesomeController; end}
|
7
|
+
Given(:loader) {MVCLI::Loader.new '/path/to/app'}
|
8
|
+
Given {loader.stub(:require) {true}}
|
9
|
+
context "loading a controller in the global namespace" do
|
10
|
+
When(:controller){loader.load :controller, 'totally_awesome'}
|
11
|
+
Then {controller.should be_instance_of TotallyAwesomeController}
|
12
|
+
end
|
13
|
+
end
|
data/spec/mvcli/router_spec.rb
CHANGED
@@ -5,53 +5,31 @@ describe "MVCLI::Router" do
|
|
5
5
|
Given(:Router) {MVCLI::Router}
|
6
6
|
Given(:actions) {mock(:Actions)}
|
7
7
|
Given(:router) {self.Router.new actions}
|
8
|
+
Given {actions.stub(:[]) {|action| @action = action; ->(command) {@command = command}}}
|
9
|
+
|
8
10
|
|
9
11
|
context "without any routes" do
|
10
12
|
When(:result) {invoke}
|
11
13
|
Then {result.should have_failed self.Router::RoutingError}
|
12
14
|
end
|
13
15
|
|
14
|
-
context "
|
15
|
-
|
16
|
-
Then {result.should have_failed}
|
17
|
-
end
|
18
|
-
|
19
|
-
context "with its root mapped to a single verb" do
|
20
|
-
Given do
|
21
|
-
actions.stub(:[]).with('logins#create') do
|
22
|
-
proc do |command|
|
23
|
-
@login = command
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
Given {router.root :to => 'logins#create', :via => :login}
|
16
|
+
context "with a route matched to an action" do
|
17
|
+
Given {router.match 'login' => 'logins#create'}
|
28
18
|
When {invoke 'login'}
|
29
|
-
Then {@
|
19
|
+
Then {@action.should eql 'logins#create'}
|
20
|
+
And {@command.should_not be_nil}
|
21
|
+
Then {@command.argv.should eql ['login']}
|
22
|
+
end
|
30
23
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
context "and a second verb is mapped to the the root" do
|
36
|
-
Given do
|
37
|
-
actions.stub(:[]).with('logins#destroy') {proc {|c| @logout = c}}
|
38
|
-
end
|
39
|
-
Given {router.root :to => 'logins#destroy', :via => :logout}
|
40
|
-
context "when I access via the original verb" do
|
41
|
-
Given {invoke 'logout' }
|
42
|
-
Then {@logout.should_not be_nil}
|
43
|
-
And {@logout.argv.should eql ['logout']}
|
44
|
-
end
|
45
|
-
end
|
24
|
+
context "with a route matched to a block" do
|
25
|
+
Given {router.match bam: ->(command) {@command = command}}
|
26
|
+
When {invoke 'bam'}
|
27
|
+
Then {@command.argv.should eql ['bam']}
|
46
28
|
end
|
47
29
|
|
48
|
-
context "with
|
49
|
-
Given
|
50
|
-
|
51
|
-
end
|
52
|
-
Given {router.root :to => 'something#show'}
|
53
|
-
When {invoke 'help'}
|
54
|
-
Then {@something.argv.should eql ['help']}
|
30
|
+
context "with a route with dynamic segments" do
|
31
|
+
Given {router.match 'show loadbalancer :name' => 'loadbalancers#show'}
|
32
|
+
When(:result) {invoke 'show loadbalancer 6'}
|
55
33
|
end
|
56
34
|
|
57
35
|
def invoke(*args)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mvcli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Lowell
|
@@ -29,7 +29,7 @@ cert_chain:
|
|
29
29
|
UgImJlChAzCoDP9zi9tdm6jAr7ttF25R9PPYr11ILb7dYe3qUzlNlM6zJx/nb31b
|
30
30
|
IhdyRVup4qLcqYSTPsm6u7VA
|
31
31
|
-----END CERTIFICATE-----
|
32
|
-
date: 2013-05-
|
32
|
+
date: 2013-05-22 00:00:00.000000000 Z
|
33
33
|
dependencies:
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: map
|
@@ -63,11 +63,16 @@ files:
|
|
63
63
|
- lib/mvcli/actions.rb
|
64
64
|
- lib/mvcli/app.rb
|
65
65
|
- lib/mvcli/command.rb
|
66
|
+
- lib/mvcli/erb.rb
|
67
|
+
- lib/mvcli/loader.rb
|
66
68
|
- lib/mvcli/middleware.rb
|
69
|
+
- lib/mvcli/renderer.rb
|
67
70
|
- lib/mvcli/router.rb
|
68
71
|
- lib/mvcli/version.rb
|
69
72
|
- mvcli.gemspec
|
70
73
|
- spec/mvcli/actions_spec.rb
|
74
|
+
- spec/mvcli/erb_spec.rb
|
75
|
+
- spec/mvcli/loader_spec.rb
|
71
76
|
- spec/mvcli/middleware_spec.rb
|
72
77
|
- spec/mvcli/router_spec.rb
|
73
78
|
- spec/spec_helper.rb
|
@@ -97,6 +102,8 @@ specification_version: 4
|
|
97
102
|
summary: Local Apps. Remote Apps. They're all at your fingertips
|
98
103
|
test_files:
|
99
104
|
- spec/mvcli/actions_spec.rb
|
105
|
+
- spec/mvcli/erb_spec.rb
|
106
|
+
- spec/mvcli/loader_spec.rb
|
100
107
|
- spec/mvcli/middleware_spec.rb
|
101
108
|
- spec/mvcli/router_spec.rb
|
102
109
|
- spec/spec_helper.rb
|