formstack 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/formstack.rb +23 -0
- data/lib/formstack/client.rb +82 -0
- data/test/formstack_test.rb +69 -0
- data/test/helper.rb +43 -0
- metadata +147 -0
data/lib/formstack.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'hashie'
|
3
|
+
|
4
|
+
directory = File.expand_path(File.dirname(__FILE__))
|
5
|
+
|
6
|
+
Hash.send :include, Hashie::HashExtensions
|
7
|
+
|
8
|
+
module Formstack
|
9
|
+
|
10
|
+
VERSION = "0.0.1".freeze
|
11
|
+
|
12
|
+
|
13
|
+
class FormstackError < StandardError
|
14
|
+
attr_reader :data
|
15
|
+
|
16
|
+
def initialize(data)
|
17
|
+
@data = data
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
require File.join(directory, 'formstack', 'client')
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Formstack
|
2
|
+
class Client
|
3
|
+
include HTTParty
|
4
|
+
base_uri "https://www.formstack.com/api/"
|
5
|
+
format :json
|
6
|
+
|
7
|
+
def initialize(key)
|
8
|
+
self.class.default_params(:api_key => key, :type => 'json')
|
9
|
+
end
|
10
|
+
|
11
|
+
def forms
|
12
|
+
self.class.get("/forms").forms.map{|f| handle_form(f)}
|
13
|
+
end
|
14
|
+
|
15
|
+
def form(form_id)
|
16
|
+
handle_form(self.class.get("/form", :query => {:id => form_id}))
|
17
|
+
end
|
18
|
+
|
19
|
+
def data(form_id, options={})
|
20
|
+
api_response = self.class.get("/data", :query => {:id => form_id}.merge(options))
|
21
|
+
api_response.submissions = api_response.submissions.map{|s| handle_submission(s) }
|
22
|
+
api_response
|
23
|
+
end
|
24
|
+
alias :submissions :data
|
25
|
+
|
26
|
+
def submission(submission_id, options={})
|
27
|
+
handle_submission(self.class.get("/submission", :query => {:id => submission_id}.merge(options)))
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def submit(form_id, options={})
|
32
|
+
self.class.post("/submit", :body => {:id => form_id}.merge(prepare_params(form_id, options)))['id']
|
33
|
+
end
|
34
|
+
|
35
|
+
def edit(submission_id, options={})
|
36
|
+
self.class.post("/edit", :body => {:id => submission_id}.merge(prepare_params(submission_id, options)))['id']
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete(submission_id)
|
40
|
+
self.class.post("/delete", :body => {:id => submission_id})['id']
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def prepare_params(form_id, params={})
|
45
|
+
data = params.delete(:data)
|
46
|
+
form = form(form_id)
|
47
|
+
data.each do |field, value|
|
48
|
+
field_id = form.fields.any? {|f| f['name'] == field.to_s} ? form.fields.find {|f| f['name'] == field.to_s}['id'] : field
|
49
|
+
params["field_#{field_id}"] = value
|
50
|
+
end
|
51
|
+
params
|
52
|
+
end
|
53
|
+
|
54
|
+
def handle_form(form)
|
55
|
+
form.created = Time.parse(form.created) unless form.created.nil?
|
56
|
+
form
|
57
|
+
end
|
58
|
+
|
59
|
+
def handle_submission(submission)
|
60
|
+
data = submission.data
|
61
|
+
data.each do |datum|
|
62
|
+
submission[datum.field] = datum.value
|
63
|
+
end
|
64
|
+
submission.timestamp = Time.parse(submission.timestamp)
|
65
|
+
submission
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.get(*args); handle_response super end
|
69
|
+
def self.post(*args); handle_response super end
|
70
|
+
|
71
|
+
def self.handle_response(response)
|
72
|
+
case response.code
|
73
|
+
when 500...600; raise FormstackError.new(Hashie::Mash.new(response).error)
|
74
|
+
else; response
|
75
|
+
end
|
76
|
+
|
77
|
+
Hashie::Mash.new(response).response
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class FormstackTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "Formstack API" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@client = Formstack::Client.new("OU812")
|
9
|
+
end
|
10
|
+
|
11
|
+
should "list forms for an account" do
|
12
|
+
stub_get("/forms?type=json&api_key=OU812", "forms.json")
|
13
|
+
forms = @client.forms
|
14
|
+
forms.size.should == 1
|
15
|
+
forms.first.name.should == 'Contact'
|
16
|
+
end
|
17
|
+
|
18
|
+
should "get details for a form" do
|
19
|
+
stub_get("/form?id=1234&type=json&api_key=OU812", "form.json")
|
20
|
+
form = @client.form(1234)
|
21
|
+
form.fields.size.should == 5
|
22
|
+
form.fields.first.section_heading.should == 'Contact Information'
|
23
|
+
end
|
24
|
+
|
25
|
+
should "get submitted data for a form" do
|
26
|
+
stub_get("/data?id=1234&page=1&type=json&api_key=OU812", "data.json")
|
27
|
+
submissions = @client.data(1234, :page => 1).submissions
|
28
|
+
submissions.size.should == 2
|
29
|
+
submissions.first['1111'].should == "John Smith"
|
30
|
+
submissions.first.timestamp.year.should == 2007
|
31
|
+
end
|
32
|
+
|
33
|
+
should "return a single submission collected for a form" do
|
34
|
+
stub_get("/submission?id=1001&type=json&api_key=OU812", "submission.json")
|
35
|
+
submission = @client.submission(1001)
|
36
|
+
submission['2222'].should == "Apple"
|
37
|
+
submission.timestamp.year.should == 2007
|
38
|
+
end
|
39
|
+
|
40
|
+
should "prepare data for form submission" do
|
41
|
+
stub_get("/form?id=1234&type=json&api_key=OU812", "form.json")
|
42
|
+
params = {:page => 3, :data => {:name => "Wynn Netherland", :phone => "940-867-5309", '123' => 'foo'}}
|
43
|
+
prepared = @client.prepare_params(1234, params)
|
44
|
+
prepared['field_7344054'].should == 'Wynn Netherland'
|
45
|
+
prepared['field_7344057'].should == '940-867-5309'
|
46
|
+
prepared['field_123'].should == 'foo'
|
47
|
+
end
|
48
|
+
|
49
|
+
should "submit data for a form" do
|
50
|
+
stub_post("/submit?type=json&api_key=OU812", "submit.json")
|
51
|
+
id = @client.submit(1234, :data => {:foo => 'bar'})
|
52
|
+
id.should == 10001
|
53
|
+
end
|
54
|
+
|
55
|
+
should "update submitted data for a form" do
|
56
|
+
stub_post("/edit?type=json&api_key=OU812", "submit.json")
|
57
|
+
id = @client.edit(1234, :data => {:foo => 'bar'})
|
58
|
+
id.should == 10001
|
59
|
+
end
|
60
|
+
|
61
|
+
should "delete submitted data for a form" do
|
62
|
+
stub_post("/delete?type=json&api_key=OU812", "submit.json")
|
63
|
+
id = @client.delete(1234)
|
64
|
+
id.should == 10001
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
|
5
|
+
require 'redgreen'
|
6
|
+
require 'matchy'
|
7
|
+
require 'fakeweb'
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
10
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
11
|
+
require 'formstack'
|
12
|
+
|
13
|
+
|
14
|
+
# Set the default allow_net_connect option--usually you'll want this off.
|
15
|
+
# You don't usually want your test suite to make HTTP connections, do you?
|
16
|
+
FakeWeb.allow_net_connect = false
|
17
|
+
|
18
|
+
class Test::Unit::TestCase
|
19
|
+
end
|
20
|
+
|
21
|
+
def fixture_file(filename)
|
22
|
+
return '' if filename == ''
|
23
|
+
file_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/' + filename)
|
24
|
+
File.read(file_path)
|
25
|
+
end
|
26
|
+
|
27
|
+
def formstack_url(url, options={})
|
28
|
+
url =~ /^http/ ? url : "https://www.formstack.com/api#{url}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def stub_request(method, url, filename, status=nil)
|
32
|
+
options = {:body => ""}
|
33
|
+
options.merge!({:body => fixture_file(filename)}) if filename
|
34
|
+
options.merge!({:body => status.last}) if status
|
35
|
+
options.merge!({:status => status}) if status
|
36
|
+
|
37
|
+
FakeWeb.register_uri(method, formstack_url(url), options)
|
38
|
+
end
|
39
|
+
|
40
|
+
def stub_get(*args); stub_request(:get, *args) end
|
41
|
+
def stub_post(*args); stub_request(:post, *args) end
|
42
|
+
|
43
|
+
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: formstack
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Wynn Netherland
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-23 00:00:00 -05:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
segments:
|
26
|
+
- 0
|
27
|
+
- 1
|
28
|
+
- 3
|
29
|
+
version: 0.1.3
|
30
|
+
name: hashie
|
31
|
+
prerelease: false
|
32
|
+
requirement: *id001
|
33
|
+
type: :runtime
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
- 1
|
42
|
+
- 0
|
43
|
+
version: 0.1.0
|
44
|
+
name: httparty
|
45
|
+
prerelease: false
|
46
|
+
requirement: *id002
|
47
|
+
type: :runtime
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 2
|
55
|
+
- 10
|
56
|
+
- 1
|
57
|
+
version: 2.10.1
|
58
|
+
name: shoulda
|
59
|
+
prerelease: false
|
60
|
+
requirement: *id003
|
61
|
+
type: :development
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
- 4
|
70
|
+
- 0
|
71
|
+
version: 0.4.0
|
72
|
+
name: matchy
|
73
|
+
prerelease: false
|
74
|
+
requirement: *id004
|
75
|
+
type: :development
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
segments:
|
82
|
+
- 1
|
83
|
+
- 2
|
84
|
+
- 5
|
85
|
+
version: 1.2.5
|
86
|
+
name: fakeweb
|
87
|
+
prerelease: false
|
88
|
+
requirement: *id005
|
89
|
+
type: :development
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
98
|
+
name: yard
|
99
|
+
prerelease: false
|
100
|
+
requirement: *id006
|
101
|
+
type: :development
|
102
|
+
description: Wrapper for the Formstack API
|
103
|
+
email: wynn.netherland@gmail.com
|
104
|
+
executables: []
|
105
|
+
|
106
|
+
extensions: []
|
107
|
+
|
108
|
+
extra_rdoc_files: []
|
109
|
+
|
110
|
+
files:
|
111
|
+
- lib/formstack/client.rb
|
112
|
+
- lib/formstack.rb
|
113
|
+
has_rdoc: true
|
114
|
+
homepage: http://github.com/pengwynn/formstack
|
115
|
+
licenses: []
|
116
|
+
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options: []
|
119
|
+
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
segments:
|
127
|
+
- 0
|
128
|
+
version: "0"
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
segments:
|
134
|
+
- 1
|
135
|
+
- 3
|
136
|
+
- 6
|
137
|
+
version: 1.3.6
|
138
|
+
requirements: []
|
139
|
+
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 1.3.6
|
142
|
+
signing_key:
|
143
|
+
specification_version: 3
|
144
|
+
summary: Wrapper for the Formstack API
|
145
|
+
test_files:
|
146
|
+
- test/helper.rb
|
147
|
+
- test/formstack_test.rb
|