wuparty 1.3.0 → 1.4.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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +7 -0
  3. data/lib/wuparty.rb +56 -274
  4. data/test/wuparty_test.rb +17 -12
  5. metadata +7 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '09a964df85dabf867074ea0b08ab6513a04d878c6e9dd6c1e8d0f35b40a0dd93'
4
- data.tar.gz: ab0a9f3fbc5c15d6a0bc8303be4e6c9f995d72f253d8dc8e5bf400b590dd8645
3
+ metadata.gz: 234b301e801407f22b72b131811d66f55a01a181caf57abbd38d8b910e5ba46b
4
+ data.tar.gz: 3ad467ad15196ba565133fd4c0aa229838e73f8fb1e682b1f3267837ff46bb06
5
5
  SHA512:
6
- metadata.gz: 6943a1829998b90acfe6c3f8b6de7f64942adc05b164f8ef82d6a251604d326c9b98f41883917f5feaf051253a892c68a2f0e67cbed1dacce9dc2566c1ef5921
7
- data.tar.gz: 5e13f8e94e47ae54dddc8e3e3c35e081d47c2be2bbc093bf7b6e9166d29e7556f33fe561bc488f197972299e1269b6f77bcf9ca9f41c2a04528689aa96561b09
6
+ metadata.gz: c51e66a8b3e8a39659932763c153633590eb339317bf552cf96103f1a7067155a5b6f09cb6061ca30b1099062069ccde5e2ea2156ed32ea4be0f6202f3ee58d1
7
+ data.tar.gz: c67eea8b6b4b0177ae6c3bff4d46f061daa11e96f24c64f779b8da7c78c67d42e77711836a86f599eb70f43349b88599dface3e93a05ee74933085691f9da4a6
@@ -32,8 +32,15 @@ Make sure you have latest version installed (1.0.0 or higher).
32
32
  API_KEY = 'AAAA-BBBB-CCCC-DDDD'
33
33
  FORM_ID = 'my-form-id'
34
34
 
35
+ ENDPOINT_DOMAIN = 'wufoo.com'
36
+ ENDPOINT_PREFIX = 'YourPrefix'
37
+
35
38
  wufoo = WuParty.new(ACCOUNT, API_KEY)
36
39
 
40
+ If your Wufoo domain is not "wufoo.com" (e.g. "wufoo.eu") and/or your account prefix does not match your account name, you can pass those in:
41
+
42
+ wufoo = WuParty.new(ACCOUNT, API_KEY, domain: 'wufoo.eu', account_prefix: 'myaccount')
43
+
37
44
  === Login
38
45
 
39
46
  result = WuParty.login(myIntegrationKey, users_email, users_password)
@@ -1,15 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'httparty'
2
- gem 'multipart-post'
3
- require 'net/http/post/multipart'
4
- gem 'mime-types'
5
- require 'mime/types'
4
+
5
+ require_relative './wuparty/entity'
6
+ require_relative './wuparty/form'
7
+ require_relative './wuparty/report'
8
+ require_relative './wuparty/user'
9
+ require_relative './wuparty/version'
6
10
 
7
11
  class WuParty
8
12
  include HTTParty
9
13
  format :json
10
14
 
11
- VERSION = '1.2.3'
12
-
13
15
  # Represents a general error connecting to the Wufoo service
14
16
  class ConnectionError < RuntimeError; end
15
17
 
@@ -24,58 +26,69 @@ class WuParty
24
26
  attr_reader :code
25
27
  end
26
28
 
27
- ENDPOINT = 'https://%s.wufoo.com/api/v3'
28
29
  API_VERSION = '3.0'
29
30
 
30
31
  # uses the Login API to fetch a user's API key
31
32
  def self.login(integration_key, email, password, account = nil)
