jeffrafter-resource_party 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Jeff Rafter
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 ADDED
@@ -0,0 +1,150 @@
1
+ resource_party
2
+ ==============
3
+
4
+ ResourceParty is a simple wrapper around HTTParty that allows you to do basic
5
+ operations with a restful resource (presumably implemented in rails). It
6
+ assumes a scaffolded resource in the following form:
7
+
8
+ class FoosController < ApplicationController
9
+ # GET /foo
10
+ # GET /foo.xml
11
+ def index
12
+ @foo = Foo.find(:all)
13
+ respond_to do |format|
14
+ format.html # index.rhtml
15
+ format.xml { render :xml => @foo.to_xml }
16
+ end
17
+ end
18
+
19
+ # GET /foo/1
20
+ # GET /foo/1.xml
21
+ def show
22
+ @foo = Foo.find(params[:id])
23
+ respond_to do |format|
24
+ format.html # show.rhtml
25
+ format.xml { render :xml => @foo.to_xml }
26
+ end
27
+ rescue ActiveRecord::RecordNotFound => rnf
28
+ render :text => rnf.message, :status => :not_found
29
+ rescue Exception => e
30
+ render :text => e.message, :status => :error
31
+ end
32
+
33
+ # GET /foo/new
34
+ def new
35
+ @foo = Foo.new
36
+ respond_to do |format|
37
+ format.html # new.rhtml
38
+ format.xml { render :xml => @foo.to_xml }
39
+ end
40
+ end
41
+
42
+ # GET /foo/1;edit
43
+ def edit
44
+ @foo = Foo.find(params[:id])
45
+ end
46
+
47
+ # POST /foo
48
+ # POST /foo.xml
49
+ def create
50
+ @foo = Foo.new(params[:foo])
51
+ respond_to do |format|
52
+ if @foo.save
53
+ flash[:notice] = 'Foo type was successfully created.'
54
+ format.html { redirect_to foo_url(@foo) }
55
+ format.xml { render :xml => @foo.to_xml }
56
+ else
57
+ format.html { render :action => "new" }
58
+ format.xml { render :xml => @foo.errors.to_xml }
59
+ end
60
+ end
61
+ rescue Exception => e
62
+ render :text => e.message, :status => :error
63
+ end
64
+
65
+ # PUT /foo/1
66
+ # PUT /foo/1.xml
67
+ def update
68
+ @foo = Foo.find(params[:id])
69
+ respond_to do |format|
70
+ if @foo.update_attributes(params[:foo])
71
+ flash[:notice] = 'Foo type was successfully updated.'
72
+ format.html { redirect_to foo_url(@foo) }
73
+ format.xml { render :xml => @foo.to_xml }
74
+ else
75
+ format.html { render :action => "edit" }
76
+ format.xml { render :xml => @foo.errors.to_xml }
77
+ end
78
+ end
79
+ rescue ActiveRecord::RecordNotFound => rnf
80
+ render :text => rnf.message, :status => :not_found
81
+ rescue Exception => e
82
+ render :text => e.message, :status => :error
83
+ end
84
+
85
+ # DELETE /foo/1
86
+ # DELETE /foo/1.xml
87
+ def destroy
88
+ @foo = Foo.find(params[:id])
89
+ @foo.destroy
90
+ respond_to do |format|
91
+ format.html { redirect_to foo_url }
92
+ format.xml { head :ok }
93
+ end
94
+ rescue ActiveRecord::RecordNotFound => rnf
95
+ render :text => rnf.message, :status => :not_found
96
+ rescue Exception => e
97
+ render :text => e.message, :status => :error
98
+ end
99
+ end
100
+
101
+ Returning head :ok for create and update is permissable (though I find returning
102
+ the actual resource is potentially more helpful as there may have been changes
103
+ made in the model before_create or before_update).
104
+
105
+ Notice that there is explicit exception handling which improves the
106
+ communication. This will hopefully be expanded to include better validation
107
+ error handling.
108
+
109
+ To make your models join the party:
110
+
111
+ require 'resource_party'
112
+
113
+ class Foo < ResourceParty::Base
114
+ base_uri 'http://localhost:3000'
115
+ route_for 'foos'
116
+ resource_for 'foo'
117
+ end
118
+
119
+ +route_for+ will be used to generate the path, i.e. "/{route_for}/4.xml"
120
+ +resource_for+ will be used when building params (like form_for)
121
+
122
+ I know both of these are automatic if you are already using active_support by
123
+ using class.to_s.downcase.singularize and friends. But hey.
124
+
125
+ Once this is built you should be able to
126
+
127
+ Foo.all
128
+ => returns an array of Foos (from the index)
129
+
130
+ Foo.find(id)
131
+ => returns a foo or a ResourceParty::RecordNotFound
132
+
133
+ Foo.destroy(id) or foo.destroy
134
+ => Deletes the foo, returns true if successful
135
+
136
+ Foo.update(id, {:my_field => "this is the change!"}) or foo.update(...)
137
+ => Updates the foo with the params, returns true if the controller
138
+ => responds with :head, otherwise returns the foo
139
+
140
+ Foo.create({:my_field => "this is the new stuff"})
141
+ => Creates the foo with the params, returns true if the controller
142
+ => responds with :head, otherwise returns the foo
143
+
144
+ Foo.new
145
+ => Fetches a blank foo so that defaulted params are possible
146
+
147
+ COPYRIGHT
148
+ =========
149
+
150
+ Copyright (c) 2008 Jeff Rafter. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |s|
8
+ s.name = "resource_party"
9
+ s.summary = "Simplified resource interaction using HTTParty"
10
+ s.email = "jeff@baobabhealth.org"
11
+ s.homepage = "http://github.com/jeffrafter/resource_party"
12
+ s.description = "Simple wrapper for HTTParty for basic operations with a restful resource"
13
+ s.authors = ["Jeff Rafter"]
14
+ s.add_dependency "jnunemaker-httparty"
15
+ s.files = FileList["[A-Z]*", "{lib,test}/**/*"]
16
+ end
17
+ rescue LoadError
18
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
19
+ end
20
+
21
+ Rake::TestTask.new do |t|
22
+ t.libs << 'lib'
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = false
25
+ end
26
+
27
+ Rake::RDocTask.new do |rdoc|
28
+ rdoc.rdoc_dir = 'rdoc'
29
+ rdoc.title = 'resource_party'
30
+ rdoc.options << '--line-numbers' << '--inline-source'
31
+ rdoc.rdoc_files.include('README*')
32
+ rdoc.rdoc_files.include('lib/**/*.rb')
33
+ end
34
+
35
+ task :default => :test
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 1
3
+ :patch: 1
4
+ :major: 0
@@ -0,0 +1,99 @@
1
+ require 'httparty'
2
+
3
+ module ResourceParty
4
+ class ServerError < RuntimeError; end
5
+ class RecordNotFound < RuntimeError; end
6
+ class Base
7
+ include HTTParty
8
+
9
+ attr_accessor :attributes
10
+
11
+ def self.route_for(val)
12
+ class_eval("def self.route; '#{val}'; end")
13
+ end
14
+
15
+ def self.resource_for(val)
16
+ class_eval("def self.resource; '#{val}'; end")
17
+ end
18
+
19
+ def initialize(params = {}, query = {}, no_defaults = false)
20
+ return self if no_defaults
21
+ response = self.class.get("/#{self.route}/new.xml")
22
+ raise ServerError.new(response.body) if response.code != "200"
23
+ hash = Hash.from_xml(response.body).values.first
24
+ hash.merge! params
25
+ self.class.from_xml hash, self
26
+ end
27
+
28
+ def self.find(id, query = {})
29
+ response = self.get("/#{self.route}/#{id}.xml", :query => query)
30
+ raise RecordNotFound.new(response.body) if response.code == "404"
31
+ raise ServerError.new(response.body) if response.code != "200"
32
+ hash = Hash.from_xml(response.body).values.first
33
+ self.from_xml hash
34
+ end
35
+
36
+ def self.create(params = {}, query = {})
37
+ response = self.post("/#{self.route}.xml", :body => body_for(params), :query => query)
38
+ raise ServerError.new(response.body) if response.code != "200"
39
+ hash = Hash.from_xml(response.body).values.first
40
+ self.from_xml hash
41
+ end
42
+
43
+ def self.update(id, params = {}, query = {})
44
+ response = self.put("/#{self.route}/#{id}.xml", :body => body_for(params), :query => query)
45
+ raise RecordNotFound.new(response.body) if response.code == "404"
46
+ raise ServerError.new(response.body) if response.code != "200"
47
+ hash = Hash.from_xml(response.body).values.first
48
+ self.from_xml hash
49
+ end
50
+
51
+ def update(params = {}, query = {})
52
+ self.class.update(self.id, params, query)
53
+ end
54
+
55
+ def self.destroy(id, query = {})
56
+ response = self.delete("/#{self.route}/#{id}.xml", :query => query, :format => :text)
57
+ raise RecordNotFound.new(response.body) if response.code == "404"
58
+ raise ServerError.new(response.body) if response.code != "200"
59
+ true
60
+ end
61
+
62
+ def destroy(query = {})
63
+ self.class.destroy(self.id, query)
64
+ end
65
+
66
+ def self.all(query = {})
67
+ response = self.get("/#{self.route}.xml", :query => query)
68
+ raise ServerError.new(response.body) if response.code != "200"
69
+ items = response.values.first
70
+ items.map{|hash| self.from_xml hash }
71
+ end
72
+
73
+ private
74
+
75
+ def self.body_for(params)
76
+ body = {}
77
+ params.each{|n,v| body["#{self.resource}[#{n}]"] = v }
78
+ body.to_query
79
+ end
80
+
81
+ def self.from_xml(params, obj = nil)
82
+ obj ||= self.new({}, {}, true)
83
+ obj.attributes = params
84
+ mod = Module.new do
85
+ obj.attributes.keys.each do |k|
86
+ define_method(k) do
87
+ return self.attributes[k]
88
+ end
89
+
90
+ define_method("#{k}=") do |val|
91
+ self.attributes[k] = val
92
+ end
93
+ end
94
+ end
95
+ obj.send(:extend, mod)
96
+ obj
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ResourcePartyTest < Test::Unit::TestCase
4
+ should "be usable by the masses" do
5
+ assert_not_nil ResourceParty::Base
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+
6
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'resource_party')
7
+
8
+ class Test::Unit::TestCase
9
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jeffrafter-resource_party
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Rafter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-10 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: jnunemaker-httparty
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ description: Simple wrapper for HTTParty for basic operations with a restful resource
25
+ email: jeff@baobabhealth.org
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - LICENSE
34
+ - Rakefile
35
+ - README
36
+ - VERSION.yml
37
+ - lib/resource_party.rb
38
+ - test/resource_party_test.rb
39
+ - test/test_helper.rb
40
+ has_rdoc: false
41
+ homepage: http://github.com/jeffrafter/resource_party
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.2.0
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: Simplified resource interaction using HTTParty
66
+ test_files: []
67
+