jeffrafter-resource_party 0.1.1

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/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
+