32
- result = self.post("https://wufoo.com/api/v3/login.json", { :body => { :integrationKey => integration_key, :email => email, :password => password, :subdomain => account }})
33
- if result.is_a?(String)
34
- raise ConnectionError, result
35
- elsif result['HTTPCode']
36
- raise HTTPError.new(result['HTTPCode'], result['Text'])
37
- else
38
- result
39
- end
33
+ result = post(
34
+ 'https://wufoo.com/api/v3/login.json',
35
+ body: {
36
+ integrationKey: integration_key,
37
+ email: email,
38
+ password: password,
39
+ subdomain: account
40
+ }
41
+ )
42
+ raise ConnectionError, result if result.is_a?(String)
43
+ raise HTTPError.new(result['HTTPCode'], result['Text']) if result['HTTPCode']
44
+ result
40
45
  end
41
46
 
42
47
  # Create a new WuParty object
43
- def initialize(account, api_key)
48
+ def initialize(account, api_key, domain: 'wufoo.com', account_prefix: nil)
44
49
  @account = account
45
50
  @api_key = api_key
51
+ @domain = domain
52
+ @account_prefix = account_prefix || @account
46
53
  @field_numbers = {}
47
54
  end
48
55
 
49
56
  # Returns list of forms and details accessible by the user account.
50
57
  def forms
51
58
  get(:forms)['Forms'].map do |details|
52
- Form.new(details['Url'], :party => self, :details => details)
59
+ Form.new(details['Url'], party: self, details: details)
53
60
  end
54
61
  end
55
62
 
56
63
  # Returns list of reports and details accessible by the user account.
57
64
  def reports
58
65
  get(:reports)['Reports'].map do |details|
59
- Report.new(details['Url'], :party => self, :details => details)
66
+ Report.new(details['Url'], party: self, details: details)
60
67
  end
61
68
  end
62
69
 
63
70
  # Returns list of users and details.
64
71
  def users
65
72
  get(:users)['Users'].map do |details|
66
- User.new(details['Url'], :party => self, :details => details)
73
+ User.new(details['Url'], party: self, details: details)
67
74
  end
68
75
  end
69
76
 
70
77
  # Returns details about the specified form.
71
78
  def form(form_id)
72
- if f = get("forms/#{form_id}")['Forms']
73
- Form.new(f.first['Url'], :party => self, :details => f.first)
74
- end
79
+ return unless (f = get("forms/#{form_id}")['Forms'])
80
+ Form.new(f.first['Url'], party: self, details: f.first)
75
81
  end
76
82
 
77
- def add_webhook(form_id, url, metadata = false, handshakeKey = "")
78
- put("forms/#{form_id}/webhooks", :body => {'url' => url, 'handshakeKey' => handshakeKey, 'metadata' => metadata})
83
+ def add_webhook(form_id, url, metadata = false, handshake_key = '')
84
+ put(
85
+ "forms/#{form_id}/webhooks",
86
+ body: {
87
+ 'url' => url,
88
+ 'handshakeKey' => handshake_key,
89
+ 'metadata' => metadata
90
+ }
91
+ )
79
92
  end
80
93
 
81
94
  def delete_webhook(form_id, webhook_hash)
@@ -84,274 +97,43 @@ class WuParty
84
97
 
85
98
  # Returns details about the specified report.
86
99
  def report(report_id)
87
- if r = get("reports/#{report_id}")['Reports']
88
- Report.new(r.first['Url'], :party => self, :details => r.first)
89
- end
100
+ return unless (r = get("reports/#{report_id}")['Reports'])
101
+ Report.new(r.first['Url'], party: self, details: r.first)
90
102
  end
91
103
 
92
- def get(method, options={}) # :nodoc:
104
+ def get(method, options = {}) # :nodoc:
93
105
  handle_http_verb(:get, method, options)
94
106
  end
95
107
 
96
- def post(method, options={}) # :nodoc:
108
+ def post(method, options = {}) # :nodoc:
97
109
  handle_http_verb(:post, method, options)
98
110
  end
99
111
 
100
- def put(method, options={}) # :nodoc:
112
+ def put(method, options = {}) # :nodoc:
101
113
  handle_http_verb(:put, method, options)
