restfulie 0.1.0.beta1
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/Gemfile +28 -0
- data/Gemfile.lock +128 -0
- data/LICENSE +17 -0
- data/README.textile +138 -0
- data/Rakefile +146 -0
- data/lib/restfulie/client/base.rb +36 -0
- data/lib/restfulie/client/cache/basic.rb +76 -0
- data/lib/restfulie/client/cache/fake.rb +15 -0
- data/lib/restfulie/client/cache/http_ext.rb +123 -0
- data/lib/restfulie/client/cache/restrictions.rb +13 -0
- data/lib/restfulie/client/cache.rb +11 -0
- data/lib/restfulie/client/configuration.rb +67 -0
- data/lib/restfulie/client/dsl.rb +66 -0
- data/lib/restfulie/client/entry_point.rb +61 -0
- data/lib/restfulie/client/ext/atom_ext.rb +14 -0
- data/lib/restfulie/client/ext/http_ext.rb +22 -0
- data/lib/restfulie/client/ext/json_ext.rb +16 -0
- data/lib/restfulie/client/feature/base.rb +75 -0
- data/lib/restfulie/client/feature/base_request.rb +35 -0
- data/lib/restfulie/client/feature/cache.rb +16 -0
- data/lib/restfulie/client/feature/enhance_response.rb +12 -0
- data/lib/restfulie/client/feature/follow_request.rb +41 -0
- data/lib/restfulie/client/feature/history.rb +26 -0
- data/lib/restfulie/client/feature/history_request.rb +19 -0
- data/lib/restfulie/client/feature/open_search/pattern_matcher.rb +25 -0
- data/lib/restfulie/client/feature/open_search.rb +21 -0
- data/lib/restfulie/client/feature/serialize_body.rb +32 -0
- data/lib/restfulie/client/feature/setup_header.rb +22 -0
- data/lib/restfulie/client/feature/throw_error.rb +41 -0
- data/lib/restfulie/client/feature/verb.rb +119 -0
- data/lib/restfulie/client/feature.rb +5 -0
- data/lib/restfulie/client/http/cache.rb +28 -0
- data/lib/restfulie/client/http/error.rb +77 -0
- data/lib/restfulie/client/http/response_holder.rb +29 -0
- data/lib/restfulie/client/http.rb +7 -0
- data/lib/restfulie/client/master_delegator.rb +31 -0
- data/lib/restfulie/client/mikyung/concatenator.rb +18 -0
- data/lib/restfulie/client/mikyung/core.rb +70 -0
- data/lib/restfulie/client/mikyung/languages/german.rb +24 -0
- data/lib/restfulie/client/mikyung/languages/portuguese.rb +23 -0
- data/lib/restfulie/client/mikyung/languages.rb +11 -0
- data/lib/restfulie/client/mikyung/rest_process_model.rb +191 -0
- data/lib/restfulie/client/mikyung/steady_state_walker.rb +38 -0
- data/lib/restfulie/client/mikyung/then_condition.rb +39 -0
- data/lib/restfulie/client/mikyung/when_condition.rb +57 -0
- data/lib/restfulie/client/mikyung.rb +15 -0
- data/lib/restfulie/client.rb +26 -0
- data/lib/restfulie/common/converter/atom/base.rb +91 -0
- data/lib/restfulie/common/converter/atom/builder.rb +111 -0
- data/lib/restfulie/common/converter/atom/helpers.rb +17 -0
- data/lib/restfulie/common/converter/atom.rb +12 -0
- data/lib/restfulie/common/converter/json/base.rb +87 -0
- data/lib/restfulie/common/converter/json/builder.rb +102 -0
- data/lib/restfulie/common/converter/json/helpers.rb +17 -0
- data/lib/restfulie/common/converter/json.rb +12 -0
- data/lib/restfulie/common/converter/open_search/descriptor.rb +32 -0
- data/lib/restfulie/common/converter/open_search.rb +16 -0
- data/lib/restfulie/common/converter/values.rb +33 -0
- data/lib/restfulie/common/converter/xml/base.rb +63 -0
- data/lib/restfulie/common/converter/xml/builder.rb +113 -0
- data/lib/restfulie/common/converter/xml/helpers.rb +17 -0
- data/lib/restfulie/common/converter/xml/link.rb +30 -0
- data/lib/restfulie/common/converter/xml/links.rb +21 -0
- data/lib/restfulie/common/converter/xml.rb +14 -0
- data/lib/restfulie/common/converter.rb +43 -0
- data/lib/restfulie/common/core_ext/hash.rb +18 -0
- data/lib/restfulie/common/core_ext.rb +1 -0
- data/lib/restfulie/common/error.rb +19 -0
- data/lib/restfulie/common/links.rb +9 -0
- data/lib/restfulie/common/logger.rb +19 -0
- data/lib/restfulie/common/representation/atom/atom.rng +597 -0
- data/lib/restfulie/common/representation/atom/base.rb +142 -0
- data/lib/restfulie/common/representation/atom/category.rb +41 -0
- data/lib/restfulie/common/representation/atom/entry.rb +59 -0
- data/lib/restfulie/common/representation/atom/factory.rb +43 -0
- data/lib/restfulie/common/representation/atom/feed.rb +110 -0
- data/lib/restfulie/common/representation/atom/link.rb +68 -0
- data/lib/restfulie/common/representation/atom/person.rb +48 -0
- data/lib/restfulie/common/representation/atom/source.rb +59 -0
- data/lib/restfulie/common/representation/atom/tag_collection.rb +38 -0
- data/lib/restfulie/common/representation/atom/xml.rb +90 -0
- data/lib/restfulie/common/representation/atom.rb +20 -0
- data/lib/restfulie/common/representation/generic.rb +22 -0
- data/lib/restfulie/common/representation/json/base.rb +27 -0
- data/lib/restfulie/common/representation/json/keys_as_methods.rb +74 -0
- data/lib/restfulie/common/representation/json/link.rb +29 -0
- data/lib/restfulie/common/representation/json/link_collection.rb +23 -0
- data/lib/restfulie/common/representation/json.rb +13 -0
- data/lib/restfulie/common/representation/links.rb +11 -0
- data/lib/restfulie/common/representation.rb +3 -0
- data/lib/restfulie/common.rb +18 -0
- data/lib/restfulie/server/action_controller/base.rb +48 -0
- data/lib/restfulie/server/action_controller/params_parser.rb +100 -0
- data/lib/restfulie/server/action_controller/patch.rb +6 -0
- data/lib/restfulie/server/action_controller/restful_responder.rb +12 -0
- data/lib/restfulie/server/action_controller/trait/cacheable.rb +81 -0
- data/lib/restfulie/server/action_controller/trait/created.rb +17 -0
- data/lib/restfulie/server/action_controller/trait.rb +9 -0
- data/lib/restfulie/server/action_controller.rb +11 -0
- data/lib/restfulie/server/action_view/helpers.rb +50 -0
- data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +21 -0
- data/lib/restfulie/server/action_view/template_handlers.rb +30 -0
- data/lib/restfulie/server/action_view.rb +10 -0
- data/lib/restfulie/server/configuration.rb +24 -0
- data/lib/restfulie/server/controller.rb +74 -0
- data/lib/restfulie/server/core_ext/array.rb +61 -0
- data/lib/restfulie/server/core_ext.rb +1 -0
- data/lib/restfulie/server.rb +25 -0
- data/lib/restfulie/version.rb +14 -0
- data/lib/restfulie.rb +34 -0
- metadata +242 -0
data/Gemfile
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# A sample Gemfile
|
|
2
|
+
source :gemcutter
|
|
3
|
+
#
|
|
4
|
+
gem "rails", ">= 3.0.0"
|
|
5
|
+
gem "libxml-ruby"
|
|
6
|
+
|
|
7
|
+
gem "rack-conneg"
|
|
8
|
+
gem "json_pure"
|
|
9
|
+
gem "sqlite3-ruby"
|
|
10
|
+
gem "yard"
|
|
11
|
+
|
|
12
|
+
gem "respondie"
|
|
13
|
+
|
|
14
|
+
if RUBY_VERSION < "1.9"
|
|
15
|
+
gem "ruby-debug"
|
|
16
|
+
else
|
|
17
|
+
gem "ruby-debug19", :require => "ruby-debug"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
group :test do
|
|
21
|
+
gem "nokogiri"
|
|
22
|
+
gem "rspec-rails", ">= 2.0.0.beta.19"
|
|
23
|
+
gem "rcov"
|
|
24
|
+
gem "sinatra"
|
|
25
|
+
gem "state_machine"
|
|
26
|
+
gem "test-unit", "= 1.2.3"
|
|
27
|
+
gem "fakeweb"
|
|
28
|
+
end
|
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
GEM
|
|
2
|
+
remote: http://rubygems.org/
|
|
3
|
+
specs:
|
|
4
|
+
abstract (1.0.0)
|
|
5
|
+
actionmailer (3.0.0)
|
|
6
|
+
actionpack (= 3.0.0)
|
|
7
|
+
mail (~> 2.2.5)
|
|
8
|
+
actionpack (3.0.0)
|
|
9
|
+
activemodel (= 3.0.0)
|
|
10
|
+
activesupport (= 3.0.0)
|
|
11
|
+
builder (~> 2.1.2)
|
|
12
|
+
erubis (~> 2.6.6)
|
|
13
|
+
i18n (~> 0.4.1)
|
|
14
|
+
rack (~> 1.2.1)
|
|
15
|
+
rack-mount (~> 0.6.12)
|
|
16
|
+
rack-test (~> 0.5.4)
|
|
17
|
+
tzinfo (~> 0.3.23)
|
|
18
|
+
activemodel (3.0.0)
|
|
19
|
+
activesupport (= 3.0.0)
|
|
20
|
+
builder (~> 2.1.2)
|
|
21
|
+
i18n (~> 0.4.1)
|
|
22
|
+
activerecord (3.0.0)
|
|
23
|
+
activemodel (= 3.0.0)
|
|
24
|
+
activesupport (= 3.0.0)
|
|
25
|
+
arel (~> 1.0.0)
|
|
26
|
+
tzinfo (~> 0.3.23)
|
|
27
|
+
activeresource (3.0.0)
|
|
28
|
+
activemodel (= 3.0.0)
|
|
29
|
+
activesupport (= 3.0.0)
|
|
30
|
+
activesupport (3.0.0)
|
|
31
|
+
arel (1.0.1)
|
|
32
|
+
activesupport (~> 3.0.0)
|
|
33
|
+
builder (2.1.2)
|
|
34
|
+
columnize (0.3.1)
|
|
35
|
+
diff-lcs (1.1.2)
|
|
36
|
+
erubis (2.6.6)
|
|
37
|
+
abstract (>= 1.0.0)
|
|
38
|
+
fakeweb (1.2.8)
|
|
39
|
+
hoe (2.6.1)
|
|
40
|
+
rake (>= 0.8.7)
|
|
41
|
+
rubyforge (>= 2.0.4)
|
|
42
|
+
i18n (0.4.1)
|
|
43
|
+
json_pure (1.4.6)
|
|
44
|
+
libxml-ruby (1.1.4)
|
|
45
|
+
linecache (0.43)
|
|
46
|
+
mail (2.2.5)
|
|
47
|
+
activesupport (>= 2.3.6)
|
|
48
|
+
mime-types
|
|
49
|
+
treetop (>= 1.4.5)
|
|
50
|
+
mime-types (1.16)
|
|
51
|
+
nokogiri (1.4.3.1)
|
|
52
|
+
polyglot (0.3.1)
|
|
53
|
+
rack (1.2.1)
|
|
54
|
+
rack-conneg (0.1.4)
|
|
55
|
+
rack (>= 1.0)
|
|
56
|
+
rack-mount (0.6.12)
|
|
57
|
+
rack (>= 1.0.0)
|
|
58
|
+
rack-test (0.5.4)
|
|
59
|
+
rack (>= 1.0)
|
|
60
|
+
rails (3.0.0)
|
|
61
|
+
actionmailer (= 3.0.0)
|
|
62
|
+
actionpack (= 3.0.0)
|
|
63
|
+
activerecord (= 3.0.0)
|
|
64
|
+
activeresource (= 3.0.0)
|
|
65
|
+
activesupport (= 3.0.0)
|
|
66
|
+
bundler (~> 1.0.0)
|
|
67
|
+
railties (= 3.0.0)
|
|
68
|
+
railties (3.0.0)
|
|
69
|
+
actionpack (= 3.0.0)
|
|
70
|
+
activesupport (= 3.0.0)
|
|
71
|
+
rake (>= 0.8.4)
|
|
72
|
+
thor (~> 0.14.0)
|
|
73
|
+
rake (0.8.7)
|
|
74
|
+
rcov (0.9.8)
|
|
75
|
+
respondie (0.9.0)
|
|
76
|
+
rspec (2.0.0.beta.19)
|
|
77
|
+
rspec-core (= 2.0.0.beta.19)
|
|
78
|
+
rspec-expectations (= 2.0.0.beta.19)
|
|
79
|
+
rspec-mocks (= 2.0.0.beta.19)
|
|
80
|
+
rspec-core (2.0.0.beta.19)
|
|
81
|
+
rspec-expectations (2.0.0.beta.19)
|
|
82
|
+
diff-lcs (>= 1.1.2)
|
|
83
|
+
rspec-mocks (2.0.0.beta.19)
|
|
84
|
+
rspec-rails (2.0.0.beta.19)
|
|
85
|
+
rspec (= 2.0.0.beta.19)
|
|
86
|
+
webrat (>= 0.7.2.beta.1)
|
|
87
|
+
ruby-debug (0.10.3)
|
|
88
|
+
columnize (>= 0.1)
|
|
89
|
+
ruby-debug-base (~> 0.10.3.0)
|
|
90
|
+
ruby-debug-base (0.10.3)
|
|
91
|
+
linecache (>= 0.3)
|
|
92
|
+
rubyforge (2.0.4)
|
|
93
|
+
json_pure (>= 1.1.7)
|
|
94
|
+
sinatra (1.0)
|
|
95
|
+
rack (>= 1.0)
|
|
96
|
+
sqlite3-ruby (1.3.1)
|
|
97
|
+
state_machine (0.9.4)
|
|
98
|
+
test-unit (1.2.3)
|
|
99
|
+
hoe (>= 1.5.1)
|
|
100
|
+
thor (0.14.0)
|
|
101
|
+
treetop (1.4.8)
|
|
102
|
+
polyglot (>= 0.3.1)
|
|
103
|
+
tzinfo (0.3.23)
|
|
104
|
+
webrat (0.7.2.beta.1)
|
|
105
|
+
nokogiri (>= 1.2.0)
|
|
106
|
+
rack (>= 1.0)
|
|
107
|
+
rack-test (>= 0.5.3)
|
|
108
|
+
yard (0.5.8)
|
|
109
|
+
|
|
110
|
+
PLATFORMS
|
|
111
|
+
ruby
|
|
112
|
+
|
|
113
|
+
DEPENDENCIES
|
|
114
|
+
fakeweb
|
|
115
|
+
json_pure
|
|
116
|
+
libxml-ruby
|
|
117
|
+
nokogiri
|
|
118
|
+
rack-conneg
|
|
119
|
+
rails (>= 3.0.0)
|
|
120
|
+
rcov
|
|
121
|
+
respondie
|
|
122
|
+
rspec-rails (>= 2.0.0.beta.19)
|
|
123
|
+
ruby-debug
|
|
124
|
+
sinatra
|
|
125
|
+
sqlite3-ruby
|
|
126
|
+
state_machine
|
|
127
|
+
test-unit (= 1.2.3)
|
|
128
|
+
yard
|
data/LICENSE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
|
data/README.textile
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
h1. Web site
|
|
2
|
+
|
|
3
|
+
Restfulie's website can be found at "http://restfulie.caelumobjects.com":http://restfulie.caelumobjects.com
|
|
4
|
+
From there you can see some videos and read the "Restfulie from Scratch guide":http://restfulie.caelumobjects.com/caelumobjects-restful-rails.pdf.
|
|
5
|
+
|
|
6
|
+
h1. Quit pretending
|
|
7
|
+
|
|
8
|
+
CRUD through HTTP is a good step forward to using resources and becoming RESTful, another step further into it is to make use of hypermedia and semantic meaningful media types: this gem allows you to do it really fast.
|
|
9
|
+
|
|
10
|
+
You can read the "article on using the web for real":http://guilhermesilveira.wordpress.com/2009/11/03/quit-pretending-use-the-web-for-real-restfulie/ which gives an introduction to hypermedia/resources/services.
|
|
11
|
+
|
|
12
|
+
h2. Why would I use restfulie?
|
|
13
|
+
|
|
14
|
+
# Easy --> writing hypermedia and semantic meaningful media type aware clients
|
|
15
|
+
# Small -> it's not a bloated solution with a huge list of APIs
|
|
16
|
+
# HATEOAS --> clients you are unaware of will not bother if you change
|
|
17
|
+
# HATEOAS --> consumed resources will not affect your software whenever they change their flow
|
|
18
|
+
# Adaptability --> clients are able to adapt to your changes
|
|
19
|
+
|
|
20
|
+
h2. Simple server example
|
|
21
|
+
|
|
22
|
+
In the server side, all you need to do is notify inherited_resources which media types you are able to represent your resource:
|
|
23
|
+
|
|
24
|
+
<pre>
|
|
25
|
+
class OrdersController < ApplicationController
|
|
26
|
+
include Restfulie::Server::ActionController::Base
|
|
27
|
+
|
|
28
|
+
respond_to :atom, :html, :xml, :commerce, :opensearch
|
|
29
|
+
|
|
30
|
+
def index
|
|
31
|
+
respond_with @orders = Order.all
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def show
|
|
35
|
+
respond_with @order = Order.find(params[:id])
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
</pre>
|
|
40
|
+
|
|
41
|
+
That's it. Restfulie will take care of rendering a valid representation according to content negotiation. You can configure the rendering process through a custom tokamak view:
|
|
42
|
+
|
|
43
|
+
<pre>
|
|
44
|
+
collection(@orders) do |collection|
|
|
45
|
+
collection.values do |value|
|
|
46
|
+
value.id = orders_url
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
collection.link("create", orders_url)
|
|
50
|
+
collection.members
|
|
51
|
+
end
|
|
52
|
+
</pre>
|
|
53
|
+
|
|
54
|
+
You can go through an entire application by "watching this video":http://guilhermesilveira.wordpress.com or "downloading an example application contained within the restfulie ":http://github.com/caelum/restfulie/tree/master/full-examples/rest_from_scratch/
|
|
55
|
+
|
|
56
|
+
h2. Simple client example
|
|
57
|
+
|
|
58
|
+
The following example is a partial REST client implementation that navigates through some relations:
|
|
59
|
+
|
|
60
|
+
<pre>
|
|
61
|
+
order = Restfulie.at('http://localhost:3000/orders/1').get!
|
|
62
|
+
order.items.each { |item| puts items }
|
|
63
|
+
receipt = order.payment.post! { :amount => 500 }
|
|
64
|
+
puts receipt.id
|
|
65
|
+
</pre>
|
|
66
|
+
|
|
67
|
+
In order to create a full REST client, "watch this video":http://guilhermesilveira.wordpress.com.
|
|
68
|
+
|
|
69
|
+
h2. Full examples
|
|
70
|
+
|
|
71
|
+
You can view an entire application running Restfulie under *spec/integration/order/server* and *spec/integration/order/client* in this git repository.
|
|
72
|
+
|
|
73
|
+
"You can also download a full example of a REST based agent and server":http://github.com/caelum/restfulie/tree/master/full-examples/rest_from_scratch/ using Restfulie, according to the Rest Architecture Maturity Model.
|
|
74
|
+
|
|
75
|
+
h2. Documentation
|
|
76
|
+
|
|
77
|
+
Appart from the simple server and client examples provided here, you can find the following links useful:
|
|
78
|
+
|
|
79
|
+
* "RDocs":http://rdoc.info/projects/caelum/restfulie
|
|
80
|
+
* "Official website":http://restfulie.caelumobjects.com
|
|
81
|
+
* "How-tos":http://restfulie.caelumobjects.com/caelumobjects-restful-rails.pdf
|
|
82
|
+
* "Buying through Rest: Rest to the enterprise (video)":http://guilhermesilveira.wordpress.com/2010/04/13/buying-through-rest-applying-rest-to-the-enterprise/
|
|
83
|
+
|
|
84
|
+
h2. Installing
|
|
85
|
+
|
|
86
|
+
Execute:
|
|
87
|
+
|
|
88
|
+
<pre>
|
|
89
|
+
gem install restfulie
|
|
90
|
+
</pre>
|
|
91
|
+
|
|
92
|
+
For use in Rails 2.3, make sure to require the responders_backport gem in addition to the restfulie gem, either in environment.rb or in the Gemfile.
|
|
93
|
+
|
|
94
|
+
h2. Building the project
|
|
95
|
+
|
|
96
|
+
If you want to build the project and run its tests, remember to install all (client and server) required gem.
|
|
97
|
+
"Bundler":http://gembundler.com/ is required to easily manage dependencies
|
|
98
|
+
|
|
99
|
+
<pre>
|
|
100
|
+
bundle install
|
|
101
|
+
rake test:spec test:integration
|
|
102
|
+
</pre>
|
|
103
|
+
|
|
104
|
+
<script type="text/javascript">
|
|
105
|
+
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
|
106
|
+
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
|
107
|
+
</script>
|
|
108
|
+
<script type="text/javascript">
|
|
109
|
+
try {
|
|
110
|
+
var pageTracker = _gat._getTracker("UA-11770776-1");
|
|
111
|
+
pageTracker._trackPageview();
|
|
112
|
+
} catch(err) {}</script>
|
|
113
|
+
|
|
114
|
+
h2. Contributions
|
|
115
|
+
|
|
116
|
+
Restfulie was created and is maintained by "Caelum":http://caelumobjects.com, and has received enormous contributions from all those developers:
|
|
117
|
+
|
|
118
|
+
Project Leader
|
|
119
|
+
Guilherme Silveira, "Caelum":http://www.caelum.com.br
|
|
120
|
+
|
|
121
|
+
Caue Guerra, caelum
|
|
122
|
+
George Guimaraes, abril and plataforma
|
|
123
|
+
Fabio Akita
|
|
124
|
+
Diego Carrion
|
|
125
|
+
Leandro Silva
|
|
126
|
+
Gavin-John Noonan
|
|
127
|
+
Antonio Marques
|
|
128
|
+
Luis Cipriani, abril
|
|
129
|
+
Everton Ribeiro, abril
|
|
130
|
+
Paulo Ahagon, abril
|
|
131
|
+
Elomar França
|
|
132
|
+
Thomas Stefano
|
|
133
|
+
"David Paniz":"http://www.caelum.com.br"
|
|
134
|
+
"Caike Souza":"http://www.caikesouza.com/blog"
|
|
135
|
+
|
|
136
|
+
h2. Rails 2
|
|
137
|
+
|
|
138
|
+
If you want to use Restfulie with Rails2, please use any release up to 0.9.2 and its minor releases.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rubygems/specification'
|
|
3
|
+
require 'rake'
|
|
4
|
+
require 'rake/gempackagetask'
|
|
5
|
+
require 'rake/rdoctask'
|
|
6
|
+
require 'rspec'
|
|
7
|
+
require 'rspec/core'
|
|
8
|
+
require 'rspec/core/rake_task'
|
|
9
|
+
require File.expand_path('lib/restfulie')
|
|
10
|
+
|
|
11
|
+
GEM = "restfulie"
|
|
12
|
+
GEM_VERSION = Restfulie::VERSION
|
|
13
|
+
SUMMARY = "Hypermedia aware resource based library in ruby (client side) and ruby on rails (server side)."
|
|
14
|
+
AUTHOR = "Guilherme Silveira, Caue Guerra, Luis Cipriani, Everton Ribeiro, George Guimaraes, Paulo Ahagon, Several contributors"
|
|
15
|
+
EMAIL = "guilherme.silveira@caelum.com.br"
|
|
16
|
+
HOMEPAGE = "http://restfulie.caelumobjects.com"
|
|
17
|
+
|
|
18
|
+
spec = Gem::Specification.new do |s|
|
|
19
|
+
s.name = GEM
|
|
20
|
+
s.version = GEM_VERSION
|
|
21
|
+
s.platform = Gem::Platform::RUBY
|
|
22
|
+
s.summary = SUMMARY
|
|
23
|
+
s.require_paths = ['lib']
|
|
24
|
+
s.files = FileList['lib/**/*.rb', '[A-Z]*', 'lib/**/*.rng'].to_a
|
|
25
|
+
s.add_dependency("nokogiri", [">= 1.4.2"])
|
|
26
|
+
s.add_dependency("actionpack", [">= 2.3.2"])
|
|
27
|
+
s.add_dependency("activesupport", [">= 2.3.2"])
|
|
28
|
+
s.add_dependency("json_pure", [">= 1.2.4"])
|
|
29
|
+
|
|
30
|
+
s.author = AUTHOR
|
|
31
|
+
s.email = EMAIL
|
|
32
|
+
s.homepage = HOMEPAGE
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
module FakeServer
|
|
36
|
+
def self.wait_server(port=3000)
|
|
37
|
+
(1..15).each do
|
|
38
|
+
begin
|
|
39
|
+
Net::HTTP.get(URI.parse("http://localhost:#{port}/"))
|
|
40
|
+
return
|
|
41
|
+
rescue
|
|
42
|
+
sleep 1
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
raise "Waited for the server but it did not finish"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.start_sinatra
|
|
49
|
+
IO.popen("cd tests && ruby ./spec/requests/fake_server.rb") do |pipe|
|
|
50
|
+
wait_server 4567
|
|
51
|
+
yield
|
|
52
|
+
Process.kill 'INT', pipe.pid
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.run(setup, process)
|
|
57
|
+
success = IO.popen(setup) do |pipe|
|
|
58
|
+
wait_server
|
|
59
|
+
success = system "rake spec"
|
|
60
|
+
Process.kill 'INT', pipe.pid
|
|
61
|
+
success
|
|
62
|
+
end
|
|
63
|
+
if !success
|
|
64
|
+
raise "Some of the specs failed"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.start_server_and_run_spec(target_dir)
|
|
69
|
+
success = Dir.chdir(File.join(File.dirname(__FILE__), target_dir)) do
|
|
70
|
+
system('rake db:drop db:create db:migrate')
|
|
71
|
+
self.run "rails server", "rake spec"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# optionally loads a task if the required gems exist
|
|
78
|
+
def optionally
|
|
79
|
+
begin
|
|
80
|
+
yield
|
|
81
|
+
rescue LoadError; end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
namespace :test do
|
|
85
|
+
|
|
86
|
+
task :spec do
|
|
87
|
+
FakeServer.start_sinatra do
|
|
88
|
+
FakeServer.start_server_and_run_spec "tests"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
task :integration do
|
|
93
|
+
FakeServer.start_server_and_run_spec "full-examples/rest_from_scratch/part_1"
|
|
94
|
+
FakeServer.start_server_and_run_spec "full-examples/rest_from_scratch/part_2"
|
|
95
|
+
FakeServer.start_server_and_run_spec "full-examples/rest_from_scratch/part_3"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
task :sinatra do
|
|
99
|
+
FakeServer.start_sinatra do
|
|
100
|
+
puts "Press something to quit"
|
|
101
|
+
gets
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
task :all => ["spec","integration"]
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
|
110
|
+
# t.spec_files = FileList['spec_*.rb']
|
|
111
|
+
t.spec_opts = ['--colour', '--format progress']
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
|
115
|
+
pkg.gem_spec = spec
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
Rake::RDocTask.new("rdoc") do |rdoc|
|
|
119
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
optionally do
|
|
123
|
+
require 'yard'
|
|
124
|
+
YARD::Rake::YardocTask.new do |t|
|
|
125
|
+
t.files = ['lib/restfulie/**/*.rb', 'README.textile']
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
desc "Install the gem locally"
|
|
130
|
+
task :install => [:package] do
|
|
131
|
+
sh %{gem install pkg/#{GEM}-#{GEM_VERSION} -l}
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
desc "Create a gemspec file"
|
|
135
|
+
task :make_spec do
|
|
136
|
+
File.open("#{GEM}.gemspec", "w") do |file|
|
|
137
|
+
file.puts spec.to_ruby
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
desc "Builds the project"
|
|
142
|
+
task :build => ["install", "test:spec"]
|
|
143
|
+
|
|
144
|
+
desc "Default build will run specs"
|
|
145
|
+
task :default => :build
|
|
146
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Restfulie
|
|
2
|
+
module Client#:nodoc
|
|
3
|
+
module Base
|
|
4
|
+
|
|
5
|
+
def method_missing(sym, *args, &block)
|
|
6
|
+
if @base_position.respond_to?(sym)
|
|
7
|
+
@base_position.send sym, *args, &block
|
|
8
|
+
else
|
|
9
|
+
super(sym, *args, &block)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.included(base)#:nodoc
|
|
14
|
+
base.extend(self)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def uses_restfulie(configuration = Configuration.new,&block)
|
|
18
|
+
EntryPoint.configuration_for(resource_name,configuration,&block)
|
|
19
|
+
configure
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def configure
|
|
23
|
+
configuration = EntryPoint.configuration_of(resource_name)
|
|
24
|
+
raise "Undefined configuration for #{resource_name}" unless configuration
|
|
25
|
+
@base_position = Restfulie.at(configuration.entry_point)
|
|
26
|
+
configuration.representations.each do |representation_name,representation|
|
|
27
|
+
register_representation(representation_name,representation)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def resource_name
|
|
32
|
+
@resource_name ||= self.class.to_s.to_sym
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Basic cache implementation for restfulie.
|
|
2
|
+
#
|
|
3
|
+
# It uses the request headers and uri to store it in memory.
|
|
4
|
+
# This cache might not be optimal for long running clients, which should use a memcached based one.
|
|
5
|
+
# Use Restfulie::Client.cache_provider to change the provider
|
|
6
|
+
module Restfulie::Client::Cache
|
|
7
|
+
class Basic
|
|
8
|
+
|
|
9
|
+
def put(key, req, response)
|
|
10
|
+
if Restfulie::Client::Cache::Restrictions.may_cache?(response)
|
|
11
|
+
Restfulie::Common::Logger.logger.debug "caching #{key} #{response}"
|
|
12
|
+
cache_add(key, req, response)
|
|
13
|
+
end
|
|
14
|
+
response
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def get(key, request)
|
|
18
|
+
|
|
19
|
+
# debugger
|
|
20
|
+
response = cache_get(key, request)
|
|
21
|
+
return nil if response.nil?
|
|
22
|
+
|
|
23
|
+
if response.has_expired_cache?
|
|
24
|
+
remove(key)
|
|
25
|
+
else
|
|
26
|
+
Restfulie::Common::Logger.logger.debug "RETURNING cache #{key}"
|
|
27
|
+
cache_hit response
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# removes all elements from the cache
|
|
33
|
+
def clear
|
|
34
|
+
cache.clear
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# allows response enhancement when the cache was hit with it
|
|
40
|
+
def cache_hit(response)
|
|
41
|
+
response
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def cache_add(key, req, response)
|
|
45
|
+
values = (cache.read(key) || []).dup
|
|
46
|
+
values << [req, response]
|
|
47
|
+
cache.write(key, values)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def cache_get(key, req)
|
|
51
|
+
return nil unless cache.exist?(key)
|
|
52
|
+
found = cache.read(key).find do |cached|
|
|
53
|
+
old_req = cached.first
|
|
54
|
+
old_response = cached.last
|
|
55
|
+
|
|
56
|
+
headers_match = old_response.vary_headers_for(old_req) == old_response.vary_headers_for(req)
|
|
57
|
+
if headers_match && old_response.verb == req.verb
|
|
58
|
+
old_response
|
|
59
|
+
else
|
|
60
|
+
false
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
found ? found.last : nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def remove(key)
|
|
67
|
+
cache.delete(key)
|
|
68
|
+
nil
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def cache
|
|
72
|
+
Restfulie::Client.cache_store
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Fake cache that does not cache anything
|
|
2
|
+
# Use Restfulie::Client.cache_provider = Restfulie::Client::Cache::Fake.new
|
|
3
|
+
module Restfulie::Client::Cache
|
|
4
|
+
class Fake
|
|
5
|
+
def put(url, req, response)
|
|
6
|
+
response
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def get(url, req)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def clear
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|