restfulie 0.6.0 → 0.7.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/README.textile +83 -7
- data/Rakefile +98 -13
- data/lib/restfulie/client/base.rb +48 -53
- data/lib/restfulie/client/configuration.rb +69 -0
- data/lib/restfulie/client/http/adapter.rb +487 -0
- data/lib/restfulie/client/http/atom_ext.rb +87 -0
- data/lib/restfulie/client/http/cache.rb +28 -0
- data/lib/restfulie/client/http/error.rb +80 -0
- data/lib/restfulie/client/http/marshal.rb +147 -0
- data/lib/restfulie/client/http.rb +13 -0
- data/lib/restfulie/client.rb +8 -56
- data/lib/restfulie/common/builder/builder_base.rb +58 -0
- data/lib/restfulie/common/builder/helpers.rb +22 -0
- data/lib/restfulie/common/builder/marshalling/atom.rb +197 -0
- data/lib/restfulie/common/builder/marshalling/base.rb +12 -0
- data/lib/restfulie/common/builder/marshalling/json.rb +2 -0
- data/lib/restfulie/common/builder/marshalling.rb +16 -0
- data/lib/restfulie/common/builder/rules/collection_rule.rb +10 -0
- data/lib/restfulie/common/builder/rules/link.rb +20 -0
- data/lib/restfulie/common/builder/rules/links.rb +9 -0
- data/lib/restfulie/common/builder/rules/member_rule.rb +8 -0
- data/lib/restfulie/common/builder/rules/namespace.rb +25 -0
- data/lib/restfulie/common/builder/rules/rules_base.rb +76 -0
- data/lib/restfulie/common/builder.rb +16 -0
- data/lib/restfulie/common/errors.rb +9 -0
- data/lib/restfulie/{logger.rb → common/logger.rb} +3 -5
- data/lib/restfulie/common/representation/atom.rb +48 -0
- data/lib/restfulie/common/representation/generic.rb +33 -0
- data/lib/restfulie/common/representation/xml.rb +24 -0
- data/lib/restfulie/common/representation.rb +10 -0
- data/lib/restfulie/common.rb +23 -0
- data/lib/restfulie/server/action_controller/base.rb +31 -0
- data/lib/restfulie/server/action_controller/params_parser.rb +62 -0
- data/lib/restfulie/server/action_controller/restful_responder.rb +39 -0
- data/lib/restfulie/server/action_controller/routing/restful_route.rb +14 -0
- data/lib/restfulie/server/action_controller/routing.rb +12 -0
- data/lib/restfulie/server/action_controller.rb +15 -0
- data/lib/restfulie/server/action_view/helpers.rb +45 -0
- data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +15 -0
- data/lib/restfulie/server/action_view/template_handlers.rb +13 -0
- data/lib/restfulie/server/action_view.rb +8 -0
- data/lib/restfulie/server/configuration.rb +21 -0
- data/lib/restfulie/server/core_ext/array.rb +45 -0
- data/lib/restfulie/server/core_ext.rb +1 -0
- data/lib/restfulie/server/restfulie_controller.rb +1 -17
- data/lib/restfulie/server.rb +15 -0
- data/lib/restfulie.rb +4 -72
- data/lib/vendor/atom/configuration.rb +24 -0
- data/lib/vendor/atom/pub.rb +250 -0
- data/lib/vendor/atom/xml/parser.rb +373 -0
- data/lib/vendor/atom.rb +771 -0
- metadata +94 -33
- data/lib/restfulie/client/atom_media_type.rb +0 -75
- data/lib/restfulie/client/cache.rb +0 -103
- data/lib/restfulie/client/entry_point.rb +0 -94
- data/lib/restfulie/client/extensions/http.rb +0 -116
- data/lib/restfulie/client/helper.rb +0 -28
- data/lib/restfulie/client/instance.rb +0 -158
- data/lib/restfulie/client/request_execution.rb +0 -321
- data/lib/restfulie/client/state.rb +0 -36
- data/lib/restfulie/media_type.rb +0 -143
- data/lib/restfulie/media_type_control.rb +0 -115
- data/lib/restfulie/media_type_defaults.rb +0 -51
- data/lib/restfulie/server/atom_media_type.rb +0 -115
- data/lib/restfulie/server/base.rb +0 -91
- data/lib/restfulie/server/controller.rb +0 -122
- data/lib/restfulie/server/instance.rb +0 -102
- data/lib/restfulie/server/marshalling.rb +0 -47
- data/lib/restfulie/server/opensearch/description.rb +0 -54
- data/lib/restfulie/server/opensearch.rb +0 -18
- data/lib/restfulie/server/transition.rb +0 -93
- data/lib/restfulie/unmarshalling.rb +0 -131
- data/lib/vendor/jeokkarak/hashi.rb +0 -65
- data/lib/vendor/jeokkarak/jeokkarak.rb +0 -81
@@ -0,0 +1,76 @@
|
|
1
|
+
module Restfulie::Common::Builder::Rules; end
|
2
|
+
|
3
|
+
class Restfulie::Common::Builder::Rules::Base
|
4
|
+
attr_accessor :blocks
|
5
|
+
attr_accessor :links
|
6
|
+
attr_reader :namespaces
|
7
|
+
|
8
|
+
def initialize(blocks = [], &block)
|
9
|
+
@links = Restfulie::Common::Builder::Rules::Links.new
|
10
|
+
@blocks = (block_given? ? [block] : []) + blocks
|
11
|
+
@namespaces = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(*args)
|
15
|
+
@blocks.each do |block|
|
16
|
+
params = ([self] + args)[0..block.arity-1]
|
17
|
+
block.call(*params)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Use to register namespace
|
22
|
+
#
|
23
|
+
#==Example:
|
24
|
+
#
|
25
|
+
# namespace(@album , "http://example.com")
|
26
|
+
# namespace(:albums, "http://example.com")
|
27
|
+
# namespace(:albums, "http://example.com", :eager_load => false)
|
28
|
+
# namespace(:albums, "http://example.com", :eager_load => { :title => 'A title' })
|
29
|
+
#
|
30
|
+
def namespace(ns, uri = nil, options = {}, &block)
|
31
|
+
object = nil
|
32
|
+
|
33
|
+
if !ns.kind_of?(String) && !ns.kind_of?(Symbol)
|
34
|
+
object = ns
|
35
|
+
ns = object.class.to_s.demodulize.downcase.pluralize.to_sym
|
36
|
+
options[:eager_load] = true unless options.key?(:eager_load)
|
37
|
+
end
|
38
|
+
|
39
|
+
unless [true, false, nil].include?(options[:eager_load])
|
40
|
+
object = options[:eager_load]
|
41
|
+
options[:eager_load] = true
|
42
|
+
end
|
43
|
+
|
44
|
+
namespace = find_or_new_namespace(ns, uri)
|
45
|
+
eager_load(object, namespace) if options[:eager_load]
|
46
|
+
|
47
|
+
yield(namespace) if block_given?
|
48
|
+
namespace
|
49
|
+
end
|
50
|
+
|
51
|
+
def metaclass
|
52
|
+
(class << self; self; end)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
# Load attributes of the object to passed hash.
|
57
|
+
# If object respond to attributes, attributes is merge, unless merge instance variables
|
58
|
+
def eager_load(object, ns)
|
59
|
+
if object.kind_of?(Hash)
|
60
|
+
ns.merge!(object.symbolize_keys)
|
61
|
+
elsif object.respond_to?(:attributes)
|
62
|
+
ns.merge!(object.attributes.symbolize_keys)
|
63
|
+
else
|
64
|
+
object.instance_variables.each do |var|
|
65
|
+
ns[var.gsub(/^@/, '').to_sym] = object.instance_variable_get(var)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Search a namespace or create a new
|
71
|
+
def find_or_new_namespace(name, uri)
|
72
|
+
namespace = @namespaces.find { |n| n.namespace == name } || (@namespaces << Restfulie::Common::Builder::Rules::Namespace.new(name, uri)).last
|
73
|
+
namespace.uri = uri unless uri.nil?
|
74
|
+
namespace
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#initialize namespace
|
2
|
+
module Restfulie::Common::Builder; end
|
3
|
+
|
4
|
+
%w(
|
5
|
+
helpers
|
6
|
+
builder_base
|
7
|
+
marshalling
|
8
|
+
rules/rules_base
|
9
|
+
rules/link
|
10
|
+
rules/links
|
11
|
+
rules/namespace
|
12
|
+
rules/member_rule
|
13
|
+
rules/collection_rule
|
14
|
+
).each do |file|
|
15
|
+
require File.join(File.dirname(__FILE__), 'builder', file)
|
16
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Restfulie::Common::Error
|
2
|
+
class RestfulieError < StandardError; end
|
3
|
+
class MarshallingError < RestfulieError; end
|
4
|
+
class UndefinedMarshallingError < MarshallingError; end
|
5
|
+
|
6
|
+
# Atom marshallinh error
|
7
|
+
class AtomMarshallingError < MarshallingError; end
|
8
|
+
class NameSpaceError < AtomMarshallingError; end
|
9
|
+
end
|
@@ -1,13 +1,11 @@
|
|
1
|
-
module Restfulie
|
2
|
-
|
1
|
+
module Restfulie::Common::Logger
|
3
2
|
# Configure the logger used by Restfulie
|
4
3
|
#
|
5
4
|
# The logger defaults to ActiveSupport::BufferedLogger.new(STDOUT)
|
6
5
|
class << self
|
7
6
|
attr_accessor :logger
|
8
7
|
end
|
9
|
-
|
10
8
|
end
|
11
9
|
|
12
|
-
Restfulie.logger = ActiveSupport::BufferedLogger.new(STDOUT)
|
13
|
-
Restfulie.logger.level = Logger::DEBUG
|
10
|
+
Restfulie::Common::Logger.logger = ActiveSupport::BufferedLogger.new(STDOUT)
|
11
|
+
Restfulie::Common::Logger.logger.level = Logger::DEBUG
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Restfulie::Common::Representation
|
2
|
+
# Implements the interface for unmarshal Atom media type responses (application/atom+xml) to ruby objects instantiated by rAtom library.
|
3
|
+
#
|
4
|
+
# Furthermore, this class extends rAtom behavior to enable client users to easily access link relationships.
|
5
|
+
class Atom
|
6
|
+
|
7
|
+
cattr_reader :media_type_name
|
8
|
+
@@media_type_name = 'application/atom+xml'
|
9
|
+
|
10
|
+
cattr_reader :headers
|
11
|
+
@@headers = {
|
12
|
+
:get => { 'Accept' => media_type_name },
|
13
|
+
:post => { 'Content-Type' => media_type_name }
|
14
|
+
}
|
15
|
+
|
16
|
+
#Convert raw string to rAtom instances (client side)
|
17
|
+
def unmarshal(content)
|
18
|
+
begin
|
19
|
+
::Atom::Feed.load_feed(content)
|
20
|
+
rescue ::ArgumentError
|
21
|
+
::Atom::Entry.load_entry(content)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def marshal(string, rel)
|
26
|
+
string
|
27
|
+
end
|
28
|
+
|
29
|
+
# transforms this content into a parameter hash for rails (server-side usage)
|
30
|
+
def self.to_hash(content)
|
31
|
+
Hash.from_xml(content).with_indifferent_access
|
32
|
+
end
|
33
|
+
|
34
|
+
def prepare_link_for(link)
|
35
|
+
link
|
36
|
+
end
|
37
|
+
|
38
|
+
def prepare_link_for(link)
|
39
|
+
link
|
40
|
+
end
|
41
|
+
|
42
|
+
def prepare_link_for(link)
|
43
|
+
link
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Restfulie::Common::Representation
|
2
|
+
# Unknown representation's unmarshalling on the client side
|
3
|
+
class Generic
|
4
|
+
|
5
|
+
def self.media_type_name
|
6
|
+
raise Restfulie::Common::Error::RestfulieError.new("Generic representation does not have a specific media type")
|
7
|
+
end
|
8
|
+
|
9
|
+
cattr_reader :headers
|
10
|
+
@@headers = {
|
11
|
+
:get => { },
|
12
|
+
:post => { }
|
13
|
+
}
|
14
|
+
|
15
|
+
# Because there is no media type registered, return the content itself
|
16
|
+
def unmarshal(content)
|
17
|
+
def content.links
|
18
|
+
[]
|
19
|
+
end
|
20
|
+
content
|
21
|
+
end
|
22
|
+
|
23
|
+
def marshal(string, rel)
|
24
|
+
string
|
25
|
+
end
|
26
|
+
|
27
|
+
def prepare_link_for(link)
|
28
|
+
link
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Restfulie::Common::Representation
|
2
|
+
# Implements the interface for marshal Xml media type requests (application/xml)
|
3
|
+
class XmlD
|
4
|
+
|
5
|
+
cattr_reader :media_type_name
|
6
|
+
@@media_type_name = 'application/xml'
|
7
|
+
|
8
|
+
cattr_reader :headers
|
9
|
+
@@headers = {
|
10
|
+
:post => { 'Content-Type' => media_type_name }
|
11
|
+
}
|
12
|
+
|
13
|
+
def unmarshal(string)
|
14
|
+
raise "should never be invoked, xml to ruby objects should be handled by rails itself"
|
15
|
+
end
|
16
|
+
|
17
|
+
def marshal(string, rel)
|
18
|
+
string
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'active_support'
|
6
|
+
require 'action_controller'
|
7
|
+
|
8
|
+
require 'vendor/atom'
|
9
|
+
|
10
|
+
module Restfulie
|
11
|
+
module Common; end
|
12
|
+
end
|
13
|
+
|
14
|
+
%w(
|
15
|
+
errors
|
16
|
+
logger
|
17
|
+
builder
|
18
|
+
representation
|
19
|
+
).each do |file|
|
20
|
+
require "restfulie/common/#{file}"
|
21
|
+
end
|
22
|
+
|
23
|
+
include ActiveSupport::CoreExtensions::Hash
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Restfulie
|
2
|
+
module Server
|
3
|
+
module ActionController
|
4
|
+
|
5
|
+
module Base
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
# Sets a default responder for this controller.
|
9
|
+
# Needs to require responder_legacy.rb
|
10
|
+
base.responder = Restfulie::Server::ActionController::RestfulResponder
|
11
|
+
# Atom representation is added by default
|
12
|
+
ParamsParser.register('application/atom+xml', Restfulie::Common::Representation::Atom)
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
# If your controller inherits from Restfulie::Server::Controller::Base,
|
18
|
+
# it will have an :atom option, very similar to render :xml
|
19
|
+
def render(options = {}, extra_options = {}, &block)
|
20
|
+
if atom = options[:atom]
|
21
|
+
response.content_type ||= Mime::ATOM
|
22
|
+
render_for_text(atom.respond_to?(:to_atom) ? atom.to_atom.to_xml : atom.to_xml, options[:status])
|
23
|
+
else
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Restfulie
|
2
|
+
module Server
|
3
|
+
module ActionController
|
4
|
+
class ParamsParser
|
5
|
+
# This class is just a proxy for the extension point offered by ActionController::Base
|
6
|
+
@@param_parsers = ::ActionController::Base.param_parsers
|
7
|
+
|
8
|
+
##
|
9
|
+
# :singleton-method:
|
10
|
+
# Use it to register param parsers on the server side.
|
11
|
+
#
|
12
|
+
# * <tt>media type</tt>
|
13
|
+
# * <tt>a restfulie representation with to_hash method</tt>
|
14
|
+
#
|
15
|
+
# Restfulie::Server::ActionController::ParamsParser.register('application/atom+xml', Atom)
|
16
|
+
#
|
17
|
+
def self.register(content_type, representation)
|
18
|
+
@@param_parsers[Mime::Type.lookup(content_type)] = representation.method(:to_hash).to_proc
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# :singleton-method:
|
23
|
+
# Use it to unregister param parsers on the server side.
|
24
|
+
#
|
25
|
+
# * <tt>media type</tt>
|
26
|
+
#
|
27
|
+
# Restfulie::Server::ActionController::ParamsParser.unregister('application/atom+xml')
|
28
|
+
#
|
29
|
+
def self.unregister(content_type)
|
30
|
+
@@param_parsers.delete(Mime::Type.lookup(content_type))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# This monkey patch is needed because Rails 2.3.5 doesn't support
|
38
|
+
# a way of use rescue_from ActionController handling to return
|
39
|
+
# bad request status when trying to parse an invalid body request
|
40
|
+
#
|
41
|
+
# In Rails 3 this won't be necessary, because all exception handling
|
42
|
+
# extensions are handled by the Rack stack
|
43
|
+
#
|
44
|
+
# TODO Change this when porting this code to Rails 3
|
45
|
+
::ActionController::ParamsParser.class_eval do
|
46
|
+
def call(env)
|
47
|
+
begin
|
48
|
+
if params = parse_formatted_parameters(env)
|
49
|
+
env["action_controller.request.request_parameters"] = params
|
50
|
+
else
|
51
|
+
if env["CONTENT_LENGTH"] && (env["CONTENT_LENGTH"] != "0")
|
52
|
+
return [415, {'Content-Type' => 'text/html'}, "<html><body><h1>415 Unsupported Media Type</h1></body></html>"]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
rescue
|
56
|
+
return [400, {'Content-Type' => 'text/html'}, "<html><body><h1>400 Bad Request</h1></body></html>"]
|
57
|
+
end
|
58
|
+
|
59
|
+
@app.call(env)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Restfulie::Server::ActionController
|
2
|
+
class RestfulResponder < ActionController::Responder
|
3
|
+
|
4
|
+
def to_format
|
5
|
+
return if do_http_cache? && do_http_cache!
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
protected
|
10
|
+
def do_http_cache!
|
11
|
+
timestamp = resources.flatten.map do |resource|
|
12
|
+
(resource.updated_at || Time.now).utc if resource.respond_to?(:updated_at)
|
13
|
+
end.compact.max
|
14
|
+
|
15
|
+
controller.response.last_modified = timestamp if timestamp
|
16
|
+
set_public_cache_control!
|
17
|
+
|
18
|
+
head :not_modified if fresh = request.fresh?(controller.response)
|
19
|
+
fresh
|
20
|
+
end
|
21
|
+
|
22
|
+
def do_http_cache?
|
23
|
+
get? && @http_cache != false && ActionController::Base.perform_caching &&
|
24
|
+
!new_record? && controller.response.last_modified.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def new_record?
|
28
|
+
resource.respond_to?(:new_record?) && resource.new_record?
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_public_cache_control!
|
32
|
+
cache_control = response.headers["Cache-Control"].split(",").map {|k| k.strip }
|
33
|
+
cache_control.delete("private")
|
34
|
+
cache_control.delete("no-cache")
|
35
|
+
cache_control << "public"
|
36
|
+
response.headers["Cache-Control"] = cache_control.join(', ')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Restfulie::Server::ActionController::Routing::Route
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
#base.alias_method_chain :extract_request_environment, :host
|
5
|
+
end
|
6
|
+
|
7
|
+
#def extract_request_environment_with_host(request)
|
8
|
+
#env = extract_request_environment_without_host(request)
|
9
|
+
#env.merge :host => request.host,
|
10
|
+
#:domain => request.domain, :subdomain => request.subdomains.first
|
11
|
+
#end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Restfulie::Server::ActionController::Routing#:nodoc:
|
2
|
+
end
|
3
|
+
|
4
|
+
require 'restfulie/server/action_controller/routing/restful_route'
|
5
|
+
|
6
|
+
ActionController::Routing::RouteSet.send :include,
|
7
|
+
Restfulie::Server::ActionController::Routing::Route
|
8
|
+
|
9
|
+
ActionController::Routing::Route.send :include,
|
10
|
+
Restfulie::Server::ActionController::Routing::Route
|
11
|
+
|
12
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Restfulie::Server::ActionController#:nodoc:
|
2
|
+
|
3
|
+
if defined?(::ActionController) || defined?(::ApplicationController)
|
4
|
+
|
5
|
+
%w(
|
6
|
+
params_parser
|
7
|
+
restful_responder
|
8
|
+
base
|
9
|
+
routing
|
10
|
+
).each do |file|
|
11
|
+
autoload file.camelize.to_sym, "restfulie/server/action_controller/#{file}"
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Restfulie::Server::ActionView::Helpers
|
2
|
+
# Load a partial template to execute in describe
|
3
|
+
#
|
4
|
+
# For example:
|
5
|
+
#
|
6
|
+
# Passing the current context to partial in template:
|
7
|
+
#
|
8
|
+
# describe_member(@album) do |member, album|
|
9
|
+
# partial('member', binding)
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# in partial:
|
13
|
+
#
|
14
|
+
# member.links << link(:rel => :artistis, :href => album_artists_url(album))
|
15
|
+
#
|
16
|
+
# Or passing local variables assing
|
17
|
+
#
|
18
|
+
# descirbe_collection(@albums) do |collection|
|
19
|
+
# collection.describe_members do |member, album|
|
20
|
+
# partial('member', :locals => {:member => member, :album => album})
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
def partial(partial_path, caller_binding = nil)
|
25
|
+
template = _pick_partial_template(partial_path)
|
26
|
+
|
27
|
+
# Create a context to assing variables
|
28
|
+
if caller_binding.kind_of?(Hash)
|
29
|
+
Proc.new do
|
30
|
+
extend Restfulie::Common::Builder::Helpers
|
31
|
+
context = eval("(class << self; self; end)", binding)
|
32
|
+
|
33
|
+
unless caller_binding[:locals].nil?
|
34
|
+
caller_binding[:locals].each do |k, v|
|
35
|
+
context.send(:define_method, k.to_sym) { v }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
partial(partial_path, binding)
|
40
|
+
end.call
|
41
|
+
else
|
42
|
+
eval(template.source, caller_binding, template.path)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Restfulie::Server::ActionView::TemplateHandlers
|
2
|
+
|
3
|
+
class Tokamak < ActionView::TemplateHandler
|
4
|
+
include ActionView::TemplateHandlers::Compilable
|
5
|
+
|
6
|
+
# TODO: Implement error for code not return builder
|
7
|
+
def compile(template)
|
8
|
+
"extend Restfulie::Common::Builder::Helpers; " +
|
9
|
+
"extend Restfulie::Server::ActionView::Helpers; " +
|
10
|
+
"code_block = lambda { #{template.source} };" +
|
11
|
+
"builder = code_block.call; " +
|
12
|
+
"builder.to_atom "
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Restfulie::Server::ActionView::TemplateHandlers #:nodoc:
|
2
|
+
end
|
3
|
+
|
4
|
+
require 'restfulie/server/action_view/template_handlers/tokamak'
|
5
|
+
|
6
|
+
if defined? ::ActionView::Template and ::ActionView::Template.respond_to? :register_template_handler
|
7
|
+
::ActionView::Template
|
8
|
+
else
|
9
|
+
::ActionView::Base
|
10
|
+
end.register_template_handler(:tokamak, Restfulie::Server::ActionView::TemplateHandlers::Tokamak)
|
11
|
+
|
12
|
+
::ActionController::Base.exempt_from_layout :tokamak if defined? ::ActionController::Base
|
13
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Restfulie::Server::Configuration
|
2
|
+
#Defines host to be passed to polymorphic_url.
|
3
|
+
# You need to setup this to your own domain in order to generate meaningful links.
|
4
|
+
mattr_accessor :host
|
5
|
+
@@host = 'localhost'
|
6
|
+
|
7
|
+
# Passes a symbol to polymorphic_url in order to use a namespaced named_route.
|
8
|
+
# So, if config.named_route_prefix = :rest, it will search for rest_album_url,
|
9
|
+
# rest_album_songs_url, and so on.
|
10
|
+
mattr_accessor :named_route_prefix
|
11
|
+
@@named_route_prefix = nil
|
12
|
+
|
13
|
+
# This defines a Rails-like way to setup options. You can do, in a initializer:
|
14
|
+
# Restfulie::Server.setup do |config|
|
15
|
+
# config.host = 'mydomain.com'
|
16
|
+
# end
|
17
|
+
def self.setup
|
18
|
+
yield self
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Introspective methods to assist in the conversion of collections in other formats.
|
2
|
+
class Array
|
3
|
+
def to_atom(options={}, &block)
|
4
|
+
raise "Not all elements respond to to_atom" unless all? { |e| e.respond_to? :to_atom }
|
5
|
+
options = options.dup
|
6
|
+
|
7
|
+
if options.delete :only_self_link
|
8
|
+
options[:skip_associations_links] = true
|
9
|
+
options[:skip_attributes] = true
|
10
|
+
end
|
11
|
+
|
12
|
+
Atom::Feed.new do |feed|
|
13
|
+
# TODO: Define better feed attributes
|
14
|
+
# Array#to_s can return a very long string
|
15
|
+
feed.title = "Collection of #{map {|i| i.class.name }.uniq.to_sentence}"
|
16
|
+
# TODO: this id does not comply with Rest standards yet
|
17
|
+
feed.id = hash
|
18
|
+
feed.updated = updated_at
|
19
|
+
|
20
|
+
each do |element|
|
21
|
+
feed.entries << element.to_atom(options)
|
22
|
+
end
|
23
|
+
|
24
|
+
yield feed if block_given?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return max update date for items in collection, for it uses the updated_at of items.
|
29
|
+
#
|
30
|
+
#==Example:
|
31
|
+
#
|
32
|
+
# Find max updated at in ActiveRecord objects
|
33
|
+
#
|
34
|
+
# albums = Albums.find(:all)
|
35
|
+
# albums.updated_at
|
36
|
+
#
|
37
|
+
# Using a custom field to check the max date
|
38
|
+
#
|
39
|
+
# albums = Albums.find(:all)
|
40
|
+
# albums.updated_at(:created_at)
|
41
|
+
#
|
42
|
+
def updated_at(field = :updated_at)
|
43
|
+
map { |item| item.send(field) if item.respond_to?(field) }.compact.max || Time.now
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'restfulie/server/core_ext/array'
|
@@ -1,25 +1,9 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
-
# All rights reserved.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
#
|
17
|
-
|
18
1
|
module Restfulie
|
19
2
|
|
20
3
|
module Server
|
21
4
|
|
22
5
|
# Controller which adds default CRUD + search + other operations.
|
6
|
+
# TODO: move these actions to controller/base.rb (maybe using InheritedResources, maybe not)
|
23
7
|
module Controller
|
24
8
|
|
25
9
|
# creates a model based on the request media-type extracted from its content-type
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'restfulie/common'
|
2
|
+
require 'responders_backport'
|
3
|
+
|
4
|
+
module Restfulie::Server; end
|
5
|
+
|
6
|
+
%w(
|
7
|
+
configuration
|
8
|
+
action_controller
|
9
|
+
action_view
|
10
|
+
core_ext
|
11
|
+
restfulie_controller
|
12
|
+
).each do |file|
|
13
|
+
require "restfulie/server/#{file}"
|
14
|
+
end
|
15
|
+
|