102
114
  end
103
115
 
104
- def delete(method, options={}) # :nodoc:
116
+ def delete(method, options = {}) # :nodoc:
105
117
  handle_http_verb(:delete, method, options)
106
118
  end
107
119
 
108
120
  private
109
121
 
110
- def base_url
111
- ENDPOINT % @account
112
- end
113
-
114
- def handle_http_verb(verb, action, options={})
115
- options.merge!(:basic_auth => {:username => @api_key})
116
- url = "#{base_url}/#{action}.json"
117
- result = self.class.send(verb, url, options)
118
- begin
119
- result.to_s # trigger parse error if possible
120
- rescue MultiJson::DecodeError => e
121
- raise HTTPError.new(500, e.message)
122
- end
123
- if result.is_a?(String)
124
- raise ConnectionError, result
125
- elsif result['HTTPCode']
126
- raise HTTPError.new(result['HTTPCode'], result['Text'])
127
- else
128
- result
129
- end
130
- end
131
-
132
- public
133
-
134
- # ----------
135
-
136
- class Entity # :nodoc:
137
- include HTTParty
138
- format :json
139
-
140
- def initialize(id, options)
141
- @id = id
142
- if options[:party]
143
- @party = options[:party]
144
- elsif options[:account] and options[:api_key]
145
- @party = WuParty.new(options[:account], options[:api_key])
146
- else
147
- raise WuParty::InitializationException, "You must either specify a :party object or pass the :account and :api_key options. Please see the README."
148
- end
149
- @details = options[:details]
150
- end
151
-
152
- attr_reader :id
153
- attr_accessor :details
154
- end
155
-
156
- # Wraps an individual Wufoo Form.
157
- # == Instantiation
158
- # There are two ways to instantiate a Form object:
159
- # 1. Via the parent WuParty object that represents the account.
160
- # 2. Via the WuParty::Form class directly.
161
- # wufoo = WuParty.new(ACCOUNT, API_KEY)
162
- # form = wufoo.form(FORM_ID)
163
- # # or...
164
- # form = WuParty::Form.new(FORM_ID, :account => ACCOUNT, :api_key => API_KEY)
165
- # The first technique makes a call to the Wufoo API to get the form details,
166
- # while the second technique lazily loads the form details, once something is accessed via [].
167
- # == \Form Details
168
- # Access form details like it is a Hash, e.g.:
169
- # form['Name']
170
- # form['RedirectMessage']
171
- class Form < Entity
172
- # Returns field details for the form.
173
- def fields
174
- @party.get("forms/#{@id}/fields")['Fields']
175
- end
176
-
177
- # Access form details.
178
- def [](id)
179
- @details ||= @party.form(@id)
180
- @details[id]
181
- end
182
-
183
- def add_webhook(url, metadata = false, handshakeKey = "")
184
- @party.add_webhook(@details["Hash"], url, metadata, handshakeKey)
185
- end
186
-
187
- def delete_webhook(webhook_id)
188
- @party.delete_webhook(@details["Hash"], webhook_id)
189
- end
190
-
191
- # Returns fields and subfields, as a flattened array, e.g.
192
- # [{'ID' => 'Field1', 'Title' => 'Name - First', 'Type' => 'shortname', 'Required' => true }, # (subfield)
193
- # {'ID' => 'Field2', 'Title' => 'Name - Last', 'Type' => 'shortname', 'Required' => true }, # (subfield)
194
- # {'ID' => 'Field3', 'Title' => 'Birthday', 'Type' => 'date', 'Required' => flase}] # (field)
195
- # By default, only fields that can be submitted are returned. Pass *true* as the first arg to return all fields.
196
- def flattened_fields(all=false)
197
- flattened = []
198
- fields.each do |field|
199
- next unless all or field['ID'] =~ /^Field/
200
- if field['SubFields']
201
- field['SubFields'].each do |sub_field|
202
- flattened << {'ID' => sub_field['ID'], 'Title' => field['Title'] + ' - ' + sub_field['Label'], 'Type' => field['Type'], 'Required' => field['IsRequired'] == '1'}
203
- end
204
- else
205
- flattened << {'ID' => field['ID'], 'Title' => field['Title'], 'Type' => field['Type'], 'Required' => field['IsRequired'] == '1'}
206
- end
207
- end
208
- flattened
209
- end
210
-
211
- # Return entries already submitted to the form.
212
- #
213
- # Supports:
214
- # - filtering:
215
- # entries(:filters => [['Field1', 'Is_equal_to', 'Tim']])
216
- # entries(:filters => [['Field1', 'Is_equal_to', 'Tim'], ['Field2', 'Is_equal_to', 'Morgan']], :filter_match => 'OR')
217
- #
218
- # - sorting:
219
- # entries(:sort => 'EntryId DESC')
220
- #
221
- # - limiting:
222
- # entries(:limit => 5)
223
- #
224
- # See http://wufoo.com/docs/api/v3/entries/get/#filter for details
225
- def entries(options={})
226
- query = {}
227
-
228
- if options[:filters]
229
- query['match'] = options[:filter_match] || 'AND'
230
- options[:filters].each_with_index do |filter, index|
231
- query["Filter#{ index + 1 }"] = filter.join(' ')
232
- end
233
- end
234
-
235
- if options[:limit]
236
- query[:pageSize] = options[:limit]
237
- end
238
-
239
- if options[:pageStart]
240
- query[:pageStart] = options[:pageStart]
241
- end
242
-
243
- if options[:system]
244
- query[:system] = true
245
- end
246
-
247
- if options[:sort]
248
- field, direction = options[:sort].split(' ')
249
- query[:sort] = field
250
- query[:sortDirection] = direction || 'ASC'
251
- end
252
-
253
- @party.get("forms/#{@id}/entries", :query => query)['Entries']
254
- end
255
-
256
- # Return entries already submitted to the form.
257
- #
258
- # Supports:
259
- # Same as Entries above with filtering.
260
- # form.count(:filters => [['Field1', 'Is_equal_to', 'Tim']])
261
- #
262
- # See http://wufoo.com/docs/api/v3/entries/get/#filter for details
263
- def count(options={})
264
- query = {}
265
-
266
- if options[:filters]
267
- query['match'] = options[:filter_match] || 'AND'
268
- options[:filters].each_with_index do |filter, index|
269
- query["Filter#{ index + 1 }"] = filter.join(' ')
270
- end
271
- end
272
-
273
- if options[:system]
274
- query[:system] = true
275
- end
276
-
277
- @party.get("forms/#{@id}/entries/count", :query => query)['EntryCount']
278
- end
279
-
280
-
281
- # Submit form data to the form.
282
- # Pass data as a hash, with field ids as the hash keys, e.g.
283
- # submit('Field1' => 'Tim', 'Field2' => 'Morgan')
284
- # Return value is a Hash that includes the following keys:
285
- # * Status
286
- # * ErrorText
287
- # * FieldErrors
288
- # You must submit values for required fields (including all sub fields),
289
- # and dates must be formatted as <tt>YYYYMMDD</tt>.
290
- def submit(data)
291
- options = {}
292
- data.each do |key, value|
293
- if value.is_a?(Hash)
294
- type = MIME::Types.of(value[:path]).first.content_type rescue 'application/octet-stream'
295
- options[:multipart] ||= {}
296
- options[:multipart][key] = {:type => type, :path => value[:path]}
297
- else
298
- options[:body] ||= {}
299
- options[:body][key] = value
300
- end
301
- end
302
- @party.post("forms/#{@id}/entries", options)
303
- end
304
-
305
- # Returns comment details for the form.
306
- # See Wufoo API documentation for possible options,
307
- # e.g. to filter comments for a specific form entry:
308
- # form.comments('entryId' => 123)
309
- def comments(options={})
310
- options = {:query => options} if options.any?
311
- @party.get("forms/#{@id}/comments", options)['Comments']
312
- end
122
+ def base_url
123
+ "https://#{@account_prefix}.#{@domain}/api/v3"
313
124
  end
