survey-gizmo-ruby 1.0.5 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/Gemfile +1 -2
- data/README.md +88 -50
- data/Rakefile +2 -1
- data/lib/survey-gizmo-ruby.rb +1 -1
- data/lib/survey_gizmo/api/contact.rb +3 -3
- data/lib/survey_gizmo/api/option.rb +3 -4
- data/lib/survey_gizmo/api/page.rb +9 -5
- data/lib/survey_gizmo/api/question.rb +31 -17
- data/lib/survey_gizmo/api/response.rb +8 -9
- data/lib/survey_gizmo/api/survey.rb +21 -6
- data/lib/survey_gizmo/resource.rb +114 -214
- data/lib/survey_gizmo/rest_response.rb +82 -0
- data/lib/survey_gizmo/survey_gizmo.rb +27 -22
- data/spec/resource_spec.rb +81 -55
- data/spec/support/methods.rb +7 -4
- data/spec/support/spec_shared_api_object.rb +25 -71
- data/spec/support/spec_shared_object_with_errors.rb +6 -8
- data/spec/support/test_resource_classes.rb +4 -21
- data/spec/survey-gizmo-ruby_spec.rb +8 -98
- data/survey-gizmo-ruby.gemspec +22 -17
- metadata +68 -11
- data/lib/survey_gizmo/collection.rb +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7cb1e79765bcce6a50eee8322f40b91f3eb6c07a
|
4
|
+
data.tar.gz: 9667fb03ea0a0e3d1fc95b5a87dc5a1244d87a3d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0164944250b283f6cb3b3916cd9662bc30db55bf55918dbcb8f1f95edbd8c6af2eed73ce65e5714c121fcf844a3b44a5c129af756b61633574a6f114ed04f9c5
|
7
|
+
data.tar.gz: 6e96c4e265af7c09d2a1f60dab253718549c8853a19dfff98332512740ee778ddd8e6ba249f4ceeb96603ffd205bc23a272af075374de64f6cb35cd80faa94fe
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,75 +1,111 @@
|
|
1
|
-
|
1
|
+
#### WARNING:
|
2
2
|
|
3
|
-
|
3
|
+
This is version `2.0.0` of the gem, which introduces breaking changes. People who need backwards compatibility can use `1.0.4`.
|
4
4
|
|
5
|
-
|
5
|
+
What's fixed/better:
|
6
|
+
* Filtering of requests is implemented
|
7
|
+
* Requests for the questions in a survey now retrieve ALL of the questions, even the sneaky sub_questions that weren't directly returned to a basic API request.
|
6
8
|
|
7
|
-
|
9
|
+
What broke:
|
10
|
+
* SurveyGizmo objects (Survey, SurveyQuestion, etc) no longer track their own state (:new, :zombie, :saved, etc etc) - state tracking was useless anyways because exceptions always were raised on errors.
|
11
|
+
* There is no more SurveyGizmo::Collection class... now there are just Arrays.
|
12
|
+
* There is no more lazy loading/instantiation.
|
8
13
|
|
9
|
-
|
14
|
+
What's different:
|
15
|
+
* Variables are not autoloaded. That is to say when you load a Survey, the API request that loads the associated questions is not executed until you ask for them with the #questions method
|
10
16
|
|
11
|
-
|
12
|
-
|
13
|
-
-chorn@chorn.com 2013-03-15
|
17
|
+
Also a past warning from another author:
|
18
|
+
> SurveyGizmo doesn't test their REST API when they roll out changes. They don't publish a list of active defects, and when you call/email for support it is unlikely you will geto a person that knows anything about programming or the REST API. You can't talk to level 2 support, although they might offer you a discount on their paid consulting rates if the problem persists for more than a few weeks.
|
14
19
|
|
20
|
+
— chorn@chorn.com 2013-03-15
|
15
21
|
|
16
22
|
# Survey Gizmo (ruby)
|
17
23
|
|
18
|
-
Integrate with the [Survey Gizmo API](http://
|
24
|
+
Integrate with the [Survey Gizmo API](http://apisurveygizmo.helpgizmo.com/help) using an ActiveModel style interface. We currently support rest API **v3**. If you want to use version 1 of the API, please use gem version ~0.7.0
|
19
25
|
|
20
26
|
## Installation
|
21
27
|
|
22
|
-
|
28
|
+
```ruby
|
29
|
+
gem 'survey-gizmo-ruby'
|
30
|
+
```
|
23
31
|
|
24
32
|
## Basic Usage
|
25
33
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
34
|
+
```ruby
|
35
|
+
require 'survey-gizmo-ruby'
|
36
|
+
|
37
|
+
# somewhere in your app define your survey gizmo login credentials.
|
38
|
+
SurveyGizmo.setup(user: 'you@somewhere.com', password: 'mypassword')
|
39
|
+
|
40
|
+
# Retrieve the survey with id: 12345
|
41
|
+
survey = SurveyGizmo::API::Survey.first(id: 12345)
|
42
|
+
survey.title # => My Title
|
43
|
+
survey.pages # => [page1, page2,...]
|
44
|
+
|
45
|
+
# Create a question for your survey
|
46
|
+
question = SurveyGizmo::API::Question.create(survey_id: survey.id, title: 'Do you like ruby?', type: 'checkbox')
|
47
|
+
question.title = "Do you LOVE Ruby?"
|
48
|
+
question.save # => question # (but now with the id assigned by SurveyGizmo as the :id property)
|
49
|
+
|
50
|
+
# Error handling
|
51
|
+
question.save # => false
|
52
|
+
question.errors # => ['There was an error']
|
53
|
+
|
54
|
+
# Retrieving Questions for a given survey. Note that page_id is a required parameter.
|
55
|
+
questions = SurveyGizmo::API::Question.all(survey_id: survey.id, page_id: 1)
|
56
|
+
# Or just retrieve all questions for all pages of this survey
|
57
|
+
questions = survey.questions
|
58
|
+
|
59
|
+
# Retrieving SurveyResponses for a given survey.
|
60
|
+
# Note that because of both options being hashes, you need to enclose them both in braces to page successfully!
|
61
|
+
responses = SurveyGizmo::API::Response.all({survey_id: survey.id}, {page: 1})
|
62
|
+
|
63
|
+
# Retrieving page 2 of non test data SurveyResponses
|
64
|
+
filters = {page: 2, filters: [{field: 'istestdata', operator: '<>', value: 1}] }
|
65
|
+
responses = SurveyGizmo::API::Response.all({survey_id: survey_id}, filters)
|
66
|
+
```
|
67
|
+
|
68
|
+
## Debugging
|
69
|
+
|
70
|
+
The GIZMO_DEBUG environment variable will trigger full printouts of SurveyGizmo's HTTP responses and variable introspection for almost everything
|
71
|
+
|
72
|
+
```bash
|
73
|
+
cd /my/app
|
74
|
+
export GIZMO_DEBUG=true
|
75
|
+
bundle exec rails whatever
|
76
|
+
```
|
77
|
+
|
44
78
|
## Adding API Objects
|
45
79
|
|
46
80
|
Currently, the following API objects are included in the gem: `Survey`, `Question`, `Option`, `Page`, `Response`, `EmailMessage`, `SurveyCampaign`, `Contact`. If you want to use something that isn't included you can easily write a class that handles it. Here's an example of the how to do so:
|
47
81
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
82
|
+
```ruby
|
83
|
+
class SomeObject
|
84
|
+
# the base where most of the methods for handling the API are stored
|
85
|
+
include SurveyGizmo::Resource
|
86
|
+
|
87
|
+
# the attribtues the object should respond to
|
88
|
+
attribute :id, Integer
|
89
|
+
attribute :title, String
|
90
|
+
attribute :status, String
|
91
|
+
attribute :type, String
|
92
|
+
attribute :created_on, DateTime
|
93
|
+
|
94
|
+
# defing the paths used to retrieve/set info
|
95
|
+
route '/something/:id', :via => [:get, :update, :delete]
|
96
|
+
route '/something', :via => :create
|
97
|
+
|
98
|
+
# this must be defined with the params that would be included in any route
|
99
|
+
def to_param_options
|
100
|
+
{:id => self.id}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
```
|
68
104
|
|
69
105
|
The [Virtus](https://github.com/solnic/virtus) gem is included to handle the attributes, so please check their documentation as well.
|
70
106
|
|
71
107
|
# Contributing to survey-gizmo-ruby
|
72
|
-
|
108
|
+
|
73
109
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
74
110
|
* Take a gander at the github issues beforehand
|
75
111
|
* Fork the project
|
@@ -80,7 +116,9 @@ The [Virtus](https://github.com/solnic/virtus) gem is included to handle the att
|
|
80
116
|
|
81
117
|
## Missing Features
|
82
118
|
|
83
|
-
|
119
|
+
* It would be nice to implement enumerable on the Question and (especially) Response objects so people don't have to implement their own paging
|
120
|
+
* There are several API objects that are available and not included in this gem.
|
121
|
+
* It is also missing OAuth authentication ability.
|
84
122
|
|
85
123
|
|
86
124
|
# Copyright
|
data/Rakefile
CHANGED
data/lib/survey-gizmo-ruby.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require 'survey_gizmo/survey_gizmo'
|
@@ -38,12 +38,12 @@ module SurveyGizmo; module API
|
|
38
38
|
attribute :scustomfield9, String
|
39
39
|
attribute :scustomfield10, String
|
40
40
|
|
41
|
-
route '/survey/:survey_id/surveycampaign/:campaign_id/contact/:id', :
|
42
|
-
route '/survey/:survey_id/surveycampaign/:campaign_id/contact', :
|
41
|
+
route '/survey/:survey_id/surveycampaign/:campaign_id/contact/:id', via: [:get, :update, :delete]
|
42
|
+
route '/survey/:survey_id/surveycampaign/:campaign_id/contact', via: :create
|
43
43
|
|
44
44
|
# @see SurveyGizmo::Resource#to_param_options
|
45
45
|
def to_param_options
|
46
|
-
{:
|
46
|
+
{id: self.id, survey_id: self.survey_id, campaign_id: self.campaign_id}
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end; end
|
@@ -14,8 +14,8 @@ module SurveyGizmo; module API
|
|
14
14
|
attribute :properties, Hash
|
15
15
|
|
16
16
|
# routing
|
17
|
-
route '/survey/:survey_id/surveypage/:page_id/surveyquestion/:question_id/surveyoption', :
|
18
|
-
route '/survey/:survey_id/surveypage/:page_id/surveyquestion/:question_id/surveyoption/:id', :
|
17
|
+
route '/survey/:survey_id/surveypage/:page_id/surveyquestion/:question_id/surveyoption', via: :create
|
18
|
+
route '/survey/:survey_id/surveypage/:page_id/surveyquestion/:question_id/surveyoption/:id', via: [:get, :update, :delete]
|
19
19
|
|
20
20
|
# survey gizmo sends a hash back for :title
|
21
21
|
# @private
|
@@ -27,8 +27,7 @@ module SurveyGizmo; module API
|
|
27
27
|
|
28
28
|
# @see SurveyGizmo::Resource#to_param_options
|
29
29
|
def to_param_options
|
30
|
-
{:
|
30
|
+
{id: self.id, survey_id: self.survey_id, page_id: self.page_id, question_id: self.question_id}
|
31
31
|
end
|
32
|
-
|
33
32
|
end
|
34
33
|
end; end
|
@@ -12,25 +12,29 @@ module SurveyGizmo; module API
|
|
12
12
|
attribute :after, Integer
|
13
13
|
attribute :survey_id, Integer
|
14
14
|
|
15
|
-
|
16
15
|
# routing
|
17
16
|
route '/survey/:survey_id/surveypage', :via => :create
|
18
17
|
route '/survey/:survey_id/surveypage/:id', :via => [:get, :update, :delete]
|
19
18
|
|
20
|
-
|
21
|
-
|
19
|
+
def survey
|
20
|
+
@survey ||= SurveyGizmo::API::Survey.first(id: survey_id)
|
21
|
+
end
|
22
|
+
|
23
|
+
def questions
|
24
|
+
@questions ||= SurveyGizmo::API::Question.all(survey_id: survey_id, page_id: id)
|
25
|
+
end
|
22
26
|
|
23
27
|
# survey gizmo sends a hash back for :title
|
24
28
|
# @private
|
25
29
|
def title_with_multilingual=(val)
|
26
|
-
self.title_without_multilingual = val.is_a?(Hash) ? val : {
|
30
|
+
self.title_without_multilingual = val.is_a?(Hash) ? val : { 'English' => val }
|
27
31
|
end
|
28
32
|
|
29
33
|
alias_method_chain :title=, :multilingual
|
30
34
|
|
31
35
|
# @see SurveyGizmo::Resource#to_param_options
|
32
36
|
def to_param_options
|
33
|
-
{:
|
37
|
+
{id: self.id, survey_id: self.survey_id}
|
34
38
|
end
|
35
39
|
end
|
36
40
|
end; end
|
@@ -5,26 +5,40 @@ module SurveyGizmo; module API
|
|
5
5
|
|
6
6
|
# @macro [attach] virtus_attribute
|
7
7
|
# @return [$2]
|
8
|
-
attribute :id,
|
9
|
-
attribute :title,
|
10
|
-
attribute :type,
|
11
|
-
attribute :description,
|
12
|
-
attribute :shortname,
|
13
|
-
attribute :properties,
|
14
|
-
attribute :after,
|
15
|
-
attribute :survey_id,
|
16
|
-
attribute :page_id,
|
8
|
+
attribute :id, Integer
|
9
|
+
attribute :title, String
|
10
|
+
attribute :type, String
|
11
|
+
attribute :description, String
|
12
|
+
attribute :shortname, String
|
13
|
+
attribute :properties, Hash
|
14
|
+
attribute :after, Integer
|
15
|
+
attribute :survey_id, Integer
|
16
|
+
attribute :page_id, Integer, :default => 1
|
17
|
+
attribute :sub_question_skus, Array
|
18
|
+
attribute :parent_question_id, Integer
|
17
19
|
|
18
20
|
alias_attribute :_subtype, :type
|
19
21
|
|
20
|
-
route '/survey/:survey_id/surveyquestion/:id', :
|
21
|
-
route '/survey/:survey_id/surveypage/:page_id/surveyquestion', :
|
22
|
-
route '/survey/:survey_id/surveypage/:page_id/surveyquestion/:id', :
|
22
|
+
route '/survey/:survey_id/surveyquestion/:id', via: :get
|
23
|
+
route '/survey/:survey_id/surveypage/:page_id/surveyquestion', via: :create
|
24
|
+
route '/survey/:survey_id/surveypage/:page_id/surveyquestion/:id', via: [:update, :delete]
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
def survey
|
27
|
+
@survey ||= SurveyGizmo::API::Survey.first(id: survey_id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def options
|
31
|
+
@options ||= SurveyGizmo::API::Option.all(survey_id: survey_id, page_id: page_id, question_id: id)
|
32
|
+
end
|
27
33
|
|
34
|
+
def parent_question
|
35
|
+
@parent_question ||= parent_question_id ? SurveyGizmo::API::Question.first(survey_id: survey_id, id: parent_question_id) : nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def sub_questions
|
39
|
+
@sub_questions ||= sub_question_skus.map {|subquestion_id| SurveyGizmo::API::Question.first(survey_id: survey_id, id: subquestion_id)}
|
40
|
+
.each {|subquestion| subquestion.parent_question_id = id}
|
41
|
+
end
|
28
42
|
# survey gizmo sends a hash back for :title
|
29
43
|
# @private
|
30
44
|
def title_with_multilingual=(val)
|
@@ -35,7 +49,7 @@ module SurveyGizmo; module API
|
|
35
49
|
|
36
50
|
# @see SurveyGizmo::Resource#to_param_options
|
37
51
|
def to_param_options
|
38
|
-
{:
|
52
|
+
{id: self.id, survey_id: self.survey_id, page_id: self.page_id}
|
39
53
|
end
|
40
54
|
end
|
41
|
-
end; end
|
55
|
+
end; end
|
@@ -10,7 +10,7 @@ module SurveyGizmo; module API
|
|
10
10
|
attribute :contact_id, Integer
|
11
11
|
attribute :data, String
|
12
12
|
attribute :status, String
|
13
|
-
attribute :
|
13
|
+
attribute :datesubmitted, DateTime
|
14
14
|
attribute :is_test_data, Boolean
|
15
15
|
attribute :sResponseComment, String
|
16
16
|
attribute :variable, Hash # READ-ONLY
|
@@ -20,17 +20,16 @@ module SurveyGizmo; module API
|
|
20
20
|
attribute :answers, Hash # READ-ONLY
|
21
21
|
|
22
22
|
# routing
|
23
|
-
route '/survey/:survey_id/surveyresponse', :
|
24
|
-
route '/survey/:survey_id/surveyresponse/:id', :
|
23
|
+
route '/survey/:survey_id/surveyresponse', via: :create
|
24
|
+
route '/survey/:survey_id/surveyresponse/:id', via: [:get, :update, :delete]
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
{:id => self.id, :survey_id => self.survey_id}
|
26
|
+
def survey
|
27
|
+
@survey ||= SurveyGizmo::API::Survey.first(id: survey_id)
|
29
28
|
end
|
30
29
|
|
31
|
-
|
32
|
-
|
30
|
+
# @see SurveyGizmo::Resource#to_param_options
|
31
|
+
def to_param_options
|
32
|
+
{id: self.id, survey_id: self.survey_id}
|
33
33
|
end
|
34
|
-
|
35
34
|
end
|
36
35
|
end; end
|
@@ -7,7 +7,7 @@ module SurveyGizmo; module API
|
|
7
7
|
# @return [$2]
|
8
8
|
attribute :id, Integer
|
9
9
|
attribute :team, Integer
|
10
|
-
attribute :type,
|
10
|
+
attribute :type, String
|
11
11
|
attribute :_subtype, String
|
12
12
|
attribute :status, String
|
13
13
|
attribute :forward_only, Boolean
|
@@ -23,15 +23,30 @@ module SurveyGizmo; module API
|
|
23
23
|
attribute :modified_on, DateTime
|
24
24
|
attribute :copy, Boolean
|
25
25
|
|
26
|
-
route '/survey/:id', :
|
27
|
-
route '/survey', :
|
26
|
+
route '/survey/:id', via: [:get, :update, :delete]
|
27
|
+
route '/survey', via: :create
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
def pages
|
30
|
+
@pages ||= SurveyGizmo::API::Page.all(survey_id: id)
|
31
|
+
end
|
32
|
+
|
33
|
+
def questions
|
34
|
+
@questions ||= pages.map {|p| SurveyGizmo::API::Question.all(survey_id: id, page_id: p.id)}.flatten
|
35
|
+
end
|
36
|
+
|
37
|
+
# Statistics array of arrays looks like:
|
38
|
+
# [["Partial", 2], ["Disqualified", 28], ["Complete", 15]]
|
39
|
+
def number_of_completed_responses
|
40
|
+
if statistics && !statistics.empty? && (completed_data = statistics.find {|a| a[0] == 'Complete'})
|
41
|
+
completed_data[1]
|
42
|
+
else
|
43
|
+
0
|
44
|
+
end
|
45
|
+
end
|
31
46
|
|
32
47
|
# @see SurveyGizmo::Resource#to_param_options
|
33
48
|
def to_param_options
|
34
|
-
{:
|
49
|
+
{id: self.id}
|
35
50
|
end
|
36
51
|
end
|
37
52
|
end; end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'set'
|
2
|
+
require 'addressable/uri'
|
3
3
|
|
4
4
|
module SurveyGizmo
|
5
5
|
module Resource
|
@@ -8,7 +8,6 @@ module SurveyGizmo
|
|
8
8
|
included do
|
9
9
|
include Virtus.model
|
10
10
|
instance_variable_set('@paths', {})
|
11
|
-
instance_variable_set('@collections', {})
|
12
11
|
SurveyGizmo::Resource.descendants << self
|
13
12
|
end
|
14
13
|
|
@@ -22,24 +21,58 @@ module SurveyGizmo
|
|
22
21
|
module ClassMethods
|
23
22
|
|
24
23
|
# Convert a [Hash] of filters into a query string
|
25
|
-
# @param [Hash] filters
|
24
|
+
# @param [Hash] filters - simple pagination or other options at the top level, and surveygizmo "filters" at the :filters key
|
26
25
|
# @return [String]
|
26
|
+
#
|
27
|
+
# example input: {page: 2, filters: [{:field=>"istestdata", :operator=>"<>", :value=>1}]}
|
28
|
+
# The top level keys (e.g. page, resultsperpage) get simply encoded in the url, while the contents of the array of hashes
|
29
|
+
# passed at filters[:filters] gets turned into the format surveygizmo expects for its internal filtering, for example:
|
30
|
+
#
|
31
|
+
# filter[field][0]=istestdata&filter[operator][0]=<>&filter[value][0]=1
|
27
32
|
def convert_filters_into_query_string(filters = nil)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
33
|
+
if filters && filters.size > 0
|
34
|
+
output_filters = filters[:filters] || []
|
35
|
+
filter_hash = {}
|
36
|
+
output_filters.each_with_index do |filter,i|
|
37
|
+
filter_hash.merge!({
|
38
|
+
"filter[field][#{i}]".to_sym => "#{filter[:field]}",
|
39
|
+
"filter[operator][#{i}]".to_sym => "#{filter[:operator]}",
|
40
|
+
"filter[value][#{i}]".to_sym => "#{filter[:value]}",
|
41
|
+
})
|
42
|
+
end
|
43
|
+
simple_filters = filters.reject {|k,v| k == :filters}
|
44
|
+
filter_hash.merge!(simple_filters)
|
45
|
+
|
46
|
+
uri = Addressable::URI.new
|
47
|
+
uri.query_values = filter_hash
|
48
|
+
"?#{uri.query}"
|
49
|
+
else
|
50
|
+
''
|
51
|
+
end
|
32
52
|
end
|
33
53
|
|
34
54
|
# Get a list of resources
|
35
55
|
# @param [Hash] conditions
|
36
56
|
# @param [Hash] filters
|
37
|
-
# @return [
|
57
|
+
# @return [Array] of objects of this class
|
38
58
|
def all(conditions = {}, filters = nil)
|
39
|
-
response =
|
59
|
+
response = RestResponse.new(SurveyGizmo.get(handle_route(:create, conditions) + convert_filters_into_query_string(filters)))
|
40
60
|
if response.ok?
|
41
|
-
_collection =
|
42
|
-
|
61
|
+
_collection = response.data.map {|datum| datum.is_a?(Hash) ? self.new(datum) : datum}
|
62
|
+
|
63
|
+
# Add in the properties from the conditions hash because many of the important ones (like survey_id) are
|
64
|
+
# not often part of the SurveyGizmo returned data
|
65
|
+
conditions.keys.each do |k|
|
66
|
+
if conditions[k] && instance_methods.include?(k)
|
67
|
+
_collection.each { |c| c[k] ||= conditions[k] }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Sub questions are not pulled by default so we have to retrieve them
|
72
|
+
if self == SurveyGizmo::API::Question
|
73
|
+
_collection += _collection.map {|question| question.sub_questions}.flatten
|
74
|
+
end
|
75
|
+
|
43
76
|
_collection
|
44
77
|
else
|
45
78
|
[]
|
@@ -51,8 +84,10 @@ module SurveyGizmo
|
|
51
84
|
# @param [Hash] filters
|
52
85
|
# @return [Object, nil]
|
53
86
|
def first(conditions = {}, filters = nil)
|
54
|
-
response =
|
55
|
-
|
87
|
+
response = RestResponse.new(SurveyGizmo.get(handle_route(:get, conditions) + convert_filters_into_query_string(filters)))
|
88
|
+
# Add in the properties from the conditions hash because many of the important ones (like survey_id) are
|
89
|
+
# not often part of the SurveyGizmo's returned data
|
90
|
+
response.ok? ? new(conditions.merge(response.data)) : nil
|
56
91
|
end
|
57
92
|
|
58
93
|
# Create a new resource
|
@@ -61,7 +96,7 @@ module SurveyGizmo
|
|
61
96
|
# The newly created Resource instance
|
62
97
|
def create(attributes = {})
|
63
98
|
resource = new(attributes)
|
64
|
-
resource.
|
99
|
+
resource.create_record_in_surveygizmo
|
65
100
|
resource
|
66
101
|
end
|
67
102
|
|
@@ -81,8 +116,7 @@ module SurveyGizmo
|
|
81
116
|
# @param [Hash] conditions
|
82
117
|
# @return [Boolean]
|
83
118
|
def destroy(conditions)
|
84
|
-
|
85
|
-
response.ok?
|
119
|
+
RestResponse.new(SurveyGizmo.delete(handle_route(:delete, conditions))).ok?
|
86
120
|
end
|
87
121
|
|
88
122
|
# Define the path where a resource is located
|
@@ -95,76 +129,32 @@ module SurveyGizmo
|
|
95
129
|
def route(path, options)
|
96
130
|
methods = options[:via]
|
97
131
|
methods = [:get, :create, :update, :delete] if methods == :any
|
98
|
-
methods.is_a?(Array) ? methods.each{|m| @paths[m] = path } : (@paths[methods] = path)
|
132
|
+
methods.is_a?(Array) ? methods.each { |m| @paths[m] = path } : (@paths[methods] = path)
|
99
133
|
nil
|
100
134
|
end
|
101
135
|
|
136
|
+
# This method replaces the :page_id, :survey_id, etc strings defined in each model's URI routes with the
|
137
|
+
# values being passed in interpolation hash with the same keys.
|
102
138
|
# @api private
|
103
|
-
def
|
104
|
-
resource = new(attributes)
|
105
|
-
resource.__send__(:clean!)
|
106
|
-
resource
|
107
|
-
end
|
108
|
-
|
109
|
-
# Defines a new collection. These are child objects of the resource.
|
110
|
-
# @macro [new] collection
|
111
|
-
# @param [Symbol] resource_name the name of the collection, pluralized
|
112
|
-
# @param [Class] model and optional class name if the class name does not match the resource_name
|
113
|
-
# @return [Collection]
|
114
|
-
# the $1 collection
|
115
|
-
# @scope instance
|
116
|
-
def collection(resource_name, model = nil)
|
117
|
-
@collections[resource_name] = {:parent => self, :target => (model ? model : resource_name)} # workaround for weird bug with passing a class to Collection
|
118
|
-
class_eval(<<-EOS)
|
119
|
-
def #{resource_name}
|
120
|
-
@#{resource_name} ||= []
|
121
|
-
end
|
122
|
-
|
123
|
-
def #{resource_name}=(array)
|
124
|
-
@#{resource_name} = SurveyGizmo::Collection.new(#{self}, :#{resource_name}, array)
|
125
|
-
end
|
126
|
-
EOS
|
127
|
-
end
|
128
|
-
|
129
|
-
# @api private
|
130
|
-
def collections
|
131
|
-
@collections.dup.freeze
|
132
|
-
end
|
133
|
-
|
134
|
-
# @api private
|
135
|
-
def handle_route(key, *interp)
|
139
|
+
def handle_route(key, interpolation_hash)
|
136
140
|
path = @paths[key]
|
137
141
|
raise "No routes defined for `#{key}` in #{self.name}" unless path
|
138
|
-
|
142
|
+
raise "User/password hash not setup!" if SurveyGizmo.default_params.empty?
|
143
|
+
|
139
144
|
path.gsub(/:(\w+)/) do |m|
|
140
|
-
|
145
|
+
raise(SurveyGizmo::URLError, "Missing RESTful parameters in request: `#{m}`") unless interpolation_hash[$1.to_sym]
|
146
|
+
interpolation_hash[$1.to_sym]
|
141
147
|
end
|
142
148
|
end
|
143
149
|
end
|
144
150
|
|
145
|
-
# Updates attributes and saves this Resource instance
|
146
|
-
#
|
147
|
-
# @param [Hash] attributes
|
148
|
-
# attributes to be updated
|
149
|
-
#
|
150
|
-
# @return [Boolean]
|
151
|
-
# true if resource is saved
|
152
|
-
def update(attributes = {})
|
153
|
-
self.attributes = attributes
|
154
|
-
self.save
|
155
|
-
end
|
156
|
-
|
157
151
|
# Save the instance to Survey Gizmo
|
158
|
-
#
|
159
|
-
# @return [Boolean]
|
160
|
-
# true if Resource instance is saved
|
161
152
|
def save
|
162
|
-
if
|
163
|
-
|
153
|
+
if id #Then it's an update
|
154
|
+
handle_response(SurveyGizmo.post(handle_route(:update), query: self.attributes_without_blanks))
|
155
|
+
@latest_response.ok?
|
164
156
|
else
|
165
|
-
|
166
|
-
_response.ok? ? saved! : false
|
167
|
-
end
|
157
|
+
create_record_in_surveygizmo
|
168
158
|
end
|
169
159
|
end
|
170
160
|
|
@@ -172,50 +162,24 @@ module SurveyGizmo
|
|
172
162
|
# @return [self, false]
|
173
163
|
# Returns the object, if saved. Otherwise returns false.
|
174
164
|
def reload
|
175
|
-
handle_response
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
end
|
165
|
+
handle_response(SurveyGizmo.get(handle_route(:get)))
|
166
|
+
if @latest_response.ok?
|
167
|
+
self.attributes = @latest_response['data']
|
168
|
+
self
|
169
|
+
else
|
170
|
+
false
|
182
171
|
end
|
183
172
|
end
|
184
173
|
|
185
174
|
# Deleted the Resource from Survey Gizmo
|
186
175
|
# @return [Boolean]
|
187
176
|
def destroy
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
# The state of the current Resource
|
195
|
-
# @api private
|
196
|
-
def new?
|
197
|
-
@_state.nil?
|
198
|
-
end
|
199
|
-
|
200
|
-
# @todo This seemed like a good way to prevent accidently trying to perform an action
|
201
|
-
# on a record at a point when it would fail. Not sure if it's really necessary though.
|
202
|
-
[:clean, # stored and not dirty
|
203
|
-
:saved, # stored and not modified
|
204
|
-
:destroyed, # duh!
|
205
|
-
:zombie # needs to be stored
|
206
|
-
].each do |state|
|
207
|
-
# Change the method state to $1
|
208
|
-
define_method("#{state}!") do
|
209
|
-
@_state = state
|
210
|
-
true
|
211
|
-
end
|
212
|
-
|
213
|
-
# Inquire about the method state if $1
|
214
|
-
define_method("#{state}?") do
|
215
|
-
@_state == state
|
177
|
+
if id
|
178
|
+
handle_response(SurveyGizmo.delete(handle_route(:delete)))
|
179
|
+
@latest_response.ok?
|
180
|
+
else
|
181
|
+
false
|
216
182
|
end
|
217
|
-
|
218
|
-
private "#{state}!"
|
219
183
|
end
|
220
184
|
|
221
185
|
# Sets the hash that will be used to interpolate values in routes. It needs to be defined per model.
|
@@ -230,88 +194,41 @@ module SurveyGizmo
|
|
230
194
|
@errors ||= []
|
231
195
|
end
|
232
196
|
|
233
|
-
# @return [Hash] The raw JSON returned by Survey Gizmo
|
234
|
-
def raw_response
|
235
|
-
_response.response if _response
|
236
|
-
end
|
237
|
-
|
238
197
|
# @visibility private
|
239
198
|
def inspect
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
"@#{attrib.name}=#{value}" if attrib.respond_to?(:name)
|
199
|
+
if ENV['GIZMO_DEBUG']
|
200
|
+
ap "CLASS: #{self.class}"
|
244
201
|
end
|
245
202
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
end
|
254
|
-
|
255
|
-
# The parsed JSON data of the response
|
256
|
-
def data
|
257
|
-
@_data ||= (@response['data'] || {})
|
258
|
-
end
|
259
|
-
|
260
|
-
# The error message if there is one
|
261
|
-
def message
|
262
|
-
@_message ||= @response['message']
|
263
|
-
end
|
264
|
-
|
265
|
-
attr_reader :response
|
266
|
-
|
267
|
-
private
|
268
|
-
def cleanup_attribute_name(attr)
|
269
|
-
attr.downcase.gsub(/[^[:alnum:]]+/,'_').gsub(/(url|variable|standard|shown)/,'').gsub(/_+/,'_').gsub(/^_/,'').gsub(/_$/,'')
|
270
|
-
end
|
203
|
+
attribute_strings = self.class.attribute_set.map do |attrib|
|
204
|
+
if ENV['GIZMO_DEBUG']
|
205
|
+
ap attrib
|
206
|
+
ap attrib.name
|
207
|
+
ap self.send(attrib.name)
|
208
|
+
ap self.send(attrib.name).class
|
209
|
+
end
|
271
210
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
when /variable.*standard/
|
277
|
-
"meta"
|
278
|
-
when /variable.*shown/
|
279
|
-
"shown"
|
280
|
-
when /variable/
|
281
|
-
"variable"
|
282
|
-
when /question/
|
283
|
-
"answers"
|
211
|
+
if self.send(attrib.name).class == Hash
|
212
|
+
value = self.send(attrib.name).inspect
|
213
|
+
else
|
214
|
+
value = self.send(attrib.name).to_s
|
284
215
|
end
|
285
|
-
end
|
286
216
|
|
287
|
-
|
288
|
-
|
289
|
-
return if @response.nil? or not ok?
|
290
|
-
@_data = @response['data']
|
291
|
-
|
292
|
-
# Handle really crappy [] notation in SG API, so far just in SurveyResponse
|
293
|
-
items = (@_data.is_a?(Array) ? @_data : [@_data]).compact
|
294
|
-
items.each do |data_item|
|
295
|
-
data_item.keys.grep(/^\[/).each do |key|
|
296
|
-
next if data_item[key].nil? || data_item[key].length == 0
|
297
|
-
|
298
|
-
parent = find_attribute_parent(key)
|
299
|
-
data_item[parent] = {} unless data_item[parent]
|
300
|
-
|
301
|
-
case key.downcase
|
302
|
-
when /(url|variable.*standard)/
|
303
|
-
data_item[parent][cleanup_attribute_name(key).to_sym] = data_item[key]
|
304
|
-
when /variable.*shown/
|
305
|
-
data_item[parent][cleanup_attribute_name(key).to_i] = data_item[key].include?("1")
|
306
|
-
when /variable/
|
307
|
-
data_item[parent][cleanup_attribute_name(key).to_i] = data_item[key].to_i
|
308
|
-
when /question/
|
309
|
-
data_item[parent][key] = data_item[key]
|
310
|
-
end
|
217
|
+
" \"#{attrib.name}\" => \"#{value}\"\n" unless value.strip.blank?
|
218
|
+
end.compact
|
311
219
|
|
312
|
-
|
313
|
-
|
314
|
-
|
220
|
+
"#<#{self.class.name}:#{self.object_id}>\n#{attribute_strings.join()}"
|
221
|
+
end
|
222
|
+
|
223
|
+
# Returns itself if successfully saved, but with attributes added by SurveyGizmo
|
224
|
+
def create_record_in_surveygizmo(attributes = {})
|
225
|
+
http = RestResponse.new(SurveyGizmo.put(handle_route(:create), query: self.attributes_without_blanks))
|
226
|
+
handle_response(http)
|
227
|
+
if http.ok?
|
228
|
+
self.attributes = http.data
|
229
|
+
self
|
230
|
+
else
|
231
|
+
false
|
315
232
|
end
|
316
233
|
end
|
317
234
|
|
@@ -319,51 +236,34 @@ module SurveyGizmo
|
|
319
236
|
protected
|
320
237
|
|
321
238
|
def attributes_without_blanks
|
322
|
-
self.attributes.reject{|k,v| v.blank? }
|
239
|
+
self.attributes.reject { |k,v| v.blank? }
|
323
240
|
end
|
324
241
|
|
325
242
|
private
|
326
|
-
# The response object from SurveyGizmo. Useful for viewing the raw data returned
|
327
|
-
attr_reader :_response
|
328
|
-
|
329
|
-
def set_response(http)
|
330
|
-
@_response = Response.new(http)
|
331
|
-
end
|
332
|
-
|
333
243
|
def handle_route(key)
|
334
244
|
self.class.handle_route(key, to_param_options)
|
335
245
|
end
|
336
246
|
|
337
|
-
def handle_response(
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
http = SurveyGizmo.put(handle_route(:create), :query => self.attributes_without_blanks)
|
346
|
-
handle_response http do
|
347
|
-
if _response.ok?
|
348
|
-
self.attributes = _response.data
|
349
|
-
saved!
|
350
|
-
else
|
351
|
-
false
|
352
|
-
end
|
247
|
+
def handle_response(rest_response, &block)
|
248
|
+
@latest_response = rest_response
|
249
|
+
if @latest_response.ok?
|
250
|
+
self.errors.clear
|
251
|
+
true
|
252
|
+
else
|
253
|
+
errors << @latest_response.message
|
254
|
+
false
|
353
255
|
end
|
354
256
|
end
|
355
257
|
|
356
258
|
def _copy(attributes = {})
|
357
|
-
http = SurveyGizmo.post(handle_route(:update), :
|
358
|
-
handle_response
|
359
|
-
if
|
360
|
-
self.attributes =
|
361
|
-
saved!
|
259
|
+
http = RestResponse.new(SurveyGizmo.post(handle_route(:update), query: self.attributes_without_blanks))
|
260
|
+
handle_response(http) do
|
261
|
+
if http.ok?
|
262
|
+
self.attributes = http.data
|
362
263
|
else
|
363
264
|
false
|
364
265
|
end
|
365
266
|
end
|
366
267
|
end
|
367
|
-
|
368
268
|
end
|
369
269
|
end
|