restfulie 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. data/Gemfile +28 -0
  2. data/Gemfile.lock +128 -0
  3. data/LICENSE +17 -0
  4. data/README.textile +138 -0
  5. data/Rakefile +146 -0
  6. data/lib/restfulie/client/base.rb +36 -0
  7. data/lib/restfulie/client/cache/basic.rb +76 -0
  8. data/lib/restfulie/client/cache/fake.rb +15 -0
  9. data/lib/restfulie/client/cache/http_ext.rb +123 -0
  10. data/lib/restfulie/client/cache/restrictions.rb +13 -0
  11. data/lib/restfulie/client/cache.rb +11 -0
  12. data/lib/restfulie/client/configuration.rb +67 -0
  13. data/lib/restfulie/client/dsl.rb +66 -0
  14. data/lib/restfulie/client/entry_point.rb +61 -0
  15. data/lib/restfulie/client/ext/atom_ext.rb +14 -0
  16. data/lib/restfulie/client/ext/http_ext.rb +22 -0
  17. data/lib/restfulie/client/ext/json_ext.rb +16 -0
  18. data/lib/restfulie/client/feature/base.rb +75 -0
  19. data/lib/restfulie/client/feature/base_request.rb +35 -0
  20. data/lib/restfulie/client/feature/cache.rb +16 -0
  21. data/lib/restfulie/client/feature/enhance_response.rb +12 -0
  22. data/lib/restfulie/client/feature/follow_request.rb +41 -0
  23. data/lib/restfulie/client/feature/history.rb +26 -0
  24. data/lib/restfulie/client/feature/history_request.rb +19 -0
  25. data/lib/restfulie/client/feature/open_search/pattern_matcher.rb +25 -0
  26. data/lib/restfulie/client/feature/open_search.rb +21 -0
  27. data/lib/restfulie/client/feature/serialize_body.rb +32 -0
  28. data/lib/restfulie/client/feature/setup_header.rb +22 -0
  29. data/lib/restfulie/client/feature/throw_error.rb +41 -0
  30. data/lib/restfulie/client/feature/verb.rb +119 -0
  31. data/lib/restfulie/client/feature.rb +5 -0
  32. data/lib/restfulie/client/http/cache.rb +28 -0
  33. data/lib/restfulie/client/http/error.rb +77 -0
  34. data/lib/restfulie/client/http/response_holder.rb +29 -0
  35. data/lib/restfulie/client/http.rb +7 -0
  36. data/lib/restfulie/client/master_delegator.rb +31 -0
  37. data/lib/restfulie/client/mikyung/concatenator.rb +18 -0
  38. data/lib/restfulie/client/mikyung/core.rb +70 -0
  39. data/lib/restfulie/client/mikyung/languages/german.rb +24 -0
  40. data/lib/restfulie/client/mikyung/languages/portuguese.rb +23 -0
  41. data/lib/restfulie/client/mikyung/languages.rb +11 -0
  42. data/lib/restfulie/client/mikyung/rest_process_model.rb +191 -0
  43. data/lib/restfulie/client/mikyung/steady_state_walker.rb +38 -0
  44. data/lib/restfulie/client/mikyung/then_condition.rb +39 -0
  45. data/lib/restfulie/client/mikyung/when_condition.rb +57 -0
  46. data/lib/restfulie/client/mikyung.rb +15 -0
  47. data/lib/restfulie/client.rb +26 -0
  48. data/lib/restfulie/common/converter/atom/base.rb +91 -0
  49. data/lib/restfulie/common/converter/atom/builder.rb +111 -0
  50. data/lib/restfulie/common/converter/atom/helpers.rb +17 -0
  51. data/lib/restfulie/common/converter/atom.rb +12 -0
  52. data/lib/restfulie/common/converter/json/base.rb +87 -0
  53. data/lib/restfulie/common/converter/json/builder.rb +102 -0
  54. data/lib/restfulie/common/converter/json/helpers.rb +17 -0
  55. data/lib/restfulie/common/converter/json.rb +12 -0
  56. data/lib/restfulie/common/converter/open_search/descriptor.rb +32 -0
  57. data/lib/restfulie/common/converter/open_search.rb +16 -0
  58. data/lib/restfulie/common/converter/values.rb +33 -0
  59. data/lib/restfulie/common/converter/xml/base.rb +63 -0
  60. data/lib/restfulie/common/converter/xml/builder.rb +113 -0
  61. data/lib/restfulie/common/converter/xml/helpers.rb +17 -0
  62. data/lib/restfulie/common/converter/xml/link.rb +30 -0
  63. data/lib/restfulie/common/converter/xml/links.rb +21 -0
  64. data/lib/restfulie/common/converter/xml.rb +14 -0
  65. data/lib/restfulie/common/converter.rb +43 -0
  66. data/lib/restfulie/common/core_ext/hash.rb +18 -0
  67. data/lib/restfulie/common/core_ext.rb +1 -0
  68. data/lib/restfulie/common/error.rb +19 -0
  69. data/lib/restfulie/common/links.rb +9 -0
  70. data/lib/restfulie/common/logger.rb +19 -0
  71. data/lib/restfulie/common/representation/atom/atom.rng +597 -0
  72. data/lib/restfulie/common/representation/atom/base.rb +142 -0
  73. data/lib/restfulie/common/representation/atom/category.rb +41 -0
  74. data/lib/restfulie/common/representation/atom/entry.rb +59 -0
  75. data/lib/restfulie/common/representation/atom/factory.rb +43 -0
  76. data/lib/restfulie/common/representation/atom/feed.rb +110 -0
  77. data/lib/restfulie/common/representation/atom/link.rb +68 -0
  78. data/lib/restfulie/common/representation/atom/person.rb +48 -0
  79. data/lib/restfulie/common/representation/atom/source.rb +59 -0
  80. data/lib/restfulie/common/representation/atom/tag_collection.rb +38 -0
  81. data/lib/restfulie/common/representation/atom/xml.rb +90 -0
  82. data/lib/restfulie/common/representation/atom.rb +20 -0
  83. data/lib/restfulie/common/representation/generic.rb +22 -0
  84. data/lib/restfulie/common/representation/json/base.rb +27 -0
  85. data/lib/restfulie/common/representation/json/keys_as_methods.rb +74 -0
  86. data/lib/restfulie/common/representation/json/link.rb +29 -0
  87. data/lib/restfulie/common/representation/json/link_collection.rb +23 -0
  88. data/lib/restfulie/common/representation/json.rb +13 -0
  89. data/lib/restfulie/common/representation/links.rb +11 -0
  90. data/lib/restfulie/common/representation.rb +3 -0
  91. data/lib/restfulie/common.rb +18 -0
  92. data/lib/restfulie/server/action_controller/base.rb +48 -0
  93. data/lib/restfulie/server/action_controller/params_parser.rb +100 -0
  94. data/lib/restfulie/server/action_controller/patch.rb +6 -0
  95. data/lib/restfulie/server/action_controller/restful_responder.rb +12 -0
  96. data/lib/restfulie/server/action_controller/trait/cacheable.rb +81 -0
  97. data/lib/restfulie/server/action_controller/trait/created.rb +17 -0
  98. data/lib/restfulie/server/action_controller/trait.rb +9 -0
  99. data/lib/restfulie/server/action_controller.rb +11 -0
  100. data/lib/restfulie/server/action_view/helpers.rb +50 -0
  101. data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +21 -0
  102. data/lib/restfulie/server/action_view/template_handlers.rb +30 -0
  103. data/lib/restfulie/server/action_view.rb +10 -0
  104. data/lib/restfulie/server/configuration.rb +24 -0
  105. data/lib/restfulie/server/controller.rb +74 -0
  106. data/lib/restfulie/server/core_ext/array.rb +61 -0
  107. data/lib/restfulie/server/core_ext.rb +1 -0
  108. data/lib/restfulie/server.rb +25 -0
  109. data/lib/restfulie/version.rb +14 -0
  110. data/lib/restfulie.rb +34 -0
  111. metadata +242 -0