314
125
 
315
- # Wraps an individual Wufoo Report.
316
- # == Instantiation
317
- # There are two ways to instantiate a Report object:
318
- # 1. Via the parent WuParty object that represents the account.
319
- # 2. Via the WuParty::Report class directly.
320
- # wufoo = WuParty.new(ACCOUNT, API_KEY)
321
- # report = wufoo.report(REPORT_ID)
322
- # # or...
323
- # report = WuParty::Report.new(REPORT_ID, :account => ACCOUNT, :api_key => API_KEY)
324
- # The first technique makes a call to the Wufoo API to get the report details,
325
- # while the second technique lazily loads the report details, once something is accessed via [].
326
- # == \Report Details
327
- # Access report details like it is a Hash, e.g.:
328
- # report['Name']
329
- class Report < Entity
330
- # Access report details.
331
- def [](id)
332
- @details ||= @party.report(@id)
333
- @details[id]
126
+ def handle_http_verb(verb, action, options = {})
127
+ options[:basic_auth] = { username: @api_key }
128
+ url = "#{base_url}/#{action}.json"
129
+ result = self.class.send(verb, url, options)
130
+ begin
131
+ result.to_s # trigger parse error if possible
132
+ rescue MultiJson::DecodeError => e
133
+ raise HTTPError.new(500, e.message)
334
134
  end
