speck_gem 1.0.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.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem "rack"
4
+ gem "tilt"
5
+ gem "mocha_standalone"
data/Gemfile.lock ADDED
@@ -0,0 +1,16 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ metaclass (0.0.1)
5
+ mocha (0.12.3)
6
+ metaclass (~> 0.0.1)
7
+ rack (1.5.2)
8
+ tilt (1.3.6)
9
+
10
+ PLATFORMS
11
+ ruby
12
+
13
+ DEPENDENCIES
14
+ mocha
15
+ rack
16
+ tilt
data/README.md ADDED
@@ -0,0 +1,99 @@
1
+ Speck
2
+ =====
3
+
4
+ Ruby Microframework.
5
+
6
+ Getting Started
7
+ ===============
8
+ 1. make filesystem seen in app directory
9
+ 2. require gem
10
+
11
+
12
+ Routing
13
+ =======
14
+
15
+ ```ruby
16
+ # routes.rb
17
+
18
+ match '/','Home' do
19
+ get '' => 'index'
20
+ post 'login' => 'authenticate'
21
+ end
22
+
23
+ match '/vacations','Vacation' do
24
+ get '' => 'index', '/:id'=>'show'
25
+ put '/:id' => 'update'
26
+ post '/:id' => 'edit'
27
+
28
+ match '/:id1/photos','Photo' do
29
+ get '' => 'index', '/:id2' => 'show'
30
+ put '/:id2' => 'update'
31
+ post '/:id2' => 'edit'
32
+ end
33
+ end
34
+ ```
35
+
36
+ Controllers
37
+ ===========
38
+ ```ruby
39
+ class Photo < Speck::Controller
40
+ def index
41
+ session[:user] = params[:user]
42
+ render('home.html.erb')
43
+ end
44
+
45
+ def show
46
+ @user = session[:user]
47
+ @photo = fetch_photo(params[:id])
48
+ render('photo.html.erb')
49
+ end
50
+ end
51
+
52
+ ```
53
+
54
+ Templates
55
+ =========
56
+ Speck uses the tilt gem for template rendering. Many templating languages are supported. Below is an example using erb.
57
+ ```html
58
+ <h1><%= @user %></h1>
59
+
60
+ <% @photos.each do |photo| %>
61
+ <% @id = photo.id %>
62
+ <% @location = photo.location %>
63
+ <% @file = photo.file_path %>
64
+ <%= render('photo_partial.html.erb') %>
65
+ <% end %>
66
+
67
+ ```
68
+ and photo_partial.html.erb
69
+ ```html
70
+ <h3><%= @id %></h3>
71
+ <p><%= @location %></p>
72
+ <img src='<%= @file %>' />
73
+ ```
74
+ There are helper functions for paths, javascrpit, and css.
75
+
76
+ App Structure
77
+ =============
78
+ ```
79
+ /app
80
+ /assets
81
+ /controllers
82
+ /views
83
+ config.rb
84
+ exception.html.erb
85
+ Gemfile
86
+ routes.rb
87
+ server.log
88
+ ```
89
+
90
+ Rake Commands
91
+ =============
92
+ * rake test: runs the gem's test suite
93
+
94
+ TODO
95
+ ====
96
+ * test config
97
+ * test session persistence
98
+ * app structure
99
+ * rake task for building app structure
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ task :test do
2
+ require "cutest"
3
+ require "speck"
4
+ require "mocha_standalone"
5
+ Cutest.run(Dir["test/*.rb"]-Dir["test/*_example.rb"])
6
+ end
7
+
8
+ task :default => :test
9
+
10
+ require 'bundler'
11
+ Bundler::GemHelper.install_tasks
data/app/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ gem "speck"
2
+ gem "tilt"
data/app/config.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'speck'
2
+
3
+ Speck::Config.run()
@@ -0,0 +1,2 @@
1
+ <h1><%= @status %></h1>
2
+ <p><%= @message %></p>
data/app/routes.rb ADDED
File without changes
data/app/server.log ADDED
@@ -0,0 +1,5 @@
1
+ # Logfile created on 2013-05-12 23:40:45 -0400 by logger.rb/31641
2
+ E, [2013-05-12T23:40:45.944095 #43403] ERROR -- : [2013-05-12 23:40:45 -0400] 500: Missing rack.input
3
+
4
+ E, [2013-05-12T23:42:06.077617 #43650] ERROR -- : [2013-05-12 23:42:06 -0400] 500: Missing rack.input
5
+
File without changes
@@ -0,0 +1,67 @@
1
+ require 'rack'
2
+
3
+
4
+ module Speck
5
+ class Config
6
+ private_class_method :new
7
+
8
+ def self.app_root
9
+ if Dir.pwd[-3,3] == 'app'
10
+ dir = Dir.pwd
11
+ else
12
+ dir = Dir.pwd+'/app'
13
+ end
14
+ @@app_root ||= dir
15
+ end
16
+
17
+ def self.set_app_root(root)
18
+ @@app_root = root
19
+ end
20
+
21
+ def set_app_server(type)
22
+ @@server = type
23
+ end
24
+
25
+ def self.app_server
26
+ @@server ||= Rack::Handler::WEBrick
27
+ end
28
+
29
+ def self.app_port
30
+ @@port ||= 5000
31
+ end
32
+
33
+ def self.set_app_port(port)
34
+ @@port = port
35
+ end
36
+
37
+ def self.app_middleware
38
+ @@middleware ||= [[Rack::Static,{:urls => ["/assets"]}],
39
+ [Rack::Session::Cookie, {:key => 'rack.session',
40
+ :path => '/',
41
+ :expire_after => 2592000,
42
+ :secret => 'SECRETKEY1111'}]]
43
+ end
44
+
45
+ def self.add_app_middleware(middleware, options)
46
+ nxt = [middleware, options]
47
+ if app_middleware.nil?
48
+ @@middleware = [nxt]
49
+ else
50
+ @@middleware << nxt
51
+ end
52
+ end
53
+
54
+ def self.launch
55
+ app = Rack::Builder.app do
56
+ Speck::Config.app_middleware.each do |middleware|
57
+ use middleware[0], middleware[1]
58
+ end
59
+ Signal.trap('INT') {
60
+ Speck::Config.app_server.shutdown
61
+ }
62
+ run Speck::Router.new
63
+ end
64
+ app_server.run(app, :Port => app_port)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,76 @@
1
+ require 'tilt'
2
+
3
+ module Speck
4
+
5
+ class Controller
6
+
7
+ def initialize(session, params)
8
+ @__session = session
9
+ @__params = params
10
+ end
11
+
12
+ def link(path,text)
13
+ "<a href='#{path}'>#{text}</a>"
14
+ end
15
+
16
+ def asset(filename)
17
+ path('asset',filename)
18
+ end
19
+
20
+ def controller(filename)
21
+ path('controller',filename)
22
+ end
23
+
24
+ def view(filename)
25
+ path('view',filename)
26
+ end
27
+
28
+ def path(type,filename)
29
+ case type
30
+ when /app/
31
+ Config.app_root+'/'+filename
32
+ when /asset/
33
+ '/assets/'+filename
34
+ when /controller/
35
+ Config.app_root+'/controllers/'+filename
36
+ when /view/
37
+ Config.app_root+'/views/'+filename
38
+ else
39
+ message = "#{type} is not a valid type! Valid types are 'app','asset','controller','view'!"
40
+ raise Speck_Exception.new(message)
41
+ end
42
+ end
43
+
44
+ def js(filename)
45
+ if filename =~ /\.js/
46
+ js = path('assets',filename)
47
+ else
48
+ js = path('assets',filename+'.js')
49
+ end
50
+ "<script src='#{js}' type='text/javascript' charset='utf-8'></script>"
51
+ end
52
+
53
+ def css(filename)
54
+ if filename =~ /\.css/
55
+ style = path('assets',filename)
56
+ else
57
+ style = path('assets',filename+'.css')
58
+ end
59
+ "<link rel='STYLESHEET' href='#{style}' type='text/css'>"
60
+ end
61
+
62
+ def render(template_path)
63
+ Log.render(template_path)
64
+ Tilt.new(template_path).render(self)
65
+ end
66
+
67
+ def session
68
+ @__session
69
+ end
70
+
71
+ def params
72
+ @__params
73
+ end
74
+ end
75
+
76
+ end
@@ -0,0 +1,17 @@
1
+ module Speck
2
+ class Speck_Exception < RuntimeError
3
+ end
4
+
5
+ class Routing_Exception < Speck_Exception
6
+ attr_reader :status, :message
7
+
8
+ def initialize(status, message)
9
+ @status = status
10
+ @message = message
11
+ end
12
+
13
+ def render()
14
+ Tilt.new(Config.app_root+'/exception.html.erb').render(self)
15
+ end
16
+ end
17
+ end
data/lib/speck/log.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'logger'
2
+
3
+ module Speck
4
+ class Log
5
+
6
+ def self.log
7
+ @log ||= Logger.new(Config.app_root+'/server.log', shift_age = 'weekly')
8
+ end
9
+
10
+ def self.render(path)
11
+ write(Logger::INFO, "Renderig: #{path}")
12
+ end
13
+
14
+ def self.request(request)
15
+ write(Logger::INFO,"Starting: #{request.request_method} #{request.fullpath}")
16
+ end
17
+
18
+ def self.dispatch(controller,action,params)
19
+ write(Logger::INFO,"Dispatching: #{controller}.#{action} with #{params}")
20
+ end
21
+
22
+ def self.exception(status,message)
23
+ write(Logger::WARN,"#{status}: #{message}")
24
+ end
25
+
26
+ def self.error(error)
27
+ puts error.backtrace
28
+ write(Logger::ERROR,"500: #{error.message}")
29
+ end
30
+
31
+ def self.write(severity,msg)
32
+ out = "[#{Time.now}] #{msg}\n"
33
+ puts out
34
+ log.add(severity,message=out)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,115 @@
1
+ require 'rack'
2
+ require 'speck/controller'
3
+ require 'speck/log'
4
+ require 'speck/exception'
5
+ require 'speck/config'
6
+
7
+ Dir[Speck::Config.app_root+"/controllers/*.rb"].each {|file| require file }
8
+
9
+
10
+ module Speck
11
+ class Router
12
+
13
+ attr_reader :routes
14
+
15
+ @@HTTP_REQUESTS = [:GET, :PUT, :POST, :DELETE]
16
+
17
+ def initialize(path=nil)
18
+ @routes = {}
19
+ @controller = []
20
+ @base = ''
21
+ @@HTTP_REQUESTS.each{ |req| @routes[req] = {}}
22
+ build_routes(path)
23
+ end
24
+
25
+ def build_routes(path=nil)
26
+ path ||= Config.app_root+'/routes.rb'
27
+ instance_eval(File.read(path))
28
+ end
29
+
30
+ def match(base,controller, &block)
31
+ @base << base
32
+ @controller << controller
33
+ instance_eval(&block)
34
+ @controller.pop()
35
+ @base.chomp!(base)
36
+ end
37
+
38
+ def call(env)
39
+ @request = Rack::Request.new(env)
40
+ @response = process
41
+ @response.finish
42
+ end
43
+
44
+ def symbolize_keys(hash)
45
+ hash.keys.each do |key|
46
+ hash[(key.to_sym rescue key) || key] = hash.delete(key)
47
+ end
48
+ hash
49
+ end
50
+
51
+ def controller_action_params
52
+ routes = @routes[@request.request_method.to_sym]
53
+ valid_routes = routes.keys.select{ |route| matching? route}
54
+ raise Routing_Exception.new(404,'Page not found!') if valid_routes.empty?
55
+ controller, action = routes[valid_routes.first]
56
+ params = extract_params(valid_routes.first)
57
+ params.merge!(symbolize_keys(@request.params)) if @request.form_data?
58
+ [controller, action, params]
59
+ end
60
+
61
+ def matching?(route)
62
+ route_list = route.split('/')
63
+ path_list = @request.path.split('/')
64
+ return false unless path_list.length == route_list.length
65
+ path_list.length.times { |i| return false unless route_list[i][0] == ":" or route_list[i] == path_list[i]}
66
+ true
67
+ end
68
+
69
+ def extract_params(route)
70
+ route_list = route.split('/')
71
+ path_list = @request.path.split('/')
72
+
73
+ params = {}
74
+ path_list.length.times do |i|
75
+ params[route_list[i].sub(":","").to_sym] = path_list[i] if route_list[i][0] == ":"
76
+ end
77
+ params
78
+ end
79
+
80
+ def process
81
+ Log.request(@request)
82
+ begin
83
+ controller, action, params = controller_action_params
84
+ Log.dispatch(controller,action,params)
85
+ session = @request.env['rack.session']
86
+ session[:init] = true #forces session loading
87
+ body = Kernel.const_get(controller).new(session|| {}, params).send(action)
88
+ status = 200
89
+ rescue Routing_Exception => ex
90
+ Log.exception(ex.status, ex.message)
91
+ body = ex.render
92
+ status = ex.status
93
+ rescue RuntimeError => e
94
+ Log.error(e)
95
+ ex = Routing_Exception.new(500,'Server Error!')
96
+ body = ex.render
97
+ status = 500
98
+ end
99
+ resp = Rack::Response.new(body=body, status=status)
100
+ end
101
+
102
+ def add_route(request_type, bindings)
103
+ bindings.each { |route, action| @routes[request_type][@base+route] = [@controller.last,action] }
104
+ end
105
+
106
+ def method_missing(name, *args, &block)
107
+ if @@HTTP_REQUESTS.include?(name.upcase)
108
+ add_route(name.upcase,args[0])
109
+ else
110
+ super(name, *args, &block)
111
+ end
112
+ end
113
+
114
+ end
115
+ end
data/lib/speck.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'speck/log'
2
+ require 'speck/router'
3
+ require 'speck/controller'
4
+ require 'speck/config'
data/server.log ADDED
@@ -0,0 +1 @@
1
+ # Logfile created on 2013-05-12 22:35:54 -0400 by logger.rb/31641
data/speck.gemspec ADDED
@@ -0,0 +1,10 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'speck_gem'
3
+ s.version = '1.0.0'
4
+ s.date = '2013-04-06'
5
+ s.summary = "See documentation"
6
+ s.description = "A simple ruby web framework"
7
+ s.authors = ["David Thomas"]
8
+ s.email = 'davidthomas5412@gmail.com'
9
+ s.files = `git ls-files`.split("\n") - %w[.gitignore]
10
+ end
data/test/config.rb ADDED
File without changes
@@ -0,0 +1,51 @@
1
+ require 'speck'
2
+
3
+ class Location < Speck::Controller
4
+ def index
5
+ "index called"
6
+ end
7
+
8
+ def show
9
+ "id: #{params[:id]}"
10
+ end
11
+
12
+ def template
13
+ @msg = 'template message'
14
+ render('test/template_example.html.erb')
15
+ end
16
+
17
+ def template_with_partial
18
+ @title = "template title"
19
+ @body = "partial body"
20
+ render('test/template2_example.html.erb')
21
+ end
22
+ end
23
+
24
+ class Book < Speck::Controller
25
+ def show
26
+ "id: #{params[:id]}"
27
+ end
28
+ end
29
+
30
+
31
+ class Home < Speck::Controller
32
+ def index
33
+ "index body"
34
+ end
35
+
36
+ def authenticate
37
+ raise RuntimeError
38
+ end
39
+ end
40
+
41
+ class Vacation < Speck::Controller
42
+ def show
43
+ "id: #{params[:id]}"
44
+ end
45
+ end
46
+
47
+ class Photo < Speck::Controller
48
+ def show
49
+ "id1: #{params[:id1]} id2: #{params[:id2]}"
50
+ end
51
+ end
@@ -0,0 +1,60 @@
1
+ require File.dirname(File.expand_path(__FILE__))+'/controller_example.rb'
2
+
3
+ def assert_contain(actual, expected)
4
+ actual =~ expected
5
+ end
6
+
7
+ setup do
8
+ Speck::Log.stubs(:render)
9
+ end
10
+
11
+ test "controller dispatching actions" do
12
+ assert_equal Location.new({},{}).send('index'), "index called"
13
+ assert_equal Location.new({},{:id => 99}).send('show'), "id: 99"
14
+ end
15
+
16
+ test "controller rendering with instance variables" do
17
+ assert_contain Location.new({},{}).send('template'), /template message/
18
+ end
19
+
20
+ test "controller classes don't share param state" do
21
+ assert_equal Location.new({},{:id => 0}).send('show'), "id: 0"
22
+ assert_equal Book.new({},{:id => 1}).send('show'), "id: 1"
23
+ end
24
+
25
+ test "recursive rendering of partials" do
26
+ assert_contain Location.new({},{}).send('template_with_partial'), /template title/
27
+ assert_contain Location.new({},{}).send('template_with_partial'), /partial body/
28
+ end
29
+
30
+ test "session persists accross requests" do
31
+ end
32
+
33
+ test "path" do
34
+ loc = Location.new({},{})
35
+ root = Speck::Config.app_root
36
+ assert_equal loc.path('app','config.rb'), root+'/config.rb'
37
+ assert_equal loc.path('views','photo.html.erb'), root+'/views/photo.html.erb'
38
+ assert_equal loc.path('asset','jquery.js'), '/assets/jquery.js'
39
+ end
40
+
41
+ test "invalid path raises speck exception" do
42
+ loc = Location.new({},{})
43
+ assert_raise Speck::Speck_Exception do
44
+ loc.path('veew','')
45
+ end
46
+ end
47
+
48
+ test "javascript helper" do
49
+ loc = Location.new({},{})
50
+ root = Speck::Config.app_root
51
+ expected = "<script src='/assets/jquery.js' type='text/javascript' charset='utf-8'></script>"
52
+ assert_equal loc.js('jquery'), expected
53
+ end
54
+
55
+ test "css helper" do
56
+ loc = Location.new({},{})
57
+ root = Speck::Config.app_root
58
+ expected = "<link rel='STYLESHEET' href='/assets/style.css' type='text/css'>"
59
+ assert_equal loc.css('style'), expected
60
+ end
data/test/exception.rb ADDED
@@ -0,0 +1,11 @@
1
+ setup do
2
+ Speck::Config.set_app_root('app')
3
+ end
4
+
5
+ test "404 routing exception" do
6
+ ex = Speck::Routing_Exception.new(404,'Page not found!')
7
+ assert_equal ex.status, 404
8
+ assert_equal ex.message, 'Page not found!'
9
+ assert_equal ex.render, "<h1>404</h1>
10
+ <p>Page not found!</p>"
11
+ end
data/test/logger.rb ADDED
@@ -0,0 +1,7 @@
1
+ test "logger is singleton" do
2
+ initial_log = Speck::Log.log
3
+ initial_log.expects(:add)
4
+ Speck::Log.expects(:write)
5
+ Speck::Log.dispatch("controller","acton","params")
6
+ assert_equal Speck::Log.log, initial_log
7
+ end
@@ -0,0 +1 @@
1
+ <%= @body %>
data/test/router.rb ADDED
@@ -0,0 +1,66 @@
1
+ test = File.dirname(File.expand_path(__FILE__))
2
+ require test+'/controller_example.rb'
3
+
4
+ ### To test response
5
+ module Rack
6
+ class Response
7
+ attr_reader :body
8
+ end
9
+ end
10
+
11
+ def expect_request
12
+ Speck::Log.expects(:request)
13
+ Speck::Log.expects(:dispatch)
14
+ end
15
+
16
+ def test_response(r,env,status,body)
17
+ expect_request
18
+ env['rack.session'] ={}
19
+ resp = r.call(env)
20
+ assert_equal resp[2].body(), [body]
21
+ assert_equal resp[0], status
22
+ end
23
+
24
+ setup do
25
+ Speck::Router.new(test+'/routes_example.rb')
26
+ end
27
+
28
+ test 'routes controller action' do |r|
29
+ assert_equal r.routes[:GET]['/'], ['Home','index']
30
+ assert_equal r.routes[:POST]['/login'], ['Home','authenticate']
31
+ end
32
+
33
+ test 'nested routes' do |r|
34
+ assert_equal r.routes[:GET]['/vacations/:id1/photos'], ['Photo','index']
35
+ end
36
+
37
+ test 'route with param' do |r|
38
+ assert_equal r.routes[:PUT]['/vacations/:id'], ['Vacation','update']
39
+ end
40
+
41
+ test 'handle example request' do |r|
42
+ env = {"PATH_INFO"=>"/", "REQUEST_METHOD"=>"GET"}
43
+ test_response(r,env,200,"index body")
44
+ end
45
+
46
+ test 'handle exmple request with parameters' do |r|
47
+ env = {"PATH_INFO"=>"/vacations/99", "REQUEST_METHOD"=>"GET"}
48
+ test_response(r,env,200,"id: 99")
49
+ end
50
+
51
+ test 'handle nested route request with multiple parameters' do |r|
52
+ env = {"PATH_INFO"=>"/vacations/1/photos/2", "REQUEST_METHOD"=>"GET"}
53
+ test_response(r,env,200,"id1: 1 id2: 2")
54
+ end
55
+
56
+ test 'handle 404' do |r|
57
+ env = {"PATH_INFO"=>"facebook", "REQUEST_METHOD"=>"GET"}
58
+ Speck::Log.expects(:exception)
59
+ test_response(r,env,404,"<h1>404</h1>\n<p>Page not found!</p>")
60
+ end
61
+
62
+ test 'handle 500' do |r|
63
+ env = {"PATH_INFO"=>"/login", "REQUEST_METHOD"=>"POST"}
64
+ Speck::Log.expects(:error)
65
+ test_response(r,env,500,"<h1>500</h1>\n<p>Server Error!</p>")
66
+ end
@@ -0,0 +1,16 @@
1
+ match '/','Home' do
2
+ get '' => 'index'
3
+ post 'login' => 'authenticate'
4
+ end
5
+
6
+ match '/vacations','Vacation' do
7
+ get '' => 'index', '/:id'=>'show'
8
+ put '/:id' => 'update'
9
+ post '/:id' => 'edit'
10
+
11
+ match '/:id1/photos','Photo' do
12
+ get '' => 'index', '/:id2' => 'show'
13
+ put '/:id2' => 'update'
14
+ post '/:id2' => 'edit'
15
+ end
16
+ end
@@ -0,0 +1,2 @@
1
+ <h1><%= @title %></h1>
2
+ <p><%= render('test/partial_example.html.erb') %></p>
@@ -0,0 +1 @@
1
+ <p><%= @message %></p>
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: speck_gem
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Thomas
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-06 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A simple ruby web framework
15
+ email: davidthomas5412@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - Gemfile
21
+ - Gemfile.lock
22
+ - README.md
23
+ - Rakefile
24
+ - app/Gemfile
25
+ - app/config.rb
26
+ - app/exception.html.erb
27
+ - app/routes.rb
28
+ - app/server.log
29
+ - app/server.log.20130511
30
+ - lib/speck.rb
31
+ - lib/speck/config.rb
32
+ - lib/speck/controller.rb
33
+ - lib/speck/exception.rb
34
+ - lib/speck/log.rb
35
+ - lib/speck/router.rb
36
+ - server.log
37
+ - speck.gemspec
38
+ - test/config.rb
39
+ - test/controller_example.rb
40
+ - test/controllers.rb
41
+ - test/exception.rb
42
+ - test/logger.rb
43
+ - test/partial_example.html.erb
44
+ - test/router.rb
45
+ - test/routes_example.rb
46
+ - test/template2_example.html.erb
47
+ - test/template_example.html.erb
48
+ homepage:
49
+ licenses: []
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 1.8.24
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: See documentation
72
+ test_files: []