party_resource 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +19 -0
- data/lib/party_resource/buildable.rb +60 -0
- data/lib/party_resource/connector/base.rb +35 -0
- data/lib/party_resource/connector.rb +42 -0
- data/lib/party_resource/exceptions.rb +57 -0
- data/lib/party_resource/method_define.rb +11 -0
- data/lib/party_resource/party_resource.rb +91 -0
- data/lib/party_resource/property.rb +53 -0
- data/lib/party_resource/request.rb +36 -0
- data/lib/party_resource/route.rb +77 -0
- data/lib/party_resource.rb +8 -0
- data/spec/fixtures/other_class.rb +19 -0
- data/spec/fixtures/test_base_class.rb +17 -0
- data/spec/fixtures/test_class.rb +44 -0
- data/spec/integration/integration_spec.rb +173 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/unit/connector/base_spec.rb +83 -0
- data/spec/unit/connector_spec.rb +75 -0
- data/spec/unit/exceptions_spec.rb +34 -0
- data/spec/unit/party_resource_spec.rb +227 -0
- data/spec/unit/request_spec.rb +103 -0
- data/spec/unit/route_spec.rb +118 -0
- metadata +150 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Eden Development (UK) LTD
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= party_resource
|
2
|
+
|
3
|
+
Simple REST interface for ruby objects.
|
4
|
+
|
5
|
+
party_resource is a framework for building ruby objects which interact with a REST api. Built on top of HTTParty.
|
6
|
+
|
7
|
+
== Note on Patches/Pull Requests
|
8
|
+
|
9
|
+
* Fork the project.
|
10
|
+
* Make your feature addition or bug fix.
|
11
|
+
* Add tests for it. This is important so I don't break it in a
|
12
|
+
future version unintentionally.
|
13
|
+
* Commit, do not mess with rakefile, version, or history.
|
14
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
15
|
+
* Send me a pull request. Bonus points for topic branches.
|
16
|
+
|
17
|
+
== Copyright
|
18
|
+
|
19
|
+
Copyright (c) 2010 Eden Development (UK) LTD. See LICENSE for details.
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module PartyResource
|
2
|
+
module Buildable
|
3
|
+
|
4
|
+
def builder
|
5
|
+
Builder.new(@options[:as])
|
6
|
+
end
|
7
|
+
|
8
|
+
class Builder
|
9
|
+
def initialize(build_options)
|
10
|
+
@build_options = build_options
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(raw_result, context, included)
|
14
|
+
return nil if raw_result.nil?
|
15
|
+
return raw_result.map{ |value| build_result(value, context, included) } if map_result?(raw_result)
|
16
|
+
build_result(raw_result, context, included)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def builder
|
21
|
+
return lambda {|raw_result, context| raw_result} if wants_raw_result?
|
22
|
+
return lambda {|raw_result, context| return_type(context).send(return_method,raw_result) } if wants_object?
|
23
|
+
return lambda {|raw_result, context| @build_options.call(raw_result) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def build_result(value, context, included)
|
27
|
+
if value.is_a? Hash
|
28
|
+
value.merge!(included)
|
29
|
+
end
|
30
|
+
builder.call(value, context)
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def map_result?(result)
|
35
|
+
result.is_a?(Array) && !wants_raw_result?
|
36
|
+
end
|
37
|
+
|
38
|
+
def wants_raw_result?
|
39
|
+
return_type == :raw
|
40
|
+
end
|
41
|
+
|
42
|
+
def wants_object?
|
43
|
+
@build_options.is_a?(Array) || @build_options.is_a?(Class) || @build_options == :self
|
44
|
+
end
|
45
|
+
|
46
|
+
def return_type(context=nil)
|
47
|
+
return_type = @build_options.is_a?(Array) ? @build_options.first : @build_options
|
48
|
+
if return_type == :self
|
49
|
+
return_type = context.is_a?(Class) ? context : context.class
|
50
|
+
end
|
51
|
+
return_type
|
52
|
+
end
|
53
|
+
|
54
|
+
def return_method
|
55
|
+
@build_options.is_a?(Array) ? @build_options.last : :new
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
module PartyResource
|
3
|
+
module Connector
|
4
|
+
|
5
|
+
class Base
|
6
|
+
attr :options
|
7
|
+
|
8
|
+
def initialize(name, options)
|
9
|
+
self.options = options
|
10
|
+
@name = name
|
11
|
+
end
|
12
|
+
|
13
|
+
def fetch(request)
|
14
|
+
response = HTTParty.send(request.verb, request.path, request.http_data(options))
|
15
|
+
unless (200..399).include? response.code
|
16
|
+
raise PartyResource::ConnectionError.build(response)
|
17
|
+
end
|
18
|
+
response
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def options=(options)
|
24
|
+
@options = {}
|
25
|
+
@options[:base_uri] = HTTParty.normalize_base_uri(options[:base_uri]) if options.has_key?(:base_uri)
|
26
|
+
|
27
|
+
if options.has_key?(:username) || options.has_key?(:password)
|
28
|
+
@options[:basic_auth] = {:username => options[:username], :password => options[:password]}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'party_resource/connector/base'
|
2
|
+
module PartyResource
|
3
|
+
def self.Connector(name = nil)
|
4
|
+
Connector.lookup(name)
|
5
|
+
end
|
6
|
+
|
7
|
+
module Connector
|
8
|
+
def self.lookup(name)
|
9
|
+
name ||= repository.default
|
10
|
+
connector = repository.connectors[name]
|
11
|
+
raise NoConnector.new(name) if connector.nil?
|
12
|
+
connector
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.default=(name)
|
16
|
+
repository.default = name
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.add(name, options)
|
20
|
+
repository.new_connector(name, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.repository
|
24
|
+
@repository ||= Repository.new
|
25
|
+
end
|
26
|
+
|
27
|
+
class Repository
|
28
|
+
attr_accessor :default
|
29
|
+
|
30
|
+
def connectors
|
31
|
+
@connectors ||= {}
|
32
|
+
end
|
33
|
+
|
34
|
+
def new_connector(name, options)
|
35
|
+
connectors[name] = Base.new(name, options)
|
36
|
+
self.default = name if default.nil? || options[:default]
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module PartyResource
|
2
|
+
|
3
|
+
Error = Class.new(StandardError)
|
4
|
+
|
5
|
+
class MissingParameter < Error
|
6
|
+
def initialize(parameter, context)
|
7
|
+
@parameter = parameter
|
8
|
+
@context = context
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"No value for #{@parameter} is available in #{@context}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class NoConnector < Error
|
17
|
+
def initialize(name)
|
18
|
+
@name = name
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"Connector '#{@name}' has not been defined"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class ConnectionError < Error;
|
27
|
+
attr_reader :data
|
28
|
+
|
29
|
+
def self.build(data=nil)
|
30
|
+
klass = case data.code
|
31
|
+
when 404: ResourceNotFound
|
32
|
+
when 422: ResourceInvalid
|
33
|
+
when 400..499: ClientError
|
34
|
+
when 500..599: ServerError
|
35
|
+
else self
|
36
|
+
end
|
37
|
+
klass.new(data)
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(data=nil)
|
41
|
+
super()
|
42
|
+
@data = data
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
code = ''
|
47
|
+
code = "#{data.code} " rescue nil
|
48
|
+
"A #{code}connection error occured"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
ClientError = Class.new(ConnectionError) # 4xx
|
53
|
+
ServerError = Class.new(ConnectionError) # 5xx
|
54
|
+
|
55
|
+
ResourceNotFound = Class.new(ClientError) # 404
|
56
|
+
ResourceInvalid = Class.new(ClientError) # 422
|
57
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module MethodDefine
|
2
|
+
private
|
3
|
+
def define_meta_method(name, &blk)
|
4
|
+
(class << self; self; end).instance_eval { define_method name, &blk }
|
5
|
+
end
|
6
|
+
|
7
|
+
def define_method_on(level, name, &block)
|
8
|
+
creator = level == :instance ? :define_method : :define_meta_method
|
9
|
+
send(creator, name, &block)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
|
+
Hash.send(:include, ActiveSupport::CoreExtensions::Hash::IndifferentAccess) unless Hash.method_defined?(:with_indifferent_access)
|
3
|
+
|
4
|
+
module PartyResource
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
include MethodDefine
|
8
|
+
|
9
|
+
def connect(name, options={})
|
10
|
+
level = options.delete(:on)
|
11
|
+
options = {:as => :self, :connector => @party_connector}.merge(options)
|
12
|
+
route = Route.new(options)
|
13
|
+
|
14
|
+
define_method_on(level, name) do |*args|
|
15
|
+
route.call(self, *args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def property(*names)
|
20
|
+
options = names.pop if names.last.is_a?(Hash)
|
21
|
+
names.each do |name|
|
22
|
+
name = name.to_sym
|
23
|
+
define_method name do
|
24
|
+
get_property(name)
|
25
|
+
end
|
26
|
+
@property_list ||= []
|
27
|
+
@property_list << Property.new(name, options)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def party_connector(name)
|
32
|
+
@party_connector = name
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def property_list
|
37
|
+
@property_list ||= []
|
38
|
+
if superclass.include?(PartyResource)
|
39
|
+
@property_list + superclass.send(:property_list)
|
40
|
+
else
|
41
|
+
@property_list
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module ParameterValues
|
47
|
+
def parameter_values(list)
|
48
|
+
list.inject({}) do |out, var|
|
49
|
+
begin
|
50
|
+
out[var] = send(var)
|
51
|
+
rescue
|
52
|
+
raise MissingParameter.new(var, self)
|
53
|
+
end
|
54
|
+
out
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_properties_hash
|
60
|
+
self.class.send(:property_list).inject({}) do |hash, property|
|
61
|
+
hash.merge(property.to_hash(self))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def properties_equal?(other)
|
66
|
+
begin
|
67
|
+
self.class.send(:property_list).all? {|property| self.send(property.name) == other.send(property.name) }
|
68
|
+
rescue NoMethodError
|
69
|
+
false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
private
|
75
|
+
def populate_properties(hash)
|
76
|
+
hash = hash.with_indifferent_access
|
77
|
+
self.class.send(:property_list).each do |property|
|
78
|
+
instance_variable_set("@#{property.name}", property.value_from(hash, self)) if property.has_value_in?(hash)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.included(klass)
|
83
|
+
klass.extend(ClassMethods)
|
84
|
+
klass.extend(ParameterValues)
|
85
|
+
klass.send(:include, ParameterValues)
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_property(name)
|
89
|
+
instance_variable_get("@#{name}")
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'party_resource/buildable'
|
2
|
+
module PartyResource
|
3
|
+
class Property
|
4
|
+
include Buildable
|
5
|
+
|
6
|
+
attr :name
|
7
|
+
|
8
|
+
def initialize(name, options)
|
9
|
+
@name = name
|
10
|
+
@options = {:as => :raw}.merge(options || {})
|
11
|
+
end
|
12
|
+
|
13
|
+
def value_from(hash, context)
|
14
|
+
builder.call retrieve_value(hash), context, {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def has_value_in?(hash)
|
18
|
+
input_hash(hash).has_key?(input_key) || hash.has_key?(name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_hash(context)
|
22
|
+
value = context.send(name)
|
23
|
+
return {} if value.nil?
|
24
|
+
value = value.to_properties_hash if value.respond_to?(:to_properties_hash)
|
25
|
+
output_keys.reverse.inject(value) do |value, key|
|
26
|
+
{key => value}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def retrieve_value(hash)
|
32
|
+
input_hash(hash)[input_key] || hash[name]
|
33
|
+
end
|
34
|
+
|
35
|
+
def input_hash(hash)
|
36
|
+
input_keys[0..-2].inject(hash) do |value, name|
|
37
|
+
value[name] || {}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def input_keys
|
42
|
+
[@options[:from] || name].flatten
|
43
|
+
end
|
44
|
+
|
45
|
+
def output_keys
|
46
|
+
[@options[:to] || input_keys].flatten
|
47
|
+
end
|
48
|
+
|
49
|
+
def input_key
|
50
|
+
input_keys.last
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PartyResource
|
2
|
+
class Request
|
3
|
+
attr_reader :verb
|
4
|
+
def initialize(verb, path, context, args, params)
|
5
|
+
@verb = verb
|
6
|
+
@path = path
|
7
|
+
@args = args
|
8
|
+
@context = context
|
9
|
+
@params = params || {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def path
|
13
|
+
args = @context.parameter_values(path_params - @args.keys).merge(@args)
|
14
|
+
URI.encode(path_params.inject(@path) do |path, param|
|
15
|
+
path.gsub(":#{param}", args[param].to_s)
|
16
|
+
end)
|
17
|
+
end
|
18
|
+
|
19
|
+
def data
|
20
|
+
@params.merge(@args).reject{|name,value| path_params.include?(name)}
|
21
|
+
end
|
22
|
+
|
23
|
+
def http_data(options={})
|
24
|
+
options = options.merge(self.params_key => self.data) unless self.data.empty?
|
25
|
+
options
|
26
|
+
end
|
27
|
+
|
28
|
+
def params_key
|
29
|
+
verb == :get ? :query : :body
|
30
|
+
end
|
31
|
+
|
32
|
+
def path_params
|
33
|
+
@path.scan(/:([\w]+)/).flatten.map{|p| p.to_sym}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'party_resource/buildable'
|
2
|
+
module PartyResource
|
3
|
+
|
4
|
+
class Route
|
5
|
+
include Buildable
|
6
|
+
|
7
|
+
VERBS = [:get, :post, :put, :delete]
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@options = transform_options(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(context, *args)
|
14
|
+
options = args.pop if args.last.is_a?(Hash) && args.size == expected_args.size + 1
|
15
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for #{expected_args.size})" unless expected_args.size == args.size
|
16
|
+
begin
|
17
|
+
builder.call(connector.fetch(request(context, args, options)), context, included(context))
|
18
|
+
rescue Error => e
|
19
|
+
name = e.class.name.split(/::/).last
|
20
|
+
return @options[:rescue][name] if @options[:rescue].has_key?(name)
|
21
|
+
raise
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def connector
|
26
|
+
PartyResource::Connector(@options[:connector])
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def request(context, args, params)
|
31
|
+
Request.new(@options[:verb], @options[:path], context, args_hash(args), params)
|
32
|
+
end
|
33
|
+
|
34
|
+
def args_hash(args)
|
35
|
+
Hash[*expected_args.zip(args).flatten]
|
36
|
+
end
|
37
|
+
|
38
|
+
def transform_options(options)
|
39
|
+
options = {:with => [], :including => {}, :rescue => {}}.merge(options)
|
40
|
+
transform_with_option(options)
|
41
|
+
transform_location_options(options)
|
42
|
+
options
|
43
|
+
end
|
44
|
+
|
45
|
+
def transform_with_option(options)
|
46
|
+
options[:with] = [options[:with]] unless options[:with].is_a?(Array)
|
47
|
+
end
|
48
|
+
|
49
|
+
def transform_location_options(options)
|
50
|
+
verbs = options.keys & VERBS
|
51
|
+
raise ArgumentError, "Must define only one verb (#{verbs.inspect} defined)" unless verbs.size == 1
|
52
|
+
options[:verb] = verbs.first
|
53
|
+
options[:path] = options.delete(options[:verb])
|
54
|
+
end
|
55
|
+
|
56
|
+
def expected_args
|
57
|
+
@options[:with]
|
58
|
+
end
|
59
|
+
|
60
|
+
def including
|
61
|
+
@options[:including]
|
62
|
+
end
|
63
|
+
|
64
|
+
def included(context)
|
65
|
+
return {} if including.empty?
|
66
|
+
|
67
|
+
context_hash = context.parameter_values(including.values)
|
68
|
+
|
69
|
+
including.inject({}) do |hash, pair|
|
70
|
+
hash[pair.first] = context_hash[pair.last]
|
71
|
+
hash
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/party_resource/method_define')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/party_resource/exceptions')
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/party_resource/property')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/party_resource/party_resource')
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/party_resource/route')
|
6
|
+
require File.expand_path(File.dirname(__FILE__) + '/party_resource/request')
|
7
|
+
require File.expand_path(File.dirname(__FILE__) + '/party_resource/connector')
|
8
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class OtherClass < TestBaseClass
|
2
|
+
def self.make_boolean(data)
|
3
|
+
data =~ /OK/
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
|
8
|
+
class OtherPartyClass
|
9
|
+
include PartyResource
|
10
|
+
party_connector :other_connector
|
11
|
+
|
12
|
+
connect :test, :get => '/url', :as => :raw
|
13
|
+
|
14
|
+
property :thing
|
15
|
+
|
16
|
+
def initialize(args)
|
17
|
+
populate_properties(args)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class TestBaseClass
|
2
|
+
attr :args
|
3
|
+
|
4
|
+
def initialize(args={})
|
5
|
+
@args = args
|
6
|
+
end
|
7
|
+
|
8
|
+
def method_missing(name, *params)
|
9
|
+
return args[name] if params.empty? && args.has_key?(name)
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def ==(other)
|
14
|
+
self.class == other.class && args == other.args
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
PartyResource::Connector.add(:other_connector, {:base_uri => 'http://otherserver/'})
|
2
|
+
PartyResource::Connector.add(:my_connector, {:base_uri => 'http://myserver/path', :username => 'fred', :password => 'pass', :default => true})
|
3
|
+
|
4
|
+
class TestClass < TestBaseClass
|
5
|
+
include PartyResource
|
6
|
+
|
7
|
+
connect :find, :get => '/find/:id.ext', :with => :id, :on => :class
|
8
|
+
|
9
|
+
connect :update, :put => '/update/:var.ext', :on => :instance, :as => OtherClass
|
10
|
+
|
11
|
+
connect :save, :post => '/save/file', :with => :data, :as => :raw
|
12
|
+
|
13
|
+
connect :destroy, :delete => '/delete', :as => [OtherClass, :make_boolean]
|
14
|
+
|
15
|
+
connect :foo, :get => '/foo', :with => :value, :as => lambda {|data| "New #{data} Improved" }
|
16
|
+
|
17
|
+
connect :fetch_json, :get => '/big_data', :as => [:self, :from_json], :rescue => {'ResourceNotFound' => nil}
|
18
|
+
|
19
|
+
connect :include, :get => '/include', :on => :instance, :as => OtherClass, :including => {:thing => :value2}
|
20
|
+
|
21
|
+
property :value, :from => :input_name
|
22
|
+
|
23
|
+
property :value2, :value3
|
24
|
+
|
25
|
+
property :nested_value, :from => [:block, :var]
|
26
|
+
|
27
|
+
property :other, :as => OtherClass
|
28
|
+
|
29
|
+
property :processed, :as => lambda { |data| "Processed: #{data}" }, :to => :output_name
|
30
|
+
|
31
|
+
property :child, :as => OtherPartyClass
|
32
|
+
|
33
|
+
def self.from_json(args)
|
34
|
+
obj = self.new
|
35
|
+
obj.send(:populate_properties, args)
|
36
|
+
obj
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
class InheritedTestClass < TestClass
|
42
|
+
property :child_property
|
43
|
+
end
|
44
|
+
|