335
-
336
- # Returns field details for the report
337
- def fields
338
- @party.get("reports/#{@id}/fields")['Fields']
339
- end
340
-
341
- # Returns widget details for the report
342
- def widgets
343
- @party.get("reports/#{@id}/widgets")['Widgets']
344
- end
345
- end
346
-
347
- # Wraps an individual Wufoo User.
348
- class User < Entity
349
-
350
- # Access user details.
351
- def [](id)
352
- @details ||= @party.report(@id)
353
- @details[id]
354
- end
355
-
135
+ raise ConnectionError, result if result.is_a?(String)
136
+ raise HTTPError.new(result['HTTPCode'], result['Text']) if result['HTTPCode']
137
+ result
356
138
  end
357
139
  end
@@ -2,14 +2,13 @@ require './lib/wuparty'
2
2
  require 'test/unit'
3
3
 
4
4
  class WuPartyTest < Test::Unit::TestCase
5
-
6
5
  # Must create a form called "Test Form" and pass in its id
7
6
  # via the ENV variable WUFOO_FORM_ID.
8
7
  # Give the form standard name and address fields.
9
8
  # Make the name field required.
10
9
 
11
10
  def setup
12
- if ENV['WUFOO_ACCOUNT'] and ENV['WUFOO_API_KEY'] and ENV['WUFOO_FORM_ID']
11
+ if ENV['WUFOO_ACCOUNT'] && ENV['WUFOO_API_KEY'] && ENV['WUFOO_FORM_ID']
13
12
  @wufoo = WuParty.new(ENV['WUFOO_ACCOUNT'], ENV['WUFOO_API_KEY'])
14
13
  @form_id = ENV['WUFOO_FORM_ID']
15
14
  else
@@ -29,7 +28,7 @@ class WuPartyTest < Test::Unit::TestCase
29
28
  end
30
29
 
31
30
  def test_get_form_id
32
- assert_equal 1, @wufoo.forms.select {|f| f.id == 'test-form'}.length
31
+ assert_equal 1, @wufoo.forms.select { |f| f.id == 'test-form' }.length
33
32
  end
34
33
 
35
34
  def test_form_by_hash
@@ -38,7 +37,7 @@ class WuPartyTest < Test::Unit::TestCase
38
37
  end
39
38
 
40
39
  def test_form_directly
