mvcli 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +4 -0
- data/Rakefile +6 -0
- data/example/controllers/loadbalancers_controller.rb +10 -0
- data/example/routes.rb +31 -0
- data/lib/mvcli/actions.rb +30 -0
- data/lib/mvcli/app.rb +33 -0
- data/lib/mvcli/command.rb +9 -0
- data/lib/mvcli/middleware.rb +38 -0
- data/lib/mvcli/router.rb +34 -0
- data/lib/mvcli/version.rb +3 -0
- data/lib/mvcli.rb +5 -0
- data/mvcli.gemspec +22 -0
- data/spec/mvcli/actions_spec.rb +30 -0
- data/spec/mvcli/middleware_spec.rb +74 -0
- data/spec/mvcli/router_spec.rb +60 -0
- data/spec/spec_helper.rb +3 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2af39b708e5b71d002d6734923412e067411c115
|
4
|
+
data.tar.gz: dcdf57432aeb3712a27878088ae4a527728b9ac2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dceaaf28dae8821938e47b2c528330e6cacf7abe51bfddadf0ef94c0b4d201659e55bcf52188280d88fe3f92d01728adb1e2014bc048e78aae49d795f61e3e83
|
7
|
+
data.tar.gz: 4b6586b4eb3b18213257b23122114d66800419d1a1940b79c4c39512ffa33e87800a04feb7610315815f7d6e1187c591e1dc3f54ada6d70c80ac0aa3fecd1a86
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Charles Lowell
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
data/example/routes.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
collection :loadbalancers do
|
2
|
+
# match "create loadbalancer"
|
3
|
+
# match "show loadbalancers"
|
4
|
+
# match "loadbalancers"
|
5
|
+
# match "show loadbalancer :id" #=> 'loadbalancers#show'
|
6
|
+
# match "update loadbalancer :id #=> loadbalancers#update"
|
7
|
+
# match "destroy loadbalancer :id"
|
8
|
+
collection :nodes do
|
9
|
+
# match "create node on loadbalancer :loadbalancer_id"
|
10
|
+
# match "create loadbalancer :loadbalancer_id node"
|
11
|
+
# match "show nodes on loadbalancer :loadbalancer_id"
|
12
|
+
# match "loadbalancer nodes"
|
13
|
+
# match "show loadbalancer :loadbalancer_id nodes"
|
14
|
+
# match "show loadbalancer :loadbalancer_id node :id"
|
15
|
+
# match "show node :id on loadbalancer :loadbalancer_id"
|
16
|
+
# match "update loadbalancer:node"
|
17
|
+
# match "destroy loadbalancer:node:$id"
|
18
|
+
# match "destroy loadbalancer node $id"
|
19
|
+
# match "destroy loadbalancer:node $id"
|
20
|
+
# match "help "
|
21
|
+
end
|
22
|
+
|
23
|
+
collection :virtual_ips, :only => :index
|
24
|
+
# match "show virtual_ips on loadbalancer :loadbalancer_id"
|
25
|
+
# match "show loadbalancer :loadbalancer_id virtual_ips"
|
26
|
+
# match "loadbalancers"
|
27
|
+
end
|
28
|
+
|
29
|
+
collection :servers do
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module MVCLI
|
2
|
+
class Actions
|
3
|
+
def initialize(loader, renderer)
|
4
|
+
@loader = loader
|
5
|
+
@renderer = renderer
|
6
|
+
end
|
7
|
+
|
8
|
+
def [](key)
|
9
|
+
controller, method = key.split('#')
|
10
|
+
Action.new @loader, @renderer, controller, method
|
11
|
+
end
|
12
|
+
|
13
|
+
class Action
|
14
|
+
def initialize(loader, renderer, controller, method)
|
15
|
+
@loader = loader
|
16
|
+
@renderer = renderer
|
17
|
+
@controller = controller
|
18
|
+
@method = method
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(command)
|
22
|
+
controller = @loader.load :controller, @controller
|
23
|
+
fail LoadError, "no such controller: #{@controller}" unless controller
|
24
|
+
context = controller.send @method
|
25
|
+
path = [@controller, @method].join('/')
|
26
|
+
@renderer.render command.output, path, context
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/mvcli/app.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative "middleware"
|
2
|
+
require_relative "command"
|
3
|
+
require_relative "router"
|
4
|
+
|
5
|
+
module MVCLI
|
6
|
+
class App
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@middleware = Middleware.new
|
10
|
+
@middleware << Router.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(command)
|
14
|
+
@middleware.call command
|
15
|
+
end
|
16
|
+
|
17
|
+
def root
|
18
|
+
self.class.root or fail "Invalid App: undefined application root directory"
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
attr_accessor :root
|
23
|
+
end
|
24
|
+
|
25
|
+
def main(argv = ARGV.dup, input = $stdin, output = $stdout, log = $stderr, env = ENV.dup)
|
26
|
+
call Command.new(argv, input, output, log, env)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.main(*args)
|
30
|
+
new.main *args
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module MVCLI
|
2
|
+
class Middleware
|
3
|
+
def initialize
|
4
|
+
@apps = []
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(command)
|
8
|
+
invoke command, 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](idx)
|
12
|
+
@apps[idx]
|
13
|
+
end
|
14
|
+
|
15
|
+
def []=(idx, app)
|
16
|
+
@apps[idx] = app
|
17
|
+
end
|
18
|
+
|
19
|
+
def <<(app)
|
20
|
+
@apps << app
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def invoke(command, index)
|
26
|
+
if app = @apps[index]
|
27
|
+
app.call(command) do |c|
|
28
|
+
if @apps[index + 1]
|
29
|
+
c ||= command
|
30
|
+
invoke c, index + 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
else
|
34
|
+
return 0
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/mvcli/router.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "map"
|
2
|
+
|
3
|
+
module MVCLI
|
4
|
+
class Router
|
5
|
+
RoutingError = Class.new StandardError
|
6
|
+
InvalidRoute = Class.new RoutingError
|
7
|
+
|
8
|
+
def initialize(actions = nil)
|
9
|
+
@actions = actions || Map.new
|
10
|
+
@root = Map.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def root(options = {})
|
14
|
+
action = options[:to] or fail InvalidRoute, "root routes must specify an action with ':to =>' E.g. root :to => 'foo#bar'"
|
15
|
+
verbs = [options[:via] || :help].flatten
|
16
|
+
verbs.each do |verb|
|
17
|
+
@root[verb] = action
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(command)
|
22
|
+
verb = command.argv.first || 'help'
|
23
|
+
path = command.argv.slice(1..-1) || []
|
24
|
+
if path.empty?
|
25
|
+
if action_name = @root[verb]
|
26
|
+
if action = @actions[action_name]
|
27
|
+
return action.call command
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
fail RoutingError, "#{path.join(':')} does not respond to #{verb}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/mvcli.rb
ADDED
data/mvcli.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mvcli/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "mvcli"
|
8
|
+
spec.version = MVCLI::VERSION
|
9
|
+
spec.authors = ["Charles Lowell"]
|
10
|
+
spec.email = ["cowboyd@thefrontside.net"]
|
11
|
+
spec.description = %q{MVC Framework for Building Command Line Apps}
|
12
|
+
spec.summary = %q{Local Apps. Remote Apps. They're all at your fingertips}
|
13
|
+
spec.homepage = "https://github.com/cowboyd/mvcli"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
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"]
|
20
|
+
|
21
|
+
spec.add_dependency "map"
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "mvcli/actions"
|
3
|
+
|
4
|
+
describe "MVCLI::Actions" do
|
5
|
+
Given(:loader) {mock(:Loader)}
|
6
|
+
Given(:renderer) {mock(:Renderer, :render => true)}
|
7
|
+
Given(:actions) {MVCLI::Actions.new loader, renderer}
|
8
|
+
|
9
|
+
context "when the loader cannot find an appropriate controller" do
|
10
|
+
Given {loader.stub(:load)}
|
11
|
+
|
12
|
+
When(:action) {actions['foo']}
|
13
|
+
Then {action.should_not be_nil}
|
14
|
+
|
15
|
+
context ".calling it" do
|
16
|
+
When(:result) {action.call(mock(:Command))}
|
17
|
+
Then {result.should have_failed LoadError}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when the class exists" do
|
22
|
+
Given(:output) {mock(:Output)}
|
23
|
+
Given(:controller) {mock(:Controller)}
|
24
|
+
Given {loader.stub(:load).with(:controller, 'foo') {controller}}
|
25
|
+
Given {controller.stub(:bar) {"the context"}}
|
26
|
+
When {actions['foo#bar'].call(mock(:Command, :output => output))}
|
27
|
+
Then {controller.should have_received(:bar)}
|
28
|
+
And {renderer.should have_received(:render).with(output, 'foo/bar', 'the context')}
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "mvcli/middleware"
|
3
|
+
|
4
|
+
describe "MVCLI::Middleware" do
|
5
|
+
before do
|
6
|
+
@middleware = MVCLI::Middleware.new
|
7
|
+
@command = mock(:Command)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "runs perfectly fine without any apps" do
|
11
|
+
@middleware.call(@command).should eql 0
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "with a single app" do
|
15
|
+
before do
|
16
|
+
@app = proc do |command|
|
17
|
+
@called = command
|
18
|
+
end
|
19
|
+
@middleware << @app
|
20
|
+
@middleware.call @command
|
21
|
+
end
|
22
|
+
it "calls it" do
|
23
|
+
@called.should eql @command
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "with a couple apps" do
|
28
|
+
before do
|
29
|
+
@sequence = []
|
30
|
+
@commands = []
|
31
|
+
@middleware << proc do |command, &block|
|
32
|
+
@commands << command
|
33
|
+
@sequence << "first.before"
|
34
|
+
block.call
|
35
|
+
@sequence << "first.after"
|
36
|
+
end
|
37
|
+
@middleware << proc do |command, &block|
|
38
|
+
@commands << command
|
39
|
+
@sequence << "second"
|
40
|
+
end
|
41
|
+
@middleware.call @command
|
42
|
+
end
|
43
|
+
it "passes the command to all the apps" do
|
44
|
+
@commands.should eql [@command, @command]
|
45
|
+
end
|
46
|
+
it "calls the first app *around* the second app" do
|
47
|
+
@sequence.should eql ["first.before", "second", "first.after"]
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "if the first app does not yield" do
|
51
|
+
before do
|
52
|
+
@sequence.clear
|
53
|
+
@middleware[0] = Proc.new {}
|
54
|
+
@middleware.call @command
|
55
|
+
end
|
56
|
+
it "never calls the second app" do
|
57
|
+
@sequence.should eql []
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "with an app that yields even though there is no next app" do
|
63
|
+
before do
|
64
|
+
app = Object.new
|
65
|
+
def app.call(command)
|
66
|
+
yield
|
67
|
+
end
|
68
|
+
@middleware << @app
|
69
|
+
end
|
70
|
+
it "runs successfully" do
|
71
|
+
@middleware.call(@command).should eql 0
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "mvcli/router"
|
3
|
+
|
4
|
+
describe "MVCLI::Router" do
|
5
|
+
Given(:Router) {MVCLI::Router}
|
6
|
+
Given(:actions) {mock(:Actions)}
|
7
|
+
Given(:router) {self.Router.new actions}
|
8
|
+
|
9
|
+
context "without any routes" do
|
10
|
+
When(:result) {invoke}
|
11
|
+
Then {result.should have_failed self.Router::RoutingError}
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when an invalid root is mapped" do
|
15
|
+
When(:result) {router.root :wat => :tf?}
|
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}
|
28
|
+
When {invoke 'login'}
|
29
|
+
Then {@login.argv.should eql ['login']}
|
30
|
+
|
31
|
+
context "when a command comes in for an unmapped verb" do
|
32
|
+
When(:result) {invoke 'fwiff'}
|
33
|
+
Then {result.should have_failed self.Router::RoutingError}
|
34
|
+
end
|
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
|
46
|
+
end
|
47
|
+
|
48
|
+
context "with its root mapped without a specific verb" do
|
49
|
+
Given do
|
50
|
+
actions.stub(:[]).with('something#show') {proc {|c|@something = c}}
|
51
|
+
end
|
52
|
+
Given {router.root :to => 'something#show'}
|
53
|
+
When {invoke 'help'}
|
54
|
+
Then {@something.argv.should eql ['help']}
|
55
|
+
end
|
56
|
+
|
57
|
+
def invoke(*args)
|
58
|
+
router.call mock(:Command, :argv => args)
|
59
|
+
end
|
60
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mvcli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Charles Lowell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIDPjCCAiagAwIBAgIBADANBgkqhkiG9w0BAQUFADBFMRAwDgYDVQQDDAdjb3di
|
14
|
+
b3lkMRwwGgYKCZImiZPyLGQBGRYMdGhlZnJvbnRzaWRlMRMwEQYKCZImiZPyLGQB
|
15
|
+
GRYDbmV0MB4XDTEzMDEzMDIxMDYwNFoXDTE0MDEzMDIxMDYwNFowRTEQMA4GA1UE
|
16
|
+
AwwHY293Ym95ZDEcMBoGCgmSJomT8ixkARkWDHRoZWZyb250c2lkZTETMBEGCgmS
|
17
|
+
JomT8ixkARkWA25ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAO45
|
18
|
+
CUxpETDGYXjCCy2dMg/aIrdrTqBqQW5ZrzhHxF9EkcdmWFr0z/qMz0JSpZ3pF11Z
|
19
|
+
KYaj5PaQQpjZfLPwbuiGGkuSWi+UAac//V18xo6S4lzRBjO+gpzG9f2AOzt9b+SR
|
20
|
+
Uc8UhO7QBZ5edUDxMxw9QstD+U0YBAlzsPJbHuUOqdtxXmNQCds3ZnqTgZaIpdUy
|
21
|
+
CSejtrukSmlthxFzwgMezYQhcYxmkl+Q475JUodnI6Pjc6nja/Or8Y6cEWiLgeUa
|
22
|
+
a+efcPGLDEbwJC7TGRrvk8yassMByBEJ3XueTMzeqWFd+665ptciojYo6BvIAR0N
|
23
|
+
iLwks0x567FZyS8SqTcCAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUxVgR
|
24
|
+
5TUqf7Hd24ICb3g4FNbM7oYwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IB
|
25
|
+
AQDdJj+NzZhiYXA56z0wzRUA/Fcf6CYqKB+RFRlPssDEcHTor5SnwdWgQof/gNLi
|
26
|
+
Qel1Om4zO0Shcp89jxaUqtvEdYVhmyfc0vycHmemKttNBT734yMrEJtF8Hhy+Dnz
|
27
|
+
9CzixXLvgGaRH+mf3M0+l+zIDJJr2L+39L8cyTSSRnp/srfI8aSmJKhGshudBKoC
|
28
|
+
Ty6Gi071pwoJXvdMaE/6iPy7bUzlndYdHyYuWSKaO9N47HqQ62oEnBraglw6ghoi
|
29
|
+
UgImJlChAzCoDP9zi9tdm6jAr7ttF25R9PPYr11ILb7dYe3qUzlNlM6zJx/nb31b
|
30
|
+
IhdyRVup4qLcqYSTPsm6u7VA
|
31
|
+
-----END CERTIFICATE-----
|
32
|
+
date: 2013-05-20 00:00:00.000000000 Z
|
33
|
+
dependencies:
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: map
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
type: :runtime
|
42
|
+
prerelease: false
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
description: MVC Framework for Building Command Line Apps
|
49
|
+
email:
|
50
|
+
- cowboyd@thefrontside.net
|
51
|
+
executables: []
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- .gitignore
|
56
|
+
- Gemfile
|
57
|
+
- LICENSE.txt
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- example/controllers/loadbalancers_controller.rb
|
61
|
+
- example/routes.rb
|
62
|
+
- lib/mvcli.rb
|
63
|
+
- lib/mvcli/actions.rb
|
64
|
+
- lib/mvcli/app.rb
|
65
|
+
- lib/mvcli/command.rb
|
66
|
+
- lib/mvcli/middleware.rb
|
67
|
+
- lib/mvcli/router.rb
|
68
|
+
- lib/mvcli/version.rb
|
69
|
+
- mvcli.gemspec
|
70
|
+
- spec/mvcli/actions_spec.rb
|
71
|
+
- spec/mvcli/middleware_spec.rb
|
72
|
+
- spec/mvcli/router_spec.rb
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
homepage: https://github.com/cowboyd/mvcli
|
75
|
+
licenses:
|
76
|
+
- MIT
|
77
|
+
metadata: {}
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 2.0.0
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: Local Apps. Remote Apps. They're all at your fingertips
|
98
|
+
test_files:
|
99
|
+
- spec/mvcli/actions_spec.rb
|
100
|
+
- spec/mvcli/middleware_spec.rb
|
101
|
+
- spec/mvcli/router_spec.rb
|
102
|
+
- spec/spec_helper.rb
|