horde_rpc 0.2.0

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/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .*.swp
4
+ .*.swo
5
+ .bundle
6
+ .config
7
+ .yardoc
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --colour
3
+ --tty
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - jruby-19mode
7
+ # - rbx-19mode
8
+ - ruby-head
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # develop
2
+
3
+ # v0.2.0
4
+ * Rename to HordeRPC
5
+
6
+ # v0.1.0
7
+ * First release!
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard 'rspec', :version => 2, :cli => '--format documentation' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec/" }
5
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2012 Mojo Lingo LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ horde_rpc
2
+ ===========
3
+
4
+ horde_rpc is a client library for accessing the Horde XML-RPC interface from Ruby.
5
+
6
+ Features
7
+ --------
8
+
9
+ * Retrieve Client records
10
+ * Record time for Clients
11
+
12
+ Requirements
13
+ ------------
14
+
15
+ * A working Horde installation
16
+
17
+ Install
18
+ -------
19
+
20
+ gem install horde_rpc
21
+
22
+ Examples
23
+ --------
24
+
25
+ ```ruby
26
+ require 'horde_rpc'
27
+ horde = HordeRPC.new 'http://horde.bar.com'
28
+ client = horde.first_client_for_company 'UberClient'
29
+ puts "Client by name 'UberClient' has ID #{client['id']}"
30
+
31
+ horde.record_time :client => client['id'],
32
+ :date => Date.today,
33
+ :hours => 3.5,
34
+ :employee => 'foo@bar.com',
35
+ :description => 'Did stuff'
36
+ :type => 1
37
+ ```
38
+
39
+ Author
40
+ ------
41
+
42
+ Original author: Ben Langfeld
43
+
44
+ Links
45
+ -----
46
+ * [Source](https://github.com/mojolingo/horde_rpc)
47
+ * [Documentation](http://rdoc.info/github/mojolingo/horde_rpc/master/frames)
48
+ * [Bug Tracker](https://github.com/mojolingo/horde_rpc/issues)
49
+
50
+ Note on Patches/Pull Requests
51
+ -----------------------------
52
+
53
+ * Fork the project.
54
+ * Make your feature addition or bug fix.
55
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
56
+ * Commit, do not mess with rakefile, version, or history.
57
+ * If you want to have your own version, that is fine but bump version in a commit by itself so I can ignore when I pull
58
+ * Send me a pull request. Bonus points for topic branches.
59
+
60
+ Copyright
61
+ ---------
62
+
63
+ Copyright (c) 2012 Mojo Lingo LLC. MIT licence (see LICENSE for details).
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'bundler/setup'
3
+
4
+ task :default => :spec
5
+
6
+ require 'rspec/core'
7
+ require 'rspec/core/rake_task'
8
+ RSpec::Core::RakeTask.new(:spec)
9
+
10
+ task :default => :spec
11
+
12
+ require 'yard'
13
+ YARD::Rake::YardocTask.new
data/horde.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "horde_rpc/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "horde_rpc"
7
+ s.version = HordeRPC::VERSION
8
+ s.authors = ["Ben Langfeld"]
9
+ s.email = ["ben@langfeld.me"]
10
+ s.homepage = "http://github.com/mojolingo/horde_rpc"
11
+ s.summary = %q{A Horde XML-RPC client library in Ruby}
12
+ s.description = %q{horde_rpc is a client library for accessing the Horde XML-RPC interface from Ruby.}
13
+
14
+ s.rubyforge_project = "horde_rpc"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency 'bundler', ["~> 1.0"]
22
+ s.add_development_dependency 'rspec', ["~> 2.8"]
23
+ s.add_development_dependency 'yard', ["~> 0.6"]
24
+ s.add_development_dependency 'rake', [">= 0"]
25
+ s.add_development_dependency 'fakeweb', [">= 0"]
26
+ s.add_development_dependency 'mocha', [">= 0"]
27
+ s.add_development_dependency 'guard-rspec'
28
+ end
data/lib/horde_rpc.rb ADDED
@@ -0,0 +1,104 @@
1
+ require 'horde_rpc/version'
2
+ require 'xmlrpc/client'
3
+
4
+ class HordeRPC
5
+ ##
6
+ # Create a new instance of the Horde connection
7
+ #
8
+ # @param [String] uri XML-RPC URI for the horde instance
9
+ # @param [String, Optional] username
10
+ # @param [String, Optional] password
11
+ #
12
+ def initialize(uri, username = nil, password = nil)
13
+ @xmlrpc_client = XMLRPC::Client.new2 uri
14
+ @xmlrpc_client.user = username
15
+ @xmlrpc_client.password = password
16
+ end
17
+
18
+ ##
19
+ # Make an RPC request against the Horde instance
20
+ #
21
+ # @param [String] method the method name to execute
22
+ # @param [Object, Optional] options
23
+ #
24
+ # @return [Object] response to the RPC
25
+ #
26
+ def request(method, *options)
27
+ @xmlrpc_client.call method, *options
28
+ end
29
+
30
+ ##
31
+ # Return data for a client by its ID
32
+ #
33
+ # @param [String] id the clients ID
34
+ #
35
+ # @return [Hash,nil] client data
36
+ #
37
+ def get_client_by_id(id)
38
+ request 'clients.getClient', id
39
+ end
40
+
41
+ ##
42
+ # Search clients by KV-pairs
43
+ #
44
+ # @param [Hash<#to_s, String>] search_params
45
+ #
46
+ # @return [Hash] map of search terms to results
47
+ #
48
+ # @example Search for clients by first name
49
+ #
50
+ # horde.search_clients :firstname => 'Bob'
51
+ # # => {'Acme' => [
52
+ # {
53
+ # "__key" => "uid=foo@bar.com",
54
+ # "__uid" => "foo@bar.com",
55
+ # "firstname" => "Joe",
56
+ # "lastname" => "Bloggs",
57
+ # "name" => "Joe Bloggs",
58
+ # "email" => "foo@bar.com",
59
+ # "homePhone" => "404 475 4840",
60
+ # "workPhone" => "404 475 4840",
61
+ # "cellPhone" => "404 475 4840",
62
+ # "homeAddress" => "Foo Lane, NY",
63
+ # "company" => "Acme",
64
+ # "id" => "uid=foo@bar.com",
65
+ # "__type" => "Object",
66
+ # "source" => "bar_clients"
67
+ # }]
68
+ # }
69
+ #
70
+ def search_clients(search_params = {})
71
+ # searchClients takes two arrays as params:
72
+ # * list of search strings
73
+ # * list of search fields
74
+ request 'clients.searchClients', search_params.values, search_params.keys.map(&:to_s)
75
+ end
76
+
77
+ ##
78
+ # Find the first client record for a particular company name
79
+ #
80
+ # @param [String] name the name of the Company
81
+ #
82
+ # @return [Hash,nil] data for the client associated with the requested company
83
+ #
84
+ def first_client_for_company(name)
85
+ results = search_clients :company => name
86
+ results[name].first
87
+ end
88
+
89
+ ##
90
+ # Record time against a project
91
+ #
92
+ # @params [Hash] options
93
+ # @option options [Date] :date the date of the billable activity
94
+ # @option options [String] :client the ID of the client to bill
95
+ # @option options [Integer] :type the type of billable activity
96
+ # @option options [Float] :hours the number of hours to bill
97
+ # @option options [String] :description a description of the billable activity
98
+ # @option options [String] :employee the username of the employee performing the billable activity
99
+ #
100
+ def record_time(options)
101
+ raise ArgumentError unless options.values_at(:date, :client, :type, :hours, :description, :employee).all?
102
+ request 'time.recordTime', options
103
+ end
104
+ end
@@ -0,0 +1,3 @@
1
+ class HordeRPC
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,280 @@
1
+ require 'spec_helper'
2
+
3
+ describe HordeRPC do
4
+ describe "sending requests" do
5
+ before do
6
+ FakeWeb.clean_registry
7
+ end
8
+
9
+ it "should hit the specified domain/port" do
10
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/'
11
+
12
+ FakeWeb.register_uri :post, "http://horde.bar.com/rpc/",
13
+ :status => ["200", "OK"],
14
+ :content_type => "text/xml",
15
+ :body => <<-RESPONSE
16
+ <?xml version="1.0"?>
17
+ <methodResponse>
18
+ <params>
19
+ <param>
20
+ <value><string>bar</string></value>
21
+ </param>
22
+ </params>
23
+ </methodResponse>
24
+ RESPONSE
25
+
26
+ horde.request 'foo'
27
+ end
28
+
29
+ it "should be formatted as XMLRPC" do
30
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/'
31
+
32
+ FakeWeb.register_uri :post, "http://horde.bar.com/rpc/",
33
+ :status => ["200", "OK"],
34
+ :content_type => "text/xml",
35
+ :body => <<-RESPONSE
36
+ <?xml version="1.0"?>
37
+ <methodResponse>
38
+ <params>
39
+ <param>
40
+ <value><string>bar</string></value>
41
+ </param>
42
+ </params>
43
+ </methodResponse>
44
+ RESPONSE
45
+
46
+ horde.request 'foo'
47
+
48
+ FakeWeb.last_request.body.should match(/<methodCall>/)
49
+ end
50
+
51
+ it "should invoke the correct method, with the correct parameters, including user/password options" do
52
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/', 'usera', 'passwordb'
53
+
54
+ FakeWeb.register_uri :post, "http://usera:passwordb@horde.bar.com/rpc/",
55
+ :status => ["200", "OK"],
56
+ :content_type => "text/xml",
57
+ :body => <<-RESPONSE
58
+ <?xml version="1.0"?>
59
+ <methodResponse>
60
+ <params>
61
+ <param>
62
+ <value><string>bar</string></value>
63
+ </param>
64
+ </params>
65
+ </methodResponse>
66
+ RESPONSE
67
+
68
+ horde.request 'foo', :foo => 'bar'
69
+
70
+ FakeWeb.last_request.body.should be == "<?xml version=\"1.0\" ?><methodCall><methodName>foo</methodName><params><param><value><struct><member><name>foo</name><value><string>bar</string></value></member></struct></value></param></params></methodCall>\n"
71
+ end
72
+
73
+ it "should be able to make a request without options" do
74
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/'
75
+
76
+ FakeWeb.register_uri :post, "http://horde.bar.com/rpc/",
77
+ :status => ["200", "OK"],
78
+ :content_type => "text/xml",
79
+ :body => <<-RESPONSE
80
+ <?xml version="1.0"?>
81
+ <methodResponse>
82
+ <params>
83
+ <param>
84
+ <value><string>bar</string></value>
85
+ </param>
86
+ </params>
87
+ </methodResponse>
88
+ RESPONSE
89
+
90
+ horde.request 'foo'
91
+
92
+ FakeWeb.last_request.body.should be == "<?xml version=\"1.0\" ?><methodCall><methodName>foo</methodName><params/></methodCall>\n"
93
+ end
94
+
95
+ it "should be able to make a request with multiple options" do
96
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/'
97
+
98
+ FakeWeb.register_uri :post, "http://horde.bar.com/rpc/",
99
+ :status => ["200", "OK"],
100
+ :content_type => "text/xml",
101
+ :body => <<-RESPONSE
102
+ <?xml version="1.0"?>
103
+ <methodResponse>
104
+ <params>
105
+ <param>
106
+ <value><string>bar</string></value>
107
+ </param>
108
+ </params>
109
+ </methodResponse>
110
+ RESPONSE
111
+
112
+ horde.request 'foo', 'bar', 'baz'
113
+
114
+ FakeWeb.last_request.body.should be == "<?xml version=\"1.0\" ?><methodCall><methodName>foo</methodName><params><param><value><string>bar</string></value></param><param><value><string>baz</string></value></param></params></methodCall>\n"
115
+ end
116
+
117
+ it "should return the returned data structure" do
118
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/'
119
+
120
+ FakeWeb.register_uri :post, "http://horde.bar.com/rpc/",
121
+ :status => ["200", "OK"],
122
+ :content_type => "text/xml",
123
+ :body => <<-RESPONSE
124
+ <?xml version="1.0"?>
125
+ <methodResponse>
126
+ <params>
127
+ <param>
128
+ <value><string>bar</string></value>
129
+ </param>
130
+ </params>
131
+ </methodResponse>
132
+ RESPONSE
133
+
134
+ horde.request('foo').should be == 'bar'
135
+ end
136
+ end
137
+
138
+ describe "fetching a client by ID" do
139
+ it "should return the fetched client data" do
140
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/'
141
+
142
+ id = "uid=foo@bar.com"
143
+
144
+ response = {
145
+ "__key" => "uid=foo@bar.com",
146
+ "__uid" => "foo@bar.com",
147
+ "firstname" => "Joe",
148
+ "lastname" => "Bloggs",
149
+ "name" => "Joe Bloggs",
150
+ "email" => "foo@bar.com",
151
+ "homePhone" => "404 475 4840",
152
+ "workPhone" => "404 475 4840",
153
+ "cellPhone" => "404 475 4840",
154
+ "homeAddress" => "Foo Lane, NY",
155
+ "company" => "Acme",
156
+ "id" => "uid=foo@bar.com",
157
+ "__type" => "Object",
158
+ "source" => "bar_clients"
159
+ }
160
+
161
+ horde.expects(:request).once.with('clients.getClient', id).returns response
162
+
163
+ client = horde.get_client_by_id id
164
+ client.should be response
165
+ end
166
+ end
167
+
168
+ describe "searching for clients" do
169
+ it "should return a set of client data" do
170
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/'
171
+
172
+ response = {'Acme' => [
173
+ {
174
+ "__key" => "uid=foo@bar.com",
175
+ "__uid" => "foo@bar.com",
176
+ "firstname" => "Joe",
177
+ "lastname" => "Bloggs",
178
+ "name" => "Joe Bloggs",
179
+ "email" => "foo@bar.com",
180
+ "homePhone" => "404 475 4840",
181
+ "workPhone" => "404 475 4840",
182
+ "cellPhone" => "404 475 4840",
183
+ "homeAddress" => "Foo Lane, NY",
184
+ "company" => "Acme",
185
+ "id" => "uid=foo@bar.com",
186
+ "__type" => "Object",
187
+ "source" => "bar_clients"
188
+ }]
189
+ }
190
+
191
+ horde.expects(:request).once.with('clients.searchClients', ['Acme'], ['company']).returns response
192
+
193
+ client = horde.search_clients :company => 'Acme'
194
+ client.should be response
195
+ end
196
+ end
197
+
198
+ describe "finding the first client by company name" do
199
+ it "should return the relevant client data" do
200
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/'
201
+
202
+ client_data = {
203
+ "__key" => "uid=foo@bar.com",
204
+ "__uid" => "foo@bar.com",
205
+ "firstname" => "Joe",
206
+ "lastname" => "Bloggs",
207
+ "name" => "Joe Bloggs",
208
+ "email" => "foo@bar.com",
209
+ "homePhone" => "404 475 4840",
210
+ "workPhone" => "404 475 4840",
211
+ "cellPhone" => "404 475 4840",
212
+ "homeAddress" => "Foo Lane, NY",
213
+ "company" => "Acme",
214
+ "id" => "uid=foo@bar.com",
215
+ "__type" => "Object",
216
+ "source" => "bar_clients"
217
+ }
218
+ response = {'Acme' => [client_data]}
219
+
220
+ horde.expects(:request).once.with('clients.searchClients', ['Acme'], ['company']).returns response
221
+
222
+ client = horde.first_client_for_company 'Acme'
223
+ client.should be == client_data
224
+ end
225
+
226
+ context "if no matches are found" do
227
+ it "should return nil" do
228
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/'
229
+
230
+ response = {'Acme' => []}
231
+
232
+ horde.expects(:request).once.with('clients.searchClients', ['Acme'], ['company']).returns response
233
+
234
+ client = horde.first_client_for_company 'Acme'
235
+ client.should be nil
236
+ end
237
+ end
238
+ end
239
+
240
+ describe "recording time" do
241
+ it "should record time given the requested parameters" do
242
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/'
243
+
244
+ options = {
245
+ :date => Date.today,
246
+ :client => 'bob@acme.com',
247
+ :type => 1,
248
+ :hours => 1.2,
249
+ :description => 'Did stuff',
250
+ :employee => 'foo@bar.com'
251
+ }
252
+
253
+ horde.expects(:request).once.with('time.recordTime', options)
254
+
255
+ horde.record_time options
256
+ end
257
+
258
+ %w{date client type hours description employee}.each do |required_option|
259
+ context "without specifying #{required_option}" do
260
+ it "should raise ArgumentError" do
261
+ horde = HordeRPC.new 'http://horde.bar.com/rpc/'
262
+
263
+ options = {
264
+ :date => Date.today,
265
+ :client => 'bob@acme.com',
266
+ :type => 1,
267
+ :hours => 1.2,
268
+ :description => 'Did stuff',
269
+ :employee => 'foo@bar.com'
270
+ }
271
+ options.merge! required_option.to_sym => nil
272
+
273
+ horde.expects(:request).never
274
+
275
+ lambda { horde.record_time options }.should raise_error(ArgumentError)
276
+ end
277
+ end
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,13 @@
1
+ require 'horde_rpc'
2
+ require 'mocha'
3
+ require 'fakeweb'
4
+
5
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
6
+
7
+ RSpec.configure do |config|
8
+ config.mock_with :mocha
9
+ config.filter_run :focus => true
10
+ config.run_all_when_everything_filtered = true
11
+ end
12
+
13
+ FakeWeb.allow_net_connect = false
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: horde_rpc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ben Langfeld
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '2.8'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '2.8'
46
+ - !ruby/object:Gem::Dependency
47
+ name: yard
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '0.6'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0.6'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: fakeweb
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: mocha
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: guard-rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: horde_rpc is a client library for accessing the Horde XML-RPC interface
127
+ from Ruby.
128
+ email:
129
+ - ben@langfeld.me
130
+ executables: []
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - .gitignore
135
+ - .rspec
136
+ - .travis.yml
137
+ - CHANGELOG.md
138
+ - Gemfile
139
+ - Guardfile
140
+ - LICENSE
141
+ - README.md
142
+ - Rakefile
143
+ - horde.gemspec
144
+ - lib/horde_rpc.rb
145
+ - lib/horde_rpc/version.rb
146
+ - spec/horde_rpc_spec.rb
147
+ - spec/spec_helper.rb
148
+ homepage: http://github.com/mojolingo/horde_rpc
149
+ licenses: []
150
+ post_install_message:
151
+ rdoc_options: []
152
+ require_paths:
153
+ - lib
154
+ required_ruby_version: !ruby/object:Gem::Requirement
155
+ none: false
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ segments:
161
+ - 0
162
+ hash: 4324098499712079725
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ none: false
165
+ requirements:
166
+ - - ! '>='
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ segments:
170
+ - 0
171
+ hash: 4324098499712079725
172
+ requirements: []
173
+ rubyforge_project: horde_rpc
174
+ rubygems_version: 1.8.21
175
+ signing_key:
176
+ specification_version: 3
177
+ summary: A Horde XML-RPC client library in Ruby
178
+ test_files:
179
+ - spec/horde_rpc_spec.rb
180
+ - spec/spec_helper.rb
181
+ has_rdoc: