savon_model 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://gems.blau.de"
2
+ source :rubygems
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,39 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ savon_model (0.1.0)
5
+
6
+ GEM
7
+ remote: http://gems.blau.de/
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ builder (2.1.2)
11
+ crack (0.1.8)
12
+ diff-lcs (1.1.2)
13
+ httpi (0.6.0)
14
+ mocha (0.9.8)
15
+ rake
16
+ rake (0.8.7)
17
+ rspec (2.0.0)
18
+ rspec-core (= 2.0.0)
19
+ rspec-expectations (= 2.0.0)
20
+ rspec-mocks (= 2.0.0)
21
+ rspec-core (2.0.0)
22
+ rspec-expectations (2.0.0)
23
+ diff-lcs (>= 1.1.2)
24
+ rspec-mocks (2.0.0)
25
+ rspec-core (= 2.0.0)
26
+ rspec-expectations (= 2.0.0)
27
+ savon (0.8.0.alpha.1)
28
+ builder (~> 2.1.2)
29
+ crack (~> 0.1.8)
30
+ httpi (>= 0.6.0)
31
+
32
+ PLATFORMS
33
+ ruby
34
+
35
+ DEPENDENCIES
36
+ mocha (~> 0.9.8)
37
+ rspec (~> 2.0.0)
38
+ savon (~> 0.8.0.alpha.1)
39
+ savon_model!
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Daniel Harrington
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.md ADDED
@@ -0,0 +1,62 @@
1
+ Savon::Model
2
+ ============
3
+
4
+ Model for SOAP service oriented applications.
5
+
6
+ [Bugs](http://github.com/rubiii/savon_model/issues) | [Docs](http://rubydoc.info/gems/savon_model/frames)
7
+
8
+ Installation
9
+ ------------
10
+
11
+ The gem is available through [Rubygems](http://rubygems.org/gems/savon_model) and can be installed via:
12
+
13
+ $ gem install savon_model
14
+
15
+ Getting started
16
+ ---------------
17
+
18
+ class User
19
+ include Savon::Model
20
+
21
+ client do [1]
22
+ http.headers["Pragma"] = "no-cache"
23
+ end
24
+
25
+ endpoint "http://example.com/users" [2]
26
+ namespace "http://v1.example.com/users" [3]
27
+
28
+ actions :get_user, :get_all_users [4]
29
+
30
+ def self.all
31
+ get_all_users.to_array [5]
32
+ end
33
+
34
+ def self.find(id)
35
+ get_user(:id => id).to_hash [6]
36
+ end
37
+
38
+ def self.delete(id)
39
+ client.request(:delete_user) do [7]
40
+ soap.body = { :id => 1 }
41
+ end.to_hash
42
+ end
43
+ end
44
+
45
+ 1. You can call the `client` method with a block of settings to be passed to `Savon::Client.new`.
46
+ The `client` method memoizes a `Savon::Client` instance, so you need to call this method before
47
+ it gets called by any other method.
48
+
49
+ 2. Sets the SOAP endpoint.
50
+
51
+ 3. Sets the SOAP namespace.
52
+
53
+ 4. Specifies the SOAP actions provided by the service. This method dynamically creates both class
54
+ and instance methods named after the arguments. These methods accept an optional SOAP body Hash
55
+ or XML String to be passed to the `Savon::Client` instance.
56
+
57
+ 5. `User.all` calls the `get_all_users` SOAP action and returns a `Savon::Response`.
58
+
59
+ 6. `User.find` calls the `get_user` SOAP action with a SOAP body Hash and returns a `Savon::Response`.
60
+
61
+ 7. This is an example of what happens "behind the scenes" on [6]. You can always use the `client`
62
+ method to directly access and use the `Savon::Client` instance.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ require "rake"
2
+
3
+ begin
4
+ require "yard"
5
+
6
+ YARD::Rake::YardocTask.new do |t|
7
+ t.files = ["README.md", "lib/**/*.rb"]
8
+ end
9
+ rescue LoadError
10
+ desc message = %{"gem install yard" to generate documentation}
11
+ task("yard") { abort message }
12
+ end
13
+
14
+ begin
15
+ require "metric_fu"
16
+
17
+ MetricFu::Configuration.run do |c|
18
+ c.metrics = [:churn, :flog, :flay, :reek, :roodi, :saikuro] # :rcov seems to be broken
19
+ c.graphs = [:flog, :flay, :reek, :roodi]
20
+ c.flay = { :dirs_to_flay => ["lib"], :minimum_score => 20 }
21
+ c.rcov[:rcov_opts] << "-Ilib -Ispec"
22
+ end
23
+ rescue LoadError
24
+ desc message = %{"gem install metric_fu" to generate metrics}
25
+ task("metrics:all") { abort message }
26
+ end
27
+
28
+ begin
29
+ require "rspec/core/rake_task"
30
+
31
+ RSpec::Core::RakeTask.new do |t|
32
+ t.rspec_opts = %w(-fd -c)
33
+ end
34
+ rescue LoadError
35
+ task :spec do
36
+ abort "Run 'gem install rspec' to be able to run specs"
37
+ end
38
+ end
39
+
40
+ task :default => :spec
@@ -0,0 +1 @@
1
+ Autotest.add_discovery { "rspec2" }
@@ -0,0 +1,41 @@
1
+ require "savon"
2
+ require "savon/model"
3
+
4
+ module Savon
5
+ module SOAP
6
+ class Response
7
+
8
+ # Returns the +original_hash+
9
+ def new_hash
10
+ @new_hash ||= response_pattern original_hash
11
+ end
12
+
13
+ alias_method :original_hash, :to_hash
14
+ alias_method :to_hash, :new_hash
15
+
16
+ def to_array
17
+ @array ||= begin
18
+ array = to_hash.kind_of?(Array) ? to_hash : [to_hash]
19
+ array.compact
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def response_pattern(hash)
26
+ return hash if Model.response_pattern.blank?
27
+
28
+ Model.response_pattern.inject(hash) do |memo, pattern|
29
+ key = case pattern
30
+ when Regexp then memo.keys.find { |key| key.to_s =~ pattern }
31
+ else memo.keys.find { |key| key.to_s == pattern.to_s }
32
+ end
33
+
34
+ return unless key
35
+ memo[key]
36
+ end
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,65 @@
1
+ require "savon"
2
+ require "savon/ext/response"
3
+
4
+ module Savon
5
+ module Model
6
+
7
+ VERSION = "0.1.0"
8
+
9
+ class << self
10
+
11
+ def response_pattern
12
+ @response_pattern ||= []
13
+ end
14
+
15
+ attr_writer :response_pattern
16
+
17
+ end
18
+
19
+ module ClassMethods
20
+
21
+ def client(&block)
22
+ @client ||= Savon::Client.new &block
23
+ end
24
+
25
+ def endpoint(uri)
26
+ client.wsdl.endpoint = uri
27
+ end
28
+
29
+ def namespace(uri)
30
+ client.wsdl.namespace = uri
31
+ end
32
+
33
+ def actions(*args)
34
+ args.each do |arg|
35
+ define_class_action arg
36
+ define_instance_action arg
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def define_class_action(action)
43
+ self.class.send :define_method, action do |body|
44
+ client.request :wsdl, action, :body => body
45
+ end
46
+ end
47
+
48
+ def define_instance_action(action)
49
+ define_method action do |body|
50
+ self.class.send action, body
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ def self.included(base)
57
+ base.extend ClassMethods
58
+ end
59
+
60
+ def client
61
+ self.class.client
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1 @@
1
+ require "savon/model"
@@ -0,0 +1,24 @@
1
+ lib = File.expand_path("../lib/", __FILE__)
2
+ $:.unshift lib unless $:.include?(lib)
3
+
4
+ require "savon_model"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "savon_model"
8
+ s.version = Savon::Model::VERSION
9
+ s.authors = "Daniel Harrington"
10
+ s.email = "me@rubiii.com"
11
+ s.homepage = "http://github.com/rubiii/#{s.name}"
12
+ s.summary = "SOAP model"
13
+ s.description = "Model for SOAP service oriented applications."
14
+
15
+ s.rubyforge_project = s.name
16
+
17
+ s.add_development_dependency "savon", "~> 0.8.0.alpha.1"
18
+
19
+ s.add_development_dependency "rspec", "~> 2.0.0"
20
+ s.add_development_dependency "mocha", "~> 0.9.8"
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.require_path = "lib"
24
+ end
@@ -0,0 +1,14 @@
1
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2
+ <soap:Body>
3
+ <ns2:authenticateResponse xmlns:ns2="http://v1_0.ws.user.example.com">
4
+ <return>
5
+ <authenticationValue>
6
+ <token>a68d1d6379b62ff339a0e0c69ed4d9cf</token>
7
+ <tokenHash>AAAJxA;cIedoT;mY10ExZwG6JuKgp2OYKxow==</tokenHash>
8
+ <client>radclient</client>
9
+ </authenticationValue>
10
+ <success>true</success>
11
+ </return>
12
+ </ns2:authenticateResponse>
13
+ </soap:Body>
14
+ </soap:Envelope>
@@ -0,0 +1,18 @@
1
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2
+ <soap:Body>
3
+ <ns2:getAllUsersResponse xmlns:ns2="http://v1_0.ws.user.example.com">
4
+ <return>
5
+ <id>1</id>
6
+ <name>Thilko</name>
7
+ </return>
8
+ <return>
9
+ <id>2</id>
10
+ <name>Peter</name>
11
+ </return>
12
+ <return>
13
+ <id>3</id>
14
+ <name>Alex</name>
15
+ </return>
16
+ </ns2:getAllUsersResponse>
17
+ </soap:Body>
18
+ </soap:Envelope>
@@ -0,0 +1,76 @@
1
+ require "spec_helper"
2
+ require "savon/ext/response"
3
+
4
+ describe Savon::SOAP::Response do
5
+ let(:response) { Savon::SOAP::Response.new http_response(:authentication) }
6
+ let(:users_response) { Savon::SOAP::Response.new http_response(:users) }
7
+
8
+ describe "#original_hash" do
9
+ it "should return the original Hash" do
10
+ response.original_hash[:authenticate_response].should be_a(Hash)
11
+ end
12
+ end
13
+
14
+ describe "#to_hash" do
15
+ it "should memoize the result" do
16
+ response.to_hash.should equal(response.to_hash)
17
+ end
18
+
19
+ context "without response pattern" do
20
+ it "should return the original Hash" do
21
+ response.to_hash[:authenticate_response].should be_a(Hash)
22
+ end
23
+ end
24
+
25
+ context "with response pattern" do
26
+ around do |example|
27
+ Savon::Model.response_pattern = [/.+_response/, :return]
28
+ example.run
29
+ Savon::Model.response_pattern = nil
30
+ end
31
+
32
+ it "should apply the response pattern" do
33
+ response.to_hash[:success].should be_true
34
+ end
35
+ end
36
+
37
+ context "with unmatched response pattern" do
38
+ around do |example|
39
+ Savon::Model.response_pattern = [:unmatched, :pattern]
40
+ example.run
41
+ Savon::Model.response_pattern = nil
42
+ end
43
+
44
+ it "should apply the response pattern" do
45
+ response.to_hash.should be_nil
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "#to_array" do
51
+ around do |example|
52
+ Savon::Model.response_pattern = [/.+_response/, :return]
53
+ example.run
54
+ Savon::Model.response_pattern = nil
55
+ end
56
+
57
+ it "should return an Array for a single response element" do
58
+ response.to_array.should be_an(Array)
59
+ response.to_array.first[:success].should be_true
60
+ end
61
+
62
+ it "should memoize the result" do
63
+ response.to_array.should equal(response.to_array)
64
+ end
65
+
66
+ it "should return an Array for multiple response element" do
67
+ users_response.to_array.should be_an(Array)
68
+ users_response.to_array.should have(3).items
69
+ end
70
+ end
71
+
72
+ def http_response(fixture)
73
+ HTTPI::Response.new 200, {}, File.read("spec/fixtures/#{fixture}.xml")
74
+ end
75
+
76
+ end
@@ -0,0 +1,63 @@
1
+ require "spec_helper"
2
+ require "savon/model"
3
+
4
+ describe Savon::Model do
5
+ let :model do
6
+ Class.new { include Savon::Model }
7
+ end
8
+
9
+ describe ".client" do
10
+ it "should should pass a given block to a new Savon::Client"
11
+
12
+ it "should memoize the Savon::Client" do
13
+ model.client.should equal(model.client)
14
+ end
15
+ end
16
+
17
+ describe ".endpoint" do
18
+ it "should set the SOAP endpoint" do
19
+ model.endpoint "http://example.com"
20
+ model.client.wsdl.endpoint.should == "http://example.com"
21
+ end
22
+ end
23
+
24
+ describe ".namespace" do
25
+ it "should set the target namespace" do
26
+ model.namespace "http://v1.example.com"
27
+ model.client.wsdl.namespace.should == "http://v1.example.com"
28
+ end
29
+ end
30
+
31
+ describe ".actions" do
32
+ before(:all) { model.actions :get_user, :get_all_users }
33
+
34
+ it "should define class methods each action" do
35
+ model.should respond_to(:get_user, :get_all_users)
36
+ end
37
+
38
+ it "should define instance methods each action" do
39
+ model.new.should respond_to(:get_user, :get_all_users)
40
+ end
41
+
42
+ context "(class-level)" do
43
+ it "should execute SOAP requests with a given body" do
44
+ model.client.expects(:request).with(:wsdl, :get_user, :body => { :id => 1 })
45
+ model.get_user :id => 1
46
+ end
47
+ end
48
+
49
+ context "(instance-level)" do
50
+ it "should delegate to the corresponding class method" do
51
+ model.expects(:get_all_users).with(:active => true)
52
+ model.new.get_all_users :active => true
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "#client" do
58
+ it "should return the class-level Savon::Client" do
59
+ model.new.client.should == model.client
60
+ end
61
+ end
62
+
63
+ end
@@ -0,0 +1,6 @@
1
+ require "rspec"
2
+ require "mocha"
3
+
4
+ RSpec.configure do |config|
5
+ config.mock_with :mocha
6
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: savon_model
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Daniel Harrington
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-20 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: savon
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: -3702664226
30
+ segments:
31
+ - 0
32
+ - 8
33
+ - 0
34
+ - alpha
35
+ - 1
36
+ version: 0.8.0.alpha.1
37
+ type: :development
38
+ version_requirements: *id001
39
+ - !ruby/object:Gem::Dependency
40
+ name: rspec
41
+ prerelease: false
42
+ requirement: &id002 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ hash: 15
48
+ segments:
49
+ - 2
50
+ - 0
51
+ - 0
52
+ version: 2.0.0
53
+ type: :development
54
+ version_requirements: *id002
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ prerelease: false
58
+ requirement: &id003 !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ~>
62
+ - !ruby/object:Gem::Version
63
+ hash: 43
64
+ segments:
65
+ - 0
66
+ - 9
67
+ - 8
68
+ version: 0.9.8
69
+ type: :development
70
+ version_requirements: *id003
71
+ description: Model for SOAP service oriented applications.
72
+ email: me@rubiii.com
73
+ executables: []
74
+
75
+ extensions: []
76
+
77
+ extra_rdoc_files: []
78
+
79
+ files:
80
+ - Gemfile
81
+ - Gemfile.lock
82
+ - LICENSE
83
+ - README.md
84
+ - Rakefile
85
+ - autotest/discover.rb
86
+ - lib/savon/ext/response.rb
87
+ - lib/savon/model.rb
88
+ - lib/savon_model.rb
89
+ - savon_model.gemspec
90
+ - spec/fixtures/authentication.xml
91
+ - spec/fixtures/users.xml
92
+ - spec/savon/ext/response_spec.rb
93
+ - spec/savon/model_spec.rb
94
+ - spec/spec_helper.rb
95
+ has_rdoc: true
96
+ homepage: http://github.com/rubiii/savon_model
97
+ licenses: []
98
+
99
+ post_install_message:
100
+ rdoc_options: []
101
+
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ hash: 3
110
+ segments:
111
+ - 0
112
+ version: "0"
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ hash: 3
119
+ segments:
120
+ - 0
121
+ version: "0"
122
+ requirements: []
123
+
124
+ rubyforge_project: savon_model
125
+ rubygems_version: 1.3.7
126
+ signing_key:
127
+ specification_version: 3
128
+ summary: SOAP model
129
+ test_files: []
130
+