restrack 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/Gemfile +4 -0
  2. data/README.rdoc +71 -0
  3. data/Rakefile +32 -0
  4. data/bin/restrack +23 -0
  5. data/config/constants.yaml +8 -0
  6. data/lib/restrack/generator/constants.yaml.erb +24 -0
  7. data/lib/restrack/generator/controller.rb.erb +35 -0
  8. data/lib/restrack/generator/loader.rb.erb +21 -0
  9. data/lib/restrack/generator.rb +93 -0
  10. data/lib/restrack/http_status.rb +10 -0
  11. data/lib/restrack/resource_controller.rb +192 -0
  12. data/lib/restrack/resource_request.rb +135 -0
  13. data/lib/restrack/support.rb +56 -0
  14. data/lib/restrack/version.rb +3 -0
  15. data/lib/restrack/web_service.rb +66 -0
  16. data/lib/restrack.rb +24 -0
  17. data/restrack.gemspec +28 -0
  18. data/test/sample_app_1/config/constants.yaml +25 -0
  19. data/test/sample_app_1/controllers/bat_controller.rb +9 -0
  20. data/test/sample_app_1/controllers/baz_controller.rb +9 -0
  21. data/test/sample_app_1/controllers/baza_controller.rb +11 -0
  22. data/test/sample_app_1/controllers/bazu_controller.rb +16 -0
  23. data/test/sample_app_1/controllers/foo_bar_controller.rb +62 -0
  24. data/test/sample_app_1/loader.rb +31 -0
  25. data/test/sample_app_1/test/test_controller_actions.rb +122 -0
  26. data/test/sample_app_1/test/test_controller_modifiers.rb +153 -0
  27. data/test/sample_app_1/test/test_formats.rb +119 -0
  28. data/test/sample_app_1/test/test_resource_request.rb +160 -0
  29. data/test/sample_app_1/test/test_web_service.rb +27 -0
  30. data/test/sample_app_1/views/foo_bar/show.xml.builder +4 -0
  31. data/test/sample_app_2/config/constants.yaml +24 -0
  32. data/test/sample_app_2/controllers/bat_controller.rb +9 -0
  33. data/test/sample_app_2/controllers/baz_controller.rb +9 -0
  34. data/test/sample_app_2/controllers/baza_controller.rb +11 -0
  35. data/test/sample_app_2/controllers/bazu_controller.rb +8 -0
  36. data/test/sample_app_2/controllers/foo_bar_controller.rb +59 -0
  37. data/test/sample_app_2/loader.rb +31 -0
  38. data/test/sample_app_2/test/test_controller_modifiers.rb +121 -0
  39. data/test/sample_app_2/test/test_resource_request.rb +71 -0
  40. data/test/sample_app_2/views/foo_bar/show.xml.builder +4 -0
  41. data/test/sample_app_3/config/constants.yaml +24 -0
  42. data/test/sample_app_3/controllers/bat_controller.rb +9 -0
  43. data/test/sample_app_3/controllers/baz_controller.rb +9 -0
  44. data/test/sample_app_3/controllers/baza_controller.rb +11 -0
  45. data/test/sample_app_3/controllers/bazu_controller.rb +8 -0
  46. data/test/sample_app_3/controllers/foo_bar_controller.rb +59 -0
  47. data/test/sample_app_3/loader.rb +31 -0
  48. data/test/sample_app_3/test/test_resource_request.rb +42 -0
  49. data/test/sample_app_3/views/foo_bar/show.xml.builder +4 -0
  50. data/test/sample_app_4/config/constants.yaml +24 -0
  51. data/test/sample_app_4/controllers/bar_controller.rb +11 -0
  52. data/test/sample_app_4/controllers/baz_controller.rb +15 -0
  53. data/test/sample_app_4/controllers/foo_controller.rb +21 -0
  54. data/test/sample_app_4/loader.rb +31 -0
  55. data/test/sample_app_4/test/test_controller_modifiers.rb +28 -0
  56. data/test/sample_app_4/test/test_formats.rb +49 -0
  57. data/test/sample_app_4/views/alphatest.png +0 -0
  58. data/test/test_support.rb +20 -0
  59. data/test/test_web_service.rb +31 -0
  60. metadata +238 -0
