restrack 1.7.0 → 1.8.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.
- data/README.markdown +9 -8
- data/README.markdown.html +25 -10
- data/Rakefile +5 -1
- data/bin/restrack +7 -4
- data/lib/restrack.rb +0 -5
- data/lib/restrack/async_web_service.rb +30 -0
- data/lib/restrack/generator.rb +24 -2
- data/lib/restrack/generator/Gemfile.erb +4 -0
- data/lib/restrack/generator/constants.yaml.erb +31 -0
- data/lib/restrack/generator/loader.rb.erb +1 -1
- data/lib/restrack/resource_request.rb +10 -7
- data/lib/restrack/version.rb +1 -1
- data/test/sample_app_1/config/constants.yaml +3 -0
- data/test/sample_app_1/test/test_controller_inputs.rb +17 -3
- metadata +5 -3
data/README.markdown
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# RESTRack
|
2
2
|
- serving JSON and XML with REST and pleasure.
|
3
3
|
|
4
|
-
## Description
|
4
|
+
## Description
|
5
5
|
RESTRack is a [Rack](http://rack.rubyforge.org/)-based [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller)
|
6
6
|
framework that makes it extremely easy to develop [REST](http://en.wikipedia.org/wiki/Representational_State_Transfer)ful
|
7
7
|
data services. It is inspired by [Rails](http://rubyonrails.org), and follows a few of its conventions. But it has no routes
|
@@ -17,12 +17,8 @@ view directory grouped by controller name subdirectories \(`view/<controller>/<a
|
|
17
17
|
requests will then render the view template with the builder gem, rather than generating XML with XmlSimple.
|
18
18
|
|
19
19
|
|
20
|
-
##
|
21
|
-
###
|
22
|
-
<sudo> gem install restrack
|
23
|
-
|
24
|
-
|
25
|
-
## Why RESTRack when there is Rails?
|
20
|
+
## Rationale
|
21
|
+
### Why RESTRack when there is Rails?
|
26
22
|
[Rails](http://rubyonrails.org/) is a powerful tool for full web applications. RESTRack is targeted at making
|
27
23
|
development of lightweight data services as easy as possible, while still giving you a performant and extensible
|
28
24
|
framework. The primary goal of of the development of RESTRack was to add as little as possible to the framework to give
|
@@ -32,10 +28,15 @@ Rails 3 instantiates approximately 80K more objects than RESTRack to do a hello
|
|
32
28
|
the default setup. Trimming Rails down by eliminating ActiveRecord, ActionMailer, and ActiveResource, it still
|
33
29
|
instantiates over 47K more objects than RESTRack.
|
34
30
|
|
35
|
-
|
31
|
+
### OK, so why RESTRack when there is Sinatra?
|
36
32
|
RESTRack provides a full, albeit small, framework for developing RESTful MVC applications.
|
37
33
|
|
38
34
|
|
35
|
+
## Installation
|
36
|
+
### Using [RubyGems](http://rubygems.org):
|
37
|
+
<sudo> gem install restrack
|
38
|
+
|
39
|
+
|
39
40
|
## CLI Usage:
|
40
41
|
### Generate a new service \(FooBar::WebService\)
|
41
42
|
- restrack generate service foo\_bar
|
data/README.markdown.html
CHANGED
@@ -1,10 +1,19 @@
|
|
1
|
-
|
1
|
+
|
2
|
+
<!doctype html>
|
3
|
+
<html lang="fr">
|
4
|
+
<head>
|
5
|
+
<meta charset="utf-8">
|
6
|
+
<title>RESTRack</title>
|
7
|
+
<link rel="stylesheet" href="http://covertprestige.info/public/css/all.css" />
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<h1>RESTRack</h1>
|
2
11
|
|
3
12
|
<ul>
|
4
13
|
<li>serving JSON and XML with REST and pleasure.</li>
|
5
14
|
</ul>
|
6
15
|
|
7
|
-
<h2>Description
|
16
|
+
<h2>Description</h2>
|
8
17
|
|
9
18
|
<p>RESTRack is a <a href="http://rack.rubyforge.org/">Rack</a>-based <a href="http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller">MVC</a>
|
10
19
|
framework that makes it extremely easy to develop <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a>ful
|
@@ -20,14 +29,9 @@ file, routing relationships are done through supplying custom code blocks to cla
|
|
20
29
|
view directory grouped by controller name subdirectories (<code>view/<controller>/<action>.xml.builder</code>). XML format
|
21
30
|
requests will then render the view template with the builder gem, rather than generating XML with XmlSimple.</p>
|
22
31
|
|
23
|
-
<h2>
|
32
|
+
<h2>Rationale</h2>
|
24
33
|
|
25
|
-
<h3>
|
26
|
-
|
27
|
-
<pre><code><sudo> gem install restrack
|
28
|
-
</code></pre>
|
29
|
-
|
30
|
-
<h2>Why RESTRack when there is Rails?</h2>
|
34
|
+
<h3>Why RESTRack when there is Rails?</h3>
|
31
35
|
|
32
36
|
<p><a href="http://rubyonrails.org/">Rails</a> is a powerful tool for full web applications. RESTRack is targeted at making
|
33
37
|
development of lightweight data services as easy as possible, while still giving you a performant and extensible
|
@@ -38,10 +42,17 @@ the web developer a good application space for developing JSON and XML services.
|
|
38
42
|
the default setup. Trimming Rails down by eliminating ActiveRecord, ActionMailer, and ActiveResource, it still
|
39
43
|
instantiates over 47K more objects than RESTRack.</p>
|
40
44
|
|
41
|
-
<
|
45
|
+
<h3>OK, so why RESTRack when there is Sinatra?</h3>
|
42
46
|
|
43
47
|
<p>RESTRack provides a full, albeit small, framework for developing RESTful MVC applications.</p>
|
44
48
|
|
49
|
+
<h2>Installation</h2>
|
50
|
+
|
51
|
+
<h3>Using <a href="http://rubygems.org">RubyGems</a>:</h3>
|
52
|
+
|
53
|
+
<pre><code><sudo> gem install restrack
|
54
|
+
</code></pre>
|
55
|
+
|
45
56
|
<h2>CLI Usage:</h2>
|
46
57
|
|
47
58
|
<h3>Generate a new service (FooBar::WebService)</h3>
|
@@ -345,3 +356,7 @@ Software.</p>
|
|
345
356
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
346
357
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
347
358
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
|
359
|
+
|
360
|
+
</body>
|
361
|
+
</html>
|
362
|
+
|
data/Rakefile
CHANGED
@@ -38,8 +38,12 @@ Rake::TestTask.new('test4') { |t|
|
|
38
38
|
t.pattern = 'test/sample_app_4/**/test_*.rb'
|
39
39
|
}
|
40
40
|
|
41
|
-
|
42
41
|
desc 'Run sample_app_5 tests.'
|
43
42
|
Rake::TestTask.new('test5') { |t|
|
44
43
|
t.pattern = 'test/sample_app_5/**/test_*.rb'
|
45
44
|
}
|
45
|
+
|
46
|
+
desc 'Run async app 1 tests.'
|
47
|
+
Rake::TestTask.new('asynctest1') { |t|
|
48
|
+
t.pattern = 'test/sample_app_async_1/**/test_*.rb'
|
49
|
+
}
|
data/bin/restrack
CHANGED
@@ -12,7 +12,10 @@ when :generate, :gen, :g
|
|
12
12
|
case noun.to_sym
|
13
13
|
when :service, :serv, :s
|
14
14
|
puts "Generating new RESTRack service #{name}..."
|
15
|
-
RESTRack::Generator.
|
15
|
+
RESTRack::Generator.generate_synchronous_service( name )
|
16
|
+
when :asynchronous_service, :asynch_service, :async_serv, :async, :as
|
17
|
+
puts "Generating new RESTRack service #{name}..."
|
18
|
+
RESTRack::Generator.generate_asynchronous_service( name )
|
16
19
|
when :controller, :cont, :c
|
17
20
|
predicate = ARGV[3] ? ARGV[3].to_sym : nil
|
18
21
|
case predicate
|
@@ -30,6 +33,6 @@ when :server, :s
|
|
30
33
|
options = { :Port => noun || 9292, :config => 'config.ru' }
|
31
34
|
options.merge({ :environment => ARGV[2] }) unless ARGV[2].nil?
|
32
35
|
Rack::Server.start( options )
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
when :version, :v
|
37
|
+
puts "Currently using RESTRack version " + RESTRack::VERSION.to_s + "."
|
38
|
+
end
|
data/lib/restrack.rb
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
|
3
|
+
module RESTRack
|
4
|
+
class AsyncWebService
|
5
|
+
AsyncResponse = [-1, {}, []].freeze
|
6
|
+
|
7
|
+
# Establish the namespace pointer.
|
8
|
+
def initialize
|
9
|
+
RESTRack::CONFIG[:SERVICE_NAME] = self.class.to_s.split('::')[0].to_sym
|
10
|
+
@request_hook = RESTRack::Hooks.new if RESTRack.const_defined?(:Hooks)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Handle requests in the Rack way.
|
14
|
+
def call( env )
|
15
|
+
EventMachine::defer do
|
16
|
+
resource_request = RESTRack::ResourceRequest.new( :request => Rack::Request.new(env) )
|
17
|
+
unless @request_hook.nil? or (RESTRack::CONFIG.has_key?(:PRE_PROCESSOR_DISABLED) and RESTRack::CONFIG[:PRE_PROCESSOR_DISABLED])
|
18
|
+
@request_hook.pre_processor(resource_request)
|
19
|
+
end
|
20
|
+
response = RESTRack::Response.new(resource_request)
|
21
|
+
unless @request_hook.nil? or (RESTRack::CONFIG.has_key?(:POST_PROCESSOR_DISABLED) and RESTRack::CONFIG[:POST_PROCESSOR_DISABLED])
|
22
|
+
@request_hook.post_processor(response)
|
23
|
+
end
|
24
|
+
env['async.callback'].call response.output
|
25
|
+
end
|
26
|
+
AsyncResponse
|
27
|
+
end # method call
|
28
|
+
|
29
|
+
end # class WebService
|
30
|
+
end # module RESTRack
|
data/lib/restrack/generator.rb
CHANGED
@@ -12,7 +12,8 @@ module RESTRack
|
|
12
12
|
:constants => 'constants.yaml.erb',
|
13
13
|
:controller => 'controller.rb.erb',
|
14
14
|
:descendant_controller => 'descendant_controller.rb.erb',
|
15
|
-
:hooks => 'hooks.rb.erb'
|
15
|
+
:hooks => 'hooks.rb.erb',
|
16
|
+
:gemfile => 'Gemfile.erb'
|
16
17
|
}
|
17
18
|
|
18
19
|
class << self
|
@@ -36,7 +37,9 @@ module RESTRack
|
|
36
37
|
FileUtils.makedirs("#{base_dir}/views/#{name}")
|
37
38
|
end
|
38
39
|
|
39
|
-
#
|
40
|
+
# The guts for generating a new RESTRack service. The loader.rb template
|
41
|
+
# will create a RESTRack::WebService or RESTRack::AsyncWebService based on
|
42
|
+
# the value of @async.
|
40
43
|
def generate_service(name)
|
41
44
|
FileUtils.makedirs("#{name}/config")
|
42
45
|
FileUtils.makedirs("#{name}/controllers")
|
@@ -59,6 +62,25 @@ module RESTRack
|
|
59
62
|
template = get_template_for( :hooks )
|
60
63
|
resultant_string = template.result( get_binding_for_service( name ) )
|
61
64
|
File.open("#{name}/hooks.rb", 'w') {|f| f.puts resultant_string }
|
65
|
+
|
66
|
+
# Added following lines to generate 'Gemfile' automatically.
|
67
|
+
template = get_template_for( :gemfile )
|
68
|
+
resultant_string = template.result( get_binding_for_service( name ) )
|
69
|
+
File.open("#{name}/Gemfile", 'w') {|f| f.puts resultant_string }
|
70
|
+
end
|
71
|
+
# Generate a new RESTRack service. This does not use EventMachine and can
|
72
|
+
# be used with any Rack supported web server.
|
73
|
+
def generate_synchronous_service(name)
|
74
|
+
@async = false
|
75
|
+
generate_service(name)
|
76
|
+
@async = nil
|
77
|
+
end
|
78
|
+
# Generate a new RESTRack service that uses EventMachine. This can only be
|
79
|
+
# used with web servers that use or support EventMachine (Thin, Rainbows).
|
80
|
+
def generate_asynchronous_service(name)
|
81
|
+
@async = true
|
82
|
+
generate_service(name)
|
83
|
+
@async = nil
|
62
84
|
end
|
63
85
|
|
64
86
|
private
|
@@ -22,3 +22,34 @@
|
|
22
22
|
:ROOT_RESOURCE_ACCEPT: []
|
23
23
|
# These are the resources which cannot be accessed from the root of your web service. Use either this or ROOT_RESOURCE_ACCEPT as a blacklist or whitelist to establish routing (relationships defined in resource controllers define further routing).
|
24
24
|
:ROOT_RESOURCE_DENY: []
|
25
|
+
|
26
|
+
# A list of input parameters which should not be output to logs:
|
27
|
+
#:PARAMS_NOT_LOGGABLE: [:password]
|
28
|
+
|
29
|
+
# :TRANSCODE: and :FORCE_ENCODING: are optional config settings
|
30
|
+
# String#encode will be called when this value is set
|
31
|
+
#:TRANSCODE: ISO-8859-1 #or UTF-8 etc
|
32
|
+
# String#force_encoding will be called when this value is set
|
33
|
+
#:FORCE_ENCODING: ISO-8859-1
|
34
|
+
|
35
|
+
# :CORS: is an optional config setting
|
36
|
+
# CORS Header configuration
|
37
|
+
# Supported:
|
38
|
+
# - Access-Control-Allow-Origin: http://localhost
|
39
|
+
# - Access-Control-Allow-Methods: POST, GET
|
40
|
+
# List of all:
|
41
|
+
# - Access-Control-Allow-Origin: <origin> | *
|
42
|
+
# e.g. Access-Control-Allow-Origin: http://mozilla.com
|
43
|
+
# - Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
|
44
|
+
# - Access-Control-Max-Age: <delta-seconds>
|
45
|
+
# - Access-Control-Allow-Credentials: true | false
|
46
|
+
# - Access-Control-Allow-Methods: <method>[, <method>]*
|
47
|
+
# e.g. Access-Control-Allow-Methods: POST, GET
|
48
|
+
# - Access-Control-Allow-Headers: <field-name>[, <field-name>]*
|
49
|
+
#:CORS:
|
50
|
+
# Access-Control-Allow-Origin: http://restrack.me
|
51
|
+
# Access-Control-Allow-Methods: POST, GET
|
52
|
+
|
53
|
+
# :PRE_PROCESSOR_DISABLED: and :POST_PROCESSOR_DISABLED: are optional config settings and are false by default
|
54
|
+
#:PRE_PROCESSOR_DISABLED: true
|
55
|
+
#:POST_PROCESSOR_DISABLED: true
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'restrack'
|
2
2
|
|
3
3
|
module <%= @service_name.camelize %>; end
|
4
|
-
class <%= @service_name.camelize %>::WebService < RESTRack
|
4
|
+
class <%= @service_name.camelize %>::WebService < RESTRack::<%= @async ? 'Async' : '' %>WebService; end
|
5
5
|
|
6
6
|
RESTRack::CONFIG = RESTRack::load_config(File.join(File.dirname(__FILE__), 'config/constants.yaml'))
|
7
7
|
RESTRack::CONFIG[:ROOT] = File.dirname(__FILE__)
|
@@ -15,9 +15,6 @@ module RESTRack
|
|
15
15
|
@request.env.select {|k,v| k.start_with? 'HTTP_'}.each do |k,v|
|
16
16
|
@headers[k.sub(/^HTTP_/, '')] = v
|
17
17
|
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def prepare
|
21
18
|
# MIME type should be determined before raising any exceptions for proper error reporting
|
22
19
|
# Set up the initial routing.
|
23
20
|
@url_chain = @request.path_info.split('/')
|
@@ -32,16 +29,17 @@ module RESTRack
|
|
32
29
|
end
|
33
30
|
# Determine MIME type from extension
|
34
31
|
@mime_type = get_mime_type_from( extension )
|
32
|
+
end
|
33
|
+
|
34
|
+
def prepare
|
35
35
|
# Now safe to raise exceptions
|
36
36
|
raise HTTP400BadRequest, "Request path of #{@request.path_info} is invalid" if @request.path_info.include?('//')
|
37
|
-
|
38
37
|
# For CORS support
|
39
38
|
if RESTRack::CONFIG[:CORS]
|
40
39
|
raise HTTP403Forbidden if @headers['Origin'].nil?
|
41
40
|
raise HTTP403Forbidden unless RESTRack::CONFIG[:CORS]['Access-Control-Allow-Origin'] == '*' or RESTRack::CONFIG[:CORS]['Access-Control-Allow-Origin'].include?(@headers['Origin'])
|
42
41
|
raise HTTP403Forbidden unless @request.env['REQUEST_METHOD'] == 'OPTIONS' or RESTRack::CONFIG[:CORS]['Access-Control-Allow-Methods'] == '*' or RESTRack::CONFIG[:CORS]['Access-Control-Allow-Methods'].include?(@request.env['REQUEST_METHOD'])
|
43
42
|
end
|
44
|
-
|
45
43
|
# Pull input data from POST body
|
46
44
|
@post_params = parse_body( @request )
|
47
45
|
@get_params = parse_query_string( @request )
|
@@ -53,7 +51,6 @@ module RESTRack
|
|
53
51
|
end
|
54
52
|
@params.symbolize!
|
55
53
|
log_request_params(@params)
|
56
|
-
|
57
54
|
# Pull first controller from URL
|
58
55
|
@active_resource_name = @url_chain.shift
|
59
56
|
unless @active_resource_name.nil? or RESTRack.controller_exists?(@active_resource_name)
|
@@ -69,7 +66,13 @@ module RESTRack
|
|
69
66
|
end
|
70
67
|
|
71
68
|
def log_request_params(params_hash)
|
72
|
-
|
69
|
+
params_to_log = params_hash.clone
|
70
|
+
if RESTRack::CONFIG[:PARAMS_NOT_LOGGABLE]
|
71
|
+
params_to_log.each_key do |param|
|
72
|
+
params_to_log[param] = '*****' if RESTRack::CONFIG[:PARAMS_NOT_LOGGABLE].include?(param.to_s)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
RESTRack.request_log.debug 'Combined Request Params: ' + params_to_log.inspect
|
73
76
|
end
|
74
77
|
|
75
78
|
# Call the next entity in the path stack.
|
data/lib/restrack/version.rb
CHANGED
@@ -27,6 +27,9 @@
|
|
27
27
|
# The stack trace will not be added to 500 response body by default, set to true to enable.
|
28
28
|
:SHOW_STACK: true
|
29
29
|
|
30
|
+
# A list of input parameters which should not be output to logs:
|
31
|
+
:PARAMS_NOT_LOGGABLE: [ password ]
|
32
|
+
|
30
33
|
# :TRANSCODE: and :FORCE_ENCODING: are optional config settings
|
31
34
|
# String#encode will be called when this value is set
|
32
35
|
#:TRANSCODE: ISO-8859-1 #or UTF-8 etc
|
@@ -21,7 +21,7 @@ class SampleApp::TestControllerInputs < Test::Unit::TestCase
|
|
21
21
|
test_val = { :test => '1', :hello => 'world', 'get?' => 'true' }.to_json
|
22
22
|
assert_equal test_val, output[2][0]
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def test_FUBAR_params
|
26
26
|
env = Rack::MockRequest.env_for('/foo_bar/echo_get?test=1&hello=world', {
|
27
27
|
:method => 'DELETE'
|
@@ -60,7 +60,7 @@ class SampleApp::TestControllerInputs < Test::Unit::TestCase
|
|
60
60
|
end
|
61
61
|
assert_equal test_val, output[2][0]
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
def test_post_xml
|
65
65
|
test_val = XmlSimple.xml_out({ :echo => 'niner' }, 'AttrPrefix' => true, 'XmlDeclaration' => true, 'NoIndent' => true)
|
66
66
|
env = Rack::MockRequest.env_for('/foo_bar/echo.xml', {
|
@@ -74,7 +74,7 @@ class SampleApp::TestControllerInputs < Test::Unit::TestCase
|
|
74
74
|
end
|
75
75
|
assert_equal test_val, output[2][0]
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
def test_post_text
|
79
79
|
test_val = 'OPCODE=PEBKAC'
|
80
80
|
env = Rack::MockRequest.env_for('/foo_bar/echo.txt', {
|
@@ -88,4 +88,18 @@ class SampleApp::TestControllerInputs < Test::Unit::TestCase
|
|
88
88
|
end
|
89
89
|
assert_equal test_val, output[2][0]
|
90
90
|
end
|
91
|
+
|
92
|
+
def test_post_password_param_no_log
|
93
|
+
test_val = { :echo => 'niner', :password => 'my_password' }.to_json
|
94
|
+
env = Rack::MockRequest.env_for('/foo_bar/echo', {
|
95
|
+
:method => 'POST',
|
96
|
+
:input => test_val,
|
97
|
+
'CONTENT_TYPE' => 'application/json'
|
98
|
+
})
|
99
|
+
output = ''
|
100
|
+
assert_nothing_raised do
|
101
|
+
output = @ws.call(env)
|
102
|
+
end
|
103
|
+
assert_equal test_val, output[2][0]
|
104
|
+
end
|
91
105
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restrack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -164,7 +164,9 @@ files:
|
|
164
164
|
- Rakefile
|
165
165
|
- bin/restrack
|
166
166
|
- lib/restrack.rb
|
167
|
+
- lib/restrack/async_web_service.rb
|
167
168
|
- lib/restrack/generator.rb
|
169
|
+
- lib/restrack/generator/Gemfile.erb
|
168
170
|
- lib/restrack/generator/config.ru.erb
|
169
171
|
- lib/restrack/generator/constants.yaml.erb
|
170
172
|
- lib/restrack/generator/controller.rb.erb
|
@@ -255,7 +257,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
255
257
|
version: '0'
|
256
258
|
requirements: []
|
257
259
|
rubyforge_project: restrack
|
258
|
-
rubygems_version: 1.8.
|
260
|
+
rubygems_version: 1.8.24
|
259
261
|
signing_key:
|
260
262
|
specification_version: 3
|
261
263
|
summary: A lightweight MVC framework developed specifically for JSON (and XML) REST
|