41
- form = WuParty::Form.new(@form_id, :account => ENV['WUFOO_ACCOUNT'], :api_key => ENV['WUFOO_API_KEY'])
40
+ form = WuParty::Form.new(@form_id, account: ENV['WUFOO_ACCOUNT'], api_key: ENV['WUFOO_API_KEY'])
42
41
  assert_equal 'Test Form', form['Name']
43
42
  end
44
43
 
@@ -65,7 +64,14 @@ class WuPartyTest < Test::Unit::TestCase
65
64
 
66
65
  def test_form_submit
67
66
  form = @wufoo.form(@form_id)
68
- result = form.submit('Field1' => 'Tim', 'Field2' => 'Morgan', 'Field3' => '4010 W. New Orleans', 'Field5' => 'Broken Arrow', 'Field6' => 'OK', 'Field7' => '74011')
67
+ result = form.submit(
68
+ 'Field1' => 'Tim',
69
+ 'Field2' => 'Morgan',
70
+ 'Field3' => '4010 W. New Orleans',
71
+ 'Field5' => 'Broken Arrow',
72
+ 'Field6' => 'OK',
73
+ 'Field7' => '74011'
74
+ )
69
75
  assert_equal 1, result['Success']
70
76
  assert result['EntryId']
71
77
  assert result['EntryLink']
@@ -84,7 +90,7 @@ class WuPartyTest < Test::Unit::TestCase
84
90
  assert_equal 1, result['FieldErrors'].length
85
91
  error = result['FieldErrors'].first
86
92
  assert_equal 'Field1', error['ID']
87
- assert_match /required/i, error['ErrorText']
93
+ assert_match(/required/i, error['ErrorText'])
88
94
  end
89
95
 
90
96
  def test_entries
@@ -97,17 +103,16 @@ class WuPartyTest < Test::Unit::TestCase
97
103
  form = @wufoo.form(@form_id)
98
104
  form.submit('Field1' => 'Tim', 'Field2' => 'Morgan')
99
105
  id = form.submit('Field1' => 'Jane', 'Field2' => 'Smith')['EntryId']
100
- assert form.entries(:filters => [['Field2', 'Is_equal_to', 'Morgan']]).any?
101
- assert_equal 1, form.entries(:filters => [['EntryId', 'Is_equal_to', id]]).length
106
+ assert form.entries(filters: [%w[Field2 Is_equal_to Morgan]]).any?
107
+ assert_equal 1, form.entries(filters: [['EntryId', 'Is_equal_to', id]]).length
102
108
  end
103
109
 
104
110
  def test_add_webhook
105
111
  # test with optional parameters
106
- response = @wufoo.add_webhook(@form_id, "http://#{ENV['WUFOO_ACCOUNT']}.com/#{@form_id}", true, "handshakeKey01")
107
- assert_match /[a-z0-9]{6}/i, response['WebHookPutResult']['Hash']
112
+ response = @wufoo.add_webhook(@form_id, "http://#{ENV['WUFOO_ACCOUNT']}.com/#{@form_id}", true, 'handshakeKey01')
113
+ assert_match(/[a-z0-9]{6}/i, response['WebHookPutResult']['Hash'])
108
114
  # test without optional parameters
109
115
  response = @wufoo.add_webhook(@form_id, "http://#{ENV['WUFOO_ACCOUNT']}.com/#{@form_id}-2")
110
- assert_match /[a-z0-9]{6}/i, response['WebHookPutResult']['Hash']
116
+ assert_match(/[a-z0-9]{6}/i, response['WebHookPutResult']['Hash'])
111
117
  end
112
-
113
118
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wuparty
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Morgan
@@ -25,33 +25,33 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.16.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: multipart-post
28
+ name: mime-types
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.0.1
33
+ version: '1.16'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 1.0.1
40
+ version: '1.16'
41
41
  - !ruby/object:Gem::Dependency
42
- name: mime-types
42
+ name: multipart-post
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '1.16'
47
+ version: 1.0.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '1.16'
54
+ version: 1.0.1
55
55
  description:
56
56
  email: tim@timmorgan.org
57
57
  executables: []