survey-gizmo-ruby 1.0.5 → 2.0.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.
- 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
|