@@ -0,0 +1,20 @@
1
+ require 'nokogiri'
2
+
3
+ module Restfulie
4
+ module Common
5
+ module Representation
6
+ module Atom
7
+ autoload :Factory, 'restfulie/common/representation/atom/factory'
8
+ autoload :XML, 'restfulie/common/representation/atom/xml'
9
+ autoload :Base, 'restfulie/common/representation/atom/base'
10
+ autoload :TagCollection, 'restfulie/common/representation/atom/tag_collection'
11
+ autoload :Link, 'restfulie/common/representation/atom/link'
12
+ autoload :Person, 'restfulie/common/representation/atom/person'
13
+ autoload :Category, 'restfulie/common/representation/atom/category'
14
+ autoload :Feed, 'restfulie/common/representation/atom/feed'
15
+ autoload :Entry, 'restfulie/common/representation/atom/entry'
16
+ autoload :Source, 'restfulie/common/representation/atom/source'
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ # Unknown representation's unmarshalling on the client side
5
+ class Generic
6
+
7
+ # Because there is no media type registered, return the content itself
8
+ def unmarshal(content)
9
+ def content.links
10
+ []
11
+ end
12
+ content
13
+ end
14
+
15
+ def marshal(string, rel)
16
+ string
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ class Json
5
+ module Base
6
+ module ClassMethods
7
+
8
+ # creates a json unmarshalled version of this object
9
+ def create(obj = nil)
10
+ @json = {}
11
+ return @json.extend(KeysAsMethods) unless obj
12
+
13
+ if obj.kind_of?(Hash) || obj.kind_of?(Array)
14
+ @json = obj
15
+ else
16
+ @json = ::JSON.parse(obj)
17
+ end
18
+
19
+ @json.extend(KeysAsMethods)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,74 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ class Json
5
+ module KeysAsMethods
6
+ def self.extended(base)
7
+ [:type, :id].each { |m| base.__free_method__(m) }
8
+ end
9
+
10
+ def [](key)
11
+ __normalize__(super(key))
12
+ end
13
+
14
+ def []=(key, value)
15
+ super(key,value)
16
+ end
17
+
18
+ def to_s
19
+ super.to_json
20
+ end
21
+
22
+ def method_missing(name, *args)
23
+ method_name = name.to_s
24
+ if method_name.last == '='
25
+ self[method_name.chop] = args[0]
26
+ else
27
+ self[method_name]
28
+ end
29
+ end
30
+
31
+ # if you have a key that is also a method (such as Array#size)
32
+ # you can use this to free the method and use the method obj.size
33
+ # to access the value of key "size".
34
+ # you still can access the old method with __[method_name]__
35
+ def __free_method__(sym)
36
+ if self.__metaclass__.method_defined?(sym) && !respond_to?("__#{sym}__")
37
+ self.__metaclass__.send(:alias_method, "__#{sym}__", sym)
38
+ end
39
+ self.__metaclass__.send(:define_method, sym) { method_missing(sym.to_s) }
40
+ self
41
+ end
42
+
43
+ def __metaclass__
44
+ class << self; self; end
45
+ end
46
+
47
+ include Restfulie::Common::Links
48
+
49
+ # easy accessors to links
50
+ def links
51
+ some_links = self["link"]
52
+ return nil unless some_links
53
+ some_links = [some_links] unless some_links.kind_of? Array
54
+ LinkCollection.new(some_links)
55
+ end
56
+
57
+ private
58
+
59
+ def __normalize__(value)
60
+ case value
61
+ when Hash
62
+ value.extend(KeysAsMethods)
63
+ when Array
64
+ value.map { |v| __normalize__(v) }
65
+ else
66
+ value
67
+ end
68
+ value
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,29 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ class Json
5
+ class Link
6
+ def initialize(obj)
7
+ @obj = obj
8
+ end
9
+
10
+ def type
11
+ @obj.type
12
+ end
13
+
14
+ def href
15
+ @obj.href
16
+ end
17
+
18
+ def rel
19
+ @obj.rel
20
+ end
21
+
22
+ def method_missing(symbol, *args, &block)
23
+ @obj.send(symbol, *args, &block)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ class Json
5
+ class LinkCollection
6
+ def initialize(parent_node)
7
+ @node = parent_node
8
+ end
9
+
10
+ def method_missing(symbol, *args, &block)
11
+ linkset = @node.select {|link| link.rel == symbol.to_s }
12
+ linkset.map! { |link| Link.new(link) }
13
+ unless linkset.empty?
14
+ linkset.size == 1 ? linkset.first : linkset
15
+ else
16
+ nil
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ class Json
5
+ autoload :Base, 'restfulie/common/representation/json/base'
6
+ autoload :KeysAsMethods, 'restfulie/common/representation/json/keys_as_methods'
7
+ autoload :Link, 'restfulie/common/representation/json/link'
8
+ autoload :LinkCollection, 'restfulie/common/representation/json/link_collection'
9
+ extend Base::ClassMethods
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ module Links
5
+ def self.extract_link_header(links)
6
+ links.collect {|link| "<#{link.href}>; rel=#{link.rel}"}.join(', ')
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Restfulie::Common::Representation
2
+ Dir["#{File.dirname(__FILE__)}/representation/*.rb"].each {|f| autoload File.basename(f)[0..-4].camelize.to_sym, f }
3
+ end
@@ -0,0 +1,18 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+
4
+ require 'rubygems'
5
+ require 'active_support'
6
+ require 'action_controller'
7
+
8
+ module Restfulie
9
+ module Common
10
+ autoload :Error, 'restfulie/common/error'
11
+ autoload :Links, 'restfulie/common/links'
12
+ autoload :Logger, 'restfulie/common/logger'
13
+ autoload :Representation, 'restfulie/common/representation'
14
+ autoload :Converter, 'restfulie/common/converter'
15
+ end
16
+ end
17
+
18
+ require 'restfulie/common/core_ext'
@@ -0,0 +1,48 @@
1
+ module Restfulie
2
+ module Server
3
+ module ActionController
4
+ module Base
5
+ def self.included(base)
6
+ # Sets a default responder for this controller.
7
+ # Needs to require responder_legacy.rb
8
+ base.responder = Restfulie::Server::ActionController::RestfulResponder
9
+ base.extend(Restfulie::Server::ActionController::Base::ClassMethods)
10
+ # Atom representation is added by default
11
+ Restfulie::Server::ActionController::ParamsParser.register('application/atom+xml', Restfulie::Common::Converter::Atom)
12
+ end
13
+
14
+ module ClassMethods
15
+ def call(env)
16
+ if include_restfulie? && env.has_key?("action_controller.restfulie.response")
17
+ if logger && logger.info?
18
+ information = "Status: #{env["action_controller.restfulie.response"][0]} "
19
+ information << ::ActionController::StatusCodes::STATUS_CODES[env["action_controller.restfulie.response"][0]]
20
+ logger.info(information)
21
+ end
22
+ return env["action_controller.restfulie.response"]
23
+ end
24
+ super
25
+ end
26
+
27
+ def include_restfulie?
28
+ defined?(Restfulie::Server::ActionController::Base) && self.include?(Restfulie::Server::ActionController::Base)
29
+ end
30
+ end
31
+
32
+ # If your controller inherits from Restfulie::Server::Controller::Base,
33
+ # it will have an :atom option, very similar to render :xml
34
+ def render(options = nil, extra_options = {}, &block)
35
+ if options && atom = options[:atom]
36
+ response.content_type ||= Mime::ATOM
37
+ representation = atom.respond_to?(:to_atom) ? atom.to_atom.to_xml : atom.to_xml
38
+ options[:text] = representation
39
+ options[:atom] = nil
40
+ super options
41
+ else
42
+ super
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,100 @@
1
+ module Restfulie
2
+ module Server
3
+ module ActionController
4
+
5
+ # This class is just a proxy for the extension point offered by ActionDispatch::ParamsParser
6
+ class ParamsParser3
7
+
8
+ def register(content_type, representation)
9
+ ActionDispatch::ParamsParser::DEFAULT_PARSERS[Mime::Type.lookup(content_type)] = representation.method(:to_hash).to_proc
10
+ end
11
+
12
+ def unregister(content_type)
13
+ ActionDispatch::ParamsParser::DEFAULT_PARSERS.delete(Mime::Type.lookup(content_type))
14
+ end
15
+ end
16
+
17
+ # This class is just a proxy for the extension point offered by ActionController::Base
18
+ class ParamsParser2
19
+
20
+ def param_parsers
21
+ ::ActionController::Base.param_parsers
22
+ end
23
+
24
+ def register(content_type, representation)
25
+ param_parsers[Mime::Type.lookup(content_type)] = representation.method(:to_hash).to_proc
26
+ end
27
+
28
+ def unregister(content_type)
29
+ param_parsers.delete(Mime::Type.lookup(content_type))
30
+ end
31
+ end
32
+
33
+
34
+ class ParamsParser
35
+
36
+ def self.rails3?
37
+ defined?(::ActionDispatch) && defined?(::ActionDispatch::ParamsParser)
38
+ end
39
+
40
+ if rails3?
41
+ @parser = ParamsParser3.new
42
+ else
43
+ @parser = ParamsParser2.new
44
+ # This monkey patch is needed because Rails 2.3.5 doesn't support
45
+ # a way of use rescue_from ActionController handling to return
46
+ # bad request status when trying to parse an invalid body request
47
+ #
48
+ # In Rails 3 this won't be necessary, because all exception handling
49
+ # extensions are handled by the Rack stack
50
+ #
51
+ # TODO Change this when porting this code to Rails 3
52
+ ::ActionController::ParamsParser.class_eval do
53
+ def call(env)
54
+ begin
55
+ if params = parse_formatted_parameters(env)
56
+ env["action_controller.request.request_parameters"] = params
57
+ elsif !(env["CONTENT_TYPE"] == "application/x-www-form-urlencoded") #do not override rails default behaviour for this media type, it's dangerous... (o.O)
58
+ if env["CONTENT_LENGTH"] && (env["CONTENT_LENGTH"] != "0")
59
+ env["action_controller.restfulie.response"] = [415, {'Content-Type' => 'text/html'}, ["<html><body><h1>415 Unsupported Media Type</h1></body></html>"]]
60
+ end
61
+ end
62
+ rescue
63
+ env["action_controller.restfulie.response"] = [400, {'Content-Type' => 'text/html'}, ["<html><body><h1>400 Bad Request</h1></body></html>"]]
64
+ end
65
+
66
+ @app.call(env)
67
+ end
68
+ end
69
+ end
70
+
71
+ ##
72
+ # :singleton-method:
73
+ # Use it to register param parsers on the server side.
74
+ #
75
+ # * <tt>media type</tt>
76
+ # * <tt>a restfulie representation with to_hash method</tt>
77
+ #
78
+ # Restfulie::Server::ActionController::ParamsParser.register('application/atom+xml', Atom)
79
+ #
80
+ def self.register(content_type, representation)
81
+ @parser.register(content_type, representation)
82
+ end
83
+
84
+ ##
85
+ # :singleton-method:
86
+ # Use it to unregister param parsers on the server side.
87
+ #
88
+ # * <tt>media type</tt>
89
+ #
90
+ # Restfulie::Server::ActionController::ParamsParser.unregister('application/atom+xml')
91
+ #
92
+ def self.unregister(content_type)
93
+ @parser.unregister(content_type)
94
+ end
95
+ end
96
+
97
+ end
98
+ end
99
+ end
100
+
@@ -0,0 +1,6 @@
1
+ module ActionController::Routing
2
+ HTTP_METHODS = [:get, :head, :post, :put, :delete, :options, :patch]
3
+ end
4
+
5
+ ActionController::Request::HTTP_METHODS << "patch"
6
+ ActionController::Request::HTTP_METHOD_LOOKUP["PATCH"] = :patch
@@ -0,0 +1,12 @@
1
+ module Restfulie
2
+ module Server
3
+ module ActionController
4
+ class RestfulResponder < ::ActionController::Responder
5
+
6
+ include CacheableResponder
7
+ include CreatedResponder
8
+
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,81 @@
1
+ class Expires
2
+ def do_http_cache(responder, headers)
3
+ if responder.options[:expires_in]
4
+ headers << "max-age=#{responder.options[:expires_in]}"
5
+ true
6
+ else
7
+ false
8
+ end
9
+ end
10
+ end
11
+
12
+ class LastModifieds
13
+ # default implementation that will check whether caching can be applied
14
+ def accepts?(responder)
15
+ responder.resources.flatten.select do |resource|
16
+ resource.respond_to?(:updated_at)
17
+ end &&
18
+ responder.controller.response.last_modified.nil? &&
19
+ !new_record?(responder)
20
+ end
21
+
22
+ def do_http_cache(responder, headers)
23
+ return false unless accepts?(responder)
24
+
25
+ timestamps = responder.resources.flatten.select do |resource|
26
+ resource.respond_to?(:updated_at)
27
+ end.map do |resource|
28
+ (resource.updated_at || Time.now).utc
29
+ end
30
+
31
+ timestamp = timestamps.max
32
+
33
+ responder.controller.response.last_modified = timestamp if timestamp
34
+ end
35
+
36
+ def new_record?(responder)
37
+ responder.resource.respond_to?(:new_record?) && responder.resource.new_record?
38
+ end
39
+
40
+ end
41
+
42
+ module Restfulie::Server::ActionController
43
+ module Trait
44
+ module Cacheable
45
+
46
+ CACHES = [::Expires.new, ::LastModifieds.new]
47
+
48
+ def to_format
49
+ headers = cache_control_headers
50
+ cached = CACHES.inject(false) do |cached, cache|
51
+ cached || cache.do_http_cache(self, headers)
52
+ end
53
+ if ::ActionController::Base.perform_caching && cached
54
+ set_public_cache_control(headers)
55
+ controller.response.headers["Cache-Control"] = headers.join(', ')
56
+ fresh = request.fresh?(controller.response)
57
+ if fresh
58
+ head :not_modified
59
+ else
60
+ super
61
+ end
62
+ else
63
+ super
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def set_public_cache_control(headers)
70
+ headers.delete("private")
71
+ headers.delete("no-cache")
72
+ headers << "public"
73
+ end
74
+
75
+ def cache_control_headers
76
+ (controller.response.headers["Cache-Control"] || "").split(",").map {|k| k.strip }
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,17 @@
1
+ module Restfulie::Server::ActionController
2
+ module Trait
3
+
4
+ # Adds support to answering as a 201 when the resource has been just created
5
+ module Created
6
+
7
+ def to_format
8
+ if (options[:status] == 201) || (options[:status] == :created)
9
+ render :status => 201, :location => controller.url_for(resource), :text => ""
10
+ else
11
+ super
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ module Restfulie
2
+ module Server
3
+ module ActionController #:nodoc:
4
+ module Trait #:nodoc:
5
+ Dir["#{File.dirname(__FILE__)}/trait/*.rb"].each {|f| autoload File.basename(f)[0..-4].camelize.to_sym, f }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Restfulie
2
+ module Server
3
+ module ActionController #:nodoc:
4
+ if defined?(::ActionController) || defined?(::ApplicationController)
5
+ Dir["#{File.dirname(__FILE__)}/action_controller/*.rb"].each {|f| autoload File.basename(f)[0..-4].camelize.to_sym, f }
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ require 'restfulie/server/action_controller/patch'
@@ -0,0 +1,50 @@
1
+ module Restfulie
2
+ module Server
3
+ module ActionView
4
+ module Helpers
5
+ # Load a partial template to execute in describe
6
+ #
7
+ # For example:
8
+ #
9
+ # Passing the current context to partial in template:
10
+ #
11
+ # member(@album) do |member, album|
12
+ # partial('member', binding)
13
+ # end
14
+ #
15
+ # in partial:
16
+ #
17
+ # member.links << link(:rel => :artists, :href => album_artists_url(album))
18
+ #
19
+ # Or passing local variables assing
20
+ #
21
+ # collection(@albums) do |collection|
22
+ # collection.members do |member, album|
23
+ # partial("member", :locals => {:member => member, :album => album})
24
+ # end
25
+ # end
26
+ #
27
+ def partial(partial_path, caller_binding = nil)
28
+ # Create a context to assing variables
29
+ if caller_binding.kind_of?(Hash)
30
+ Proc.new do
31
+ extend @restfulie_type_helpers
32
+ context = eval("(class << self; self; end)", binding)
33
+
34
+ unless caller_binding[:locals].nil?
35
+ caller_binding[:locals].each do |k, v|
36
+ context.send(:define_method, k.to_sym) { v }
37
+ end
38
+ end
39
+
40
+ partial(partial_path, binding)
41
+ end.call
42
+ else
43
+ template = _pick_partial_template(partial_path)
44
+ eval(template.source, caller_binding, template.path)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,21 @@
1
+ module Restfulie
2
+ module Server
3
+ module ActionView
4
+ module TemplateHandlers
5
+ class Tokamak < ::ActionView::TemplateHandler
6
+ include ::ActionView::TemplateHandlers::Compilable
7
+
8
+ def compile(template)
9
+ "@restfulie_type_helpers = Restfulie::Common::Converter.content_type_for(self.response.content_type).helper; " +
10
+ "extend @restfulie_type_helpers; " +
11
+ "extend Restfulie::Server::ActionView::Helpers; " +
12
+ "code_block = lambda { #{template.source} };" +
13
+ "builder = code_block.call; " +
14
+ "self.response.headers['Link'] = Restfulie::Common::Representation::Links.extract_link_header(builder.links) if builder.respond_to?(:links); " +
15
+ "builder.to_s"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ module Restfulie
2
+ module Server
3
+ module ActionView
4
+ module TemplateHandlers #:nodoc:
5
+ autoload :Tokamak, 'restfulie/server/action_view/template_handlers/tokamak'
6
+
7
+ def self.template_registry
8
+ if defined? ::ActionView::Template and
9
+ ::ActionView::Template.respond_to?(:register_template_handler)
10
+ ::ActionView::Template
11
+ else
12
+ ::ActionView::Base
13
+ end
14
+ end
15
+
16
+ # It is needed to explicitly call 'activate!' to install the Tokamak
17
+ # template handler
18
+ def self.activate!
19
+ template_registry.register_template_handler(:tokamak,
20
+ Restfulie::Server::ActionView::TemplateHandlers::Tokamak)
21
+
22
+ # TODO unsure if it can be removed. check feedback prior to 1.0.0
23
+ # if defined?(::ActionController::Base) && ::ActionController::Base.respond_to?(:exempt_from_layout)
24
+ # ::ActionController::Base.exempt_from_layout :tokamak
25
+ # end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ if defined? ::ActionView and ::ActionController
2
+ module Restfulie #:nodoc:
3
+ module Server #:nodoc:
4
+ module ActionView #:nodoc:
5
+ autoload :TemplateHandlers, 'restfulie/server/action_view/template_handlers'
6
+ autoload :Helpers, 'restfulie/server/action_view/helpers'
7
+ end
8
+ end
9
+ end
10
+ end