@@ -0,0 +1,56 @@
1
+ module RESTRack
2
+
3
+ class << self
4
+ def log; @@log; end
5
+ def request_log; @@request_log; end
6
+ end # of class methods
7
+
8
+ def self.load_config(file)
9
+ config = YAML.load_file(file)
10
+ # Open the logs on spin up.
11
+ @@log ||= Logger.new( config[:LOG] )
12
+ @@log.level = Logger.const_get( config[:LOG_LEVEL] )
13
+ @@request_log ||= Logger.new( config[:REQUEST_LOG] )
14
+ @@request_log.level = Logger.const_get( config[:LOG_LEVEL] )
15
+ # Do config validations
16
+ if config[:ROOT_RESOURCE_ACCEPT].is_a?(Array) and config[:ROOT_RESOURCE_ACCEPT].length == 1 and config[:ROOT_RESOURCE_ACCEPT][0].lstrip.rstrip == ''
17
+ config[:ROOT_RESOURCE_ACCEPT] = nil
18
+ @@log.warn 'Improper format for RESTRack::CONFIG[:ROOT_RESOURCE_ACCEPT], should be nil or empty array not array containing empty string.'
19
+ end
20
+ if not config[:ROOT_RESOURCE_ACCEPT].blank? and not config[:DEFAULT_RESOURCE].blank? and not config[:ROOT_RESOURCE_ACCEPT].include?( config[:DEFAULT_RESOURCE] )
21
+ @@log.warn 'RESTRack::CONFIG[:DEFAULT_RESOURCE] should be a member of RESTRack::CONFIG[:ROOT_RESOURCE_ACCEPT].'
22
+ end
23
+ config
24
+ end
25
+
26
+ def self.mime_type_for(format)
27
+ MIME::Types.type_for(format.to_s.downcase)[0]
28
+ end
29
+
30
+ def self.resource_exists?(resource_name)
31
+ klass = controller_class_for( resource_name )
32
+ return klass.is_a?(Class)
33
+ rescue NameError
34
+ return false
35
+ end
36
+
37
+ def self.controller_class_for(resource_name)
38
+ Kernel.const_get( RESTRack::CONFIG[:SERVICE_NAME].to_sym ).const_get( controller_name(resource_name).to_sym )
39
+ end
40
+
41
+ def self.controller_name(resource_name)
42
+ "#{resource_name.camelize}Controller".to_sym
43
+ end
44
+
45
+ end
46
+
47
+ # Courtesy of Rails' ActiveSupport, thank you DHH et al.
48
+ class Object
49
+ def blank?
50
+ respond_to?(:empty?) ? empty? : !self
51
+ end
52
+ end
53
+
54
+ # We will support ".text" as an extension
55
+ MIME::Types['text/plain'][0].extensions << 'text'
56
+ MIME::Types.index_extensions( MIME::Types['text/plain'][0] )
@@ -0,0 +1,3 @@
1
+ module RESTRack
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,66 @@
1
+ module RESTRack
2
+ class WebService
3
+
4
+ def initialize
5
+ # Establish the namespace pointer.
6
+ RESTRack::CONFIG[:SERVICE_NAME] = self.class.to_s.split('::')[0].to_sym
7
+ end
8
+
9
+ def call( env )
10
+ # Handle requests.
11
+ request = Rack::Request.new(env)
12
+ begin
13
+ resource_request = RESTRack::ResourceRequest.new( :request => request )
14
+ resource_request.locate
15
+ resource_request.call
16
+ response = resource_request.output
17
+ return valid resource_request, response
18
+ rescue Exception => exception
19
+ return caught resource_request, exception
20
+ end
21
+ end # method call
22
+
23
+ private
24
+
25
+ def valid( resource_request, response )
26
+ # Return HTTP200OK SUCCESS
27
+ RESTRack.request_log.debug "'#{resource_request.mime_type.to_s}' response data (Request ID: #{resource_request.request_id})\n" + response.to_s unless not response.respond_to?( :to_s )
28
+ RESTRack.request_log.info "HTTP200OK - (Request ID: #{resource_request.request_id})"
29
+ return [200, {'Content-Type' => resource_request.content_type}, response ]
30
+ end
31
+
32
+ def caught( resource_request, exception )
33
+ # Return appropriate response code and messages per raised exception type.
34
+ if resource_request && resource_request.request_id
35
+ RESTRack.request_log.info exception.message + "(Request ID: #{resource_request.request_id})"
36
+ else
37
+ RESTRack.request_log.info exception.message
38
+ end
39
+ case
40
+ when exception.is_a?( HTTP400BadRequest )
41
+ return [400, {'Content-Type' => 'text/plain'}, exception.message + "\nThe request cannot be fulfilled due to bad syntax." ]
42
+ when exception.is_a?( HTTP401Unauthorized )
43
+ return [401, {'Content-Type' => 'text/plain'}, exception.message + "\nYou have failed authentication for access to the resource." ]
44
+ when exception.is_a?( HTTP403Forbidden )
45
+ return [403, {'Content-Type' => 'text/plain'}, exception.message + "\nYou are forbidden to access that resource." ]
46
+ when exception.is_a?( HTTP404ResourceNotFound )
47
+ return [404, {'Content-Type' => 'text/plain'}, exception.message + "\nThe resource you requested could not be found." ]
48
+ when exception.is_a?( HTTP405MethodNotAllowed )
49
+ return [405, {'Content-Type' => 'text/plain'}, exception.message + "\nThe resource you requested does not support the request method provided." ]
50
+ when exception.is_a?( HTTP409Conflict )
51
+ return [409, {'Content-Type' => 'text/plain'}, exception.message + "\nThe resource you requested is in a conflicted state." ]
52
+ when exception.is_a?( HTTP410Gone )
53
+ return [410, {'Content-Type' => 'text/plain'}, exception.message + "\nThe resource you requested is no longer available." ]
54
+ else # HTTP500ServerError
55
+ msg = exception.message + "\n\n" + exception.backtrace.join("\n")
56
+ if resource_request && resource_request.request_id
57
+ RESTRack.log.error msg + " (Request ID: #{resource_request.request_id})\n\n"
58
+ else
59
+ RESTRack.log.error msg
60
+ end
61
+ return [500, {'Content-Type' => 'text/plain'}, msg ]
62
+ end # case Exception
63
+ end # method caught
64
+
65
+ end # class WebService
66
+ end # module RESTRack
data/lib/restrack.rb ADDED
@@ -0,0 +1,24 @@
1
+ %w[
2
+ rack
3
+ logger
4
+ find
5
+ yaml
6
+ rubygems
7
+ json
8
+ xmlsimple
9
+ builder
10
+ active_support/inflector
11
+ mime/types
12
+ ].each do |file|
13
+ require file
14
+ end
15
+
16
+ # Dynamically load all files in lib
17
+ Find.find( File.join(File.dirname(__FILE__)) ) do |file|
18
+ next if File.extname(file) != '.rb'
19
+ puts 'loading file ' + file
20
+ require file
21
+ end
22
+
23
+ include HTTPStatus
24
+ include ActiveSupport::Inflector
data/restrack.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "restrack/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "restrack"
7
+ s.version = RESTRack::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Chris St. John']
10
+ s.email = ['chris@stjohnstudios.com']
11
+ s.homepage = 'http://github.com/stjohncj'
12
+ s.summary = %q{A lightweight MVC framework developed specifically for JSON and XML REST services.}
13
+ s.description = %q{RESTRack is an MVC framework that makes it extremely easy to develop RESTful data services. It is inspired by Rails, and follows some of its conventions, but aims at being lightweight and easy to use.}
14
+
15
+ s.rubyforge_project = "restrack"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_runtime_dependency 'json'
23
+ s.add_runtime_dependency 'xml-simple', '>= 1.0.13'
24
+ s.add_runtime_dependency 'builder'
25
+ s.add_runtime_dependency 'activesupport'
26
+ s.add_runtime_dependency 'mime-types'
27
+
28
+ end
@@ -0,0 +1,25 @@
1
+ #GENERATOR-CONST# -DO NOT REMOVE OR CHANGE THIS LINE- Application-Namespace => SampleApp
2
+ #
3
+ # = constants.yaml
4
+ # This is where RESTRack applications define the constants relevant to their particular
5
+ # application that are used by the RESTRack base classes.
6
+
7
+ # Application log path definition
8
+ :LOG: '/var/log/restrack/sample_app.log'
9
+ # Request log path definition
10
+ :REQUEST_LOG: '/var/log/restrack/sample_app.request.log'
11
+
12
+ # Logger object levels
13
+ :LOG_LEVEL: :DEBUG # Logger object level
14
+ :REQUEST_LOG_LEVEL: :DEBUG # Logger object level
15
+
16
+ # Supported formats are :JSON, :XML, :YAML, :BIN, :TEXT
17
+ :DEFAULT_FORMAT: :JSON
18
+ # The resource which will handle root level requests where the name is not specified. Best for users of this not to implement method_missing in their default controller, unless they are checking for bad URI.
19
+ # This setting ('bazu') won't work because of :ROOT_RESOURCE_ACCEPT VALUE (:DEFAULT_RESOURCE should be a member of :ROOT_RESOURCE_ACCEPT).
20
+ :DEFAULT_RESOURCE: 'bazu'
21
+
22
+ # These are the resources which can be accessed from the root of your web service. If left empty, all resources are available at the root.
23
+ :ROOT_RESOURCE_ACCEPT: [ 'foo_bar' ]
24
+ # 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).
25
+ :ROOT_RESOURCE_DENY: [ 'baz' ]
@@ -0,0 +1,9 @@
1
+ class SampleApp::BatController < RESTRack::ResourceController
2
+
3
+ def show(id)
4
+ return { :WOM => 'BAT!' } if id == 777
5
+ return { :WOM => 'NOBAT!' } if id == '777'
6
+ return { :SUHWING => 'BATTER' }
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ class SampleApp::BazController < RESTRack::ResourceController
2
+
3
+ def show(id)
4
+ return { :BAZ => 'HOLA!' } if id == 777
5
+ return { :BAZ => 'ALOHA!' } if id == '777'
6
+ return { :OTHER => 'YUP' }
7
+ end
8
+
9
+ end
@@ -0,0 +1,11 @@
1
+ class SampleApp::BazaController < RESTRack::ResourceController
2
+
3
+ keyed_with_type Fixnum
4
+
5
+ def show(id)
6
+ return { :BAZA => 'YESSIR' } if id == 1
7
+ return { :NOWAY => 'JOSE' } if id == 8
8
+ return { :NOTTODAY => 'JOSEPH' }
9
+ end
10
+
11
+ end
@@ -0,0 +1,16 @@
1
+ class SampleApp::BazuController < RESTRack::ResourceController
2
+
3
+ def show(id)
4
+ return 1 if id == 1
5
+ return 0
6
+ end
7
+
8
+ def index
9
+ return [
10
+ { :id => 1, :val => 111 },
11
+ { :id => 2, :val => 222 },
12
+ { :id => 3, :val => 333 }
13
+ ]
14
+ end
15
+
16
+ end
@@ -0,0 +1,62 @@
1
+ class SampleApp::FooBarController < RESTRack::ResourceController
2
+
3
+ has_direct_relationship_to( :baz, :as => :baz ) do |id|
4
+ if id =='144'
5
+ output = '777'
6
+ else
7
+ output = '666'
8
+ end
9
+ output # You can't "return" from a Proc! It will do a "return" in the outer method. Remember a "Proc" is not a Method.
10
+ end
11
+
12
+ has_direct_relationship_to( :bat, :as => :slugger ) do |id|
13
+ if id =='144'
14
+ output = '777'
15
+ else
16
+ output = '666'
17
+ end
18
+ output # You can't "return" from a Proc! It will do a "return" in the outer method. Remember a "Proc" is not a Method.
19
+ end
20
+
21
+ has_direct_relationships_to( :baza, :as => :children ) do |id|
22
+ [1,2,3,4,5,6,7,8,9]
23
+ end
24
+
25
+ has_mapped_relationships_to( :bazu, :as => :maps ) do |id|
26
+ {
27
+ :first => 1,
28
+ :second => 2,
29
+ :third => 3
30
+ }
31
+ end
32
+
33
+ def index
34
+ [1,2,3,4,5,6,7]
35
+ end
36
+ def create
37
+ { :success => true }
38
+ end
39
+ def replace
40
+ { :success => true }
41
+ end
42
+ def drop
43
+ { :success => true }
44
+ end
45
+
46
+ def show(id)
47
+ if id == '1234567890'
48
+ return { :foo => 'abc', :bar => '123', 'baz' => 456, :more => { :one => 1, :two => [1,2], :three => :deep_fu } }
49
+ end
50
+ { :foo => 'bar', :baz => 123 }
51
+ end
52
+ def update(id)
53
+ { :success => true }
54
+ end
55
+ def destroy(id)
56
+ { :success => true }
57
+ end
58
+ def add(id)
59
+ { :success => true }
60
+ end
61
+
62
+ end
@@ -0,0 +1,31 @@
1
+ # for development only
2
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__),'../../lib'))
3
+ #####
4
+ require 'restrack'
5
+
6
+ module SampleApp; end
7
+ class SampleApp::WebService < RESTRack::WebService; end
8
+
9
+ RESTRack::CONFIG = RESTRack::load_config(File.join(File.dirname(__FILE__), 'config/constants.yaml'))
10
+ RESTRack::CONFIG[:ROOT] = File.dirname(__FILE__)
11
+
12
+ # Dynamically load all controllers
13
+ Find.find( File.join(File.dirname(__FILE__), 'controllers') ) do |file|
14
+ next if File.extname(file) != '.rb'
15
+ require file
16
+ end
17
+
18
+ if File.directory?( File.join(File.dirname(__FILE__), 'models') )
19
+ # Dynamically load all models
20
+ Find.find( File.join(File.dirname(__FILE__), 'models') ) do |file|
21
+ next if File.extname(file) != '.rb'
22
+ require file
23
+ end
24
+ end
25
+
26
+ puts "sample_app_1 RESTRack::CONFIG:\n"
27
+ config = RESTRack::CONFIG.keys.map {|c| c.to_s }.sort
28
+ config.each do |key|
29
+ puts "\t" + key + ' => ' + RESTRack::CONFIG[key.to_sym].to_s
30
+ end
31
+ puts "\n"
@@ -0,0 +1,122 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'rack/test'
4
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','loader'))
5
+ require 'pp'
6
+
7
+ class SampleApp::TestControllerActions < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @ws = SampleApp::WebService.new
11
+ end
12
+
13
+ def test_show
14
+ env = Rack::MockRequest.env_for('/foo_bar/144', {
15
+ :method => 'GET'
16
+ })
17
+ output = ''
18
+ assert_nothing_raised do
19
+ output = @ws.call(env)
20
+ end
21
+ test_val = { :foo => 'bar', :baz => 123 }.to_json
22
+ assert_equal test_val, output[2]
23
+ end
24
+
25
+ def test_update
26
+ env = Rack::MockRequest.env_for('/foo_bar/144', {
27
+ :method => 'PUT'
28
+ })
29
+ output = ''
30
+ assert_nothing_raised do
31
+ output = @ws.call(env)
32
+ end
33
+ test_val = { :success => true }.to_json
34
+ assert_equal test_val, output[2]
35
+ end
36
+
37
+ def test_add
38
+ env = Rack::MockRequest.env_for('/foo_bar/144', {
39
+ :method => 'POST'
40
+ })
41
+ output = ''
42
+ assert_nothing_raised do
43
+ output = @ws.call(env)
44
+ end
45
+ test_val = { :success => true }.to_json
46
+ assert_equal test_val, output[2]
47
+ end
48
+
49
+ def test_destroy
50
+ env = Rack::MockRequest.env_for('/foo_bar/144', {
51
+ :method => 'DELETE'
52
+ })
53
+ output = ''
54
+ assert_nothing_raised do
55
+ output = @ws.call(env)
56
+ end
57
+ test_val = { :success => true }.to_json
58
+ assert_equal test_val, output[2]
59
+ end
60
+
61
+
62
+ def test_index
63
+ env = Rack::MockRequest.env_for('/foo_bar/', {
64
+ :method => 'GET'
65
+ })
66
+ output = ''
67
+ assert_nothing_raised do
68
+ output = @ws.call(env)
69
+ end
70
+ test_val = [1,2,3,4,5,6,7].to_json
71
+ assert_equal test_val, output[2]
72
+ end
73
+
74
+ def test_replace
75
+ env = Rack::MockRequest.env_for('/foo_bar', {
76
+ :method => 'PUT'
77
+ })
78
+ output = ''
79
+ assert_nothing_raised do
80
+ output = @ws.call(env)
81
+ end
82
+ test_val = { :success => true }.to_json
83
+ assert_equal test_val, output[2]
84
+ end
85
+
86
+ def test_create
87
+ env = Rack::MockRequest.env_for('/foo_bar/', {
88
+ :method => 'POST'
89
+ })
90
+ output = ''
91
+ assert_nothing_raised do
92
+ output = @ws.call(env)
93
+ end
94
+ test_val = { :success => true }.to_json
95
+ assert_equal test_val, output[2]
96
+ end
97
+
98
+ def test_drop
99
+ env = Rack::MockRequest.env_for('/foo_bar', {
100
+ :method => 'DELETE'
101
+ })
102
+ output = ''
103
+ assert_nothing_raised do
104
+ output = @ws.call(env)
105
+ end
106
+ test_val = { :success => true }.to_json
107
+ assert_equal test_val, output[2]
108
+ end
109
+
110
+
111
+ def test_missing
112
+ env = Rack::MockRequest.env_for('/foo_bar/144/missing', {
113
+ :method => 'GET'
114
+ })
115
+ output = ''
116
+ assert_nothing_raised do
117
+ output = @ws.call(env)
118
+ end
119
+ assert_equal 405, output[0]
120
+ end
121
+
122
+ end
@@ -0,0 +1,153 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'rack/test'
4
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','loader'))
5
+ require 'pp'
6
+
7
+ class SampleApp::TestControllerModifiers < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @ws = SampleApp::WebService.new
11
+ end
12
+
13
+ def test_has_relationship_to
14
+ env = Rack::MockRequest.env_for('/foo_bar/144/baz', {
15
+ :method => 'GET'
16
+ })
17
+ output = ''
18
+ assert_nothing_raised do
19
+ output = @ws.call(env)
20
+ end
21
+ test_val = { :BAZ => 'HOLA!' }.to_json
22
+ assert_equal test_val, output[2]
23
+
24
+ env = Rack::MockRequest.env_for('/foo_bar/133/baz', {
25
+ :method => 'GET'
26
+ })
27
+ output = ''
28
+ assert_nothing_raised do
29
+ output = @ws.call(env)
30
+ end
31
+ test_val = { :OTHER => 'YUP' }.to_json
32
+ assert_equal test_val, output[2]
33
+
34
+ env = Rack::MockRequest.env_for('/foo_bar/144/baz/', {
35
+ :method => 'GET'
36
+ })
37
+ output = ''
38
+ assert_nothing_raised do
39
+ output = @ws.call(env)
40
+ end
41
+ test_val = { :BAZ => 'HOLA!' }.to_json
42
+ assert_equal test_val, output[2]
43
+ end
44
+
45
+ def test_second_has_relationship_to
46
+ env = Rack::MockRequest.env_for('/foo_bar/144/slugger', {
47
+ :method => 'GET'
48
+ })
49
+ output = ''
50
+ assert_nothing_raised do
51
+ output = @ws.call(env)
52
+ end
53
+ test_val = { :WOM => 'BAT!' }.to_json
54
+ assert_equal test_val, output[2]
55
+
56
+ env = Rack::MockRequest.env_for('/foo_bar/133/slugger', {
57
+ :method => 'GET'
58
+ })
59
+ output = ''
60
+ assert_nothing_raised do
61
+ output = @ws.call(env)
62
+ end
63
+ test_val = { :SUHWING => 'BATTER' }.to_json
64
+ assert_equal test_val, output[2]
65
+
66
+ env = Rack::MockRequest.env_for('/foo_bar/144/slugger/', {
67
+ :method => 'GET'
68
+ })
69
+ output = ''
70
+ assert_nothing_raised do
71
+ output = @ws.call(env)
72
+ end
73
+ test_val = { :WOM => 'BAT!' }.to_json
74
+ assert_equal test_val, output[2]
75
+ end
76
+
77
+ def test_has_direct_relationships_to
78
+ env = Rack::MockRequest.env_for('/foo_bar/133/children/1', {
79
+ :method => 'GET'
80
+ })
81
+ output = ''
82
+ assert_nothing_raised do
83
+ output = @ws.call(env)
84
+ end
85
+ test_val = { :BAZA => 'YESSIR' }.to_json
86
+ assert_equal test_val, output[2]
87
+
88
+ env = Rack::MockRequest.env_for('/foo_bar/133/children/8', {
89
+ :method => 'GET'
90
+ })
91
+ output = ''
92
+ assert_nothing_raised do
93
+ output = @ws.call(env)
94
+ end
95
+ test_val = { :NOWAY => 'JOSE' }.to_json
96
+ assert_equal test_val, output[2]
97
+
98
+ env = Rack::MockRequest.env_for('/foo_bar/133/children/11', {
99
+ :method => 'GET'
100
+ })
101
+ output = ''
102
+ assert_nothing_raised do
103
+ output = @ws.call(env)
104
+ end
105
+ assert_equal 404, output[0]
106
+ end
107
+
108
+ def test_has_mapped_relationships_to
109
+ env = Rack::MockRequest.env_for('/foo_bar/133/maps/first', {
110
+ :method => 'GET'
111
+ })
112
+ output = ''
113
+ assert_nothing_raised do
114
+ output = @ws.call(env)
115
+ end
116
+ test_val = '1'
117
+ assert_equal test_val, output[2]
118
+
119
+ env = Rack::MockRequest.env_for('/foo_bar/133/maps/second', {
120
+ :method => 'GET'
121
+ })
122
+ output = ''
123
+ assert_nothing_raised do
124
+ output = @ws.call(env)
125
+ end
126
+ test_val = '0'
127
+ assert_equal test_val, output[2]
128
+
129
+ env = Rack::MockRequest.env_for('/foo_bar/133/maps/third', {
130
+ :method => 'GET'
131
+ })
132
+ output = ''
133
+ assert_nothing_raised do
134
+ output = @ws.call(env)
135
+ end
136
+ test_val = '0'
137
+ assert_equal test_val, output[2]
138
+ end
139
+
140
+ def test_keyed_with_type
141
+ # baza controller exercises this option
142
+ env = Rack::MockRequest.env_for('/foo_bar/133/children/1', {
143
+ :method => 'GET'
144
+ })
145
+ output = ''
146
+ assert_nothing_raised do
147
+ output = @ws.call(env)
148
+ end
149
+ test_val = { :BAZA => 'YESSIR' }.to_json
150
+ assert_equal test_val, output[2]
151
+ end
152
+
153
+ end