survey-gizmo-ruby 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile CHANGED
@@ -1,12 +1,13 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "activesupport", '~> 3.0.1'
3
+ gem "activesupport", '>= 3.0.1'
4
4
  gem 'i18n'
5
5
  gem 'virtus', '~> 0.0.5'
6
6
  gem 'httparty'
7
7
 
8
8
  group :development do
9
- gem "yard", "~> 0.6.0"
9
+ gem 'bluecloth', :require => nil
10
+ gem "yard", "~> 0.7.0"
10
11
  gem "bundler", "~> 1.0.0"
11
12
  gem "jeweler", "~> 1.6.4"
12
13
  end
@@ -15,4 +16,5 @@ group :test do
15
16
  gem "webmock", :require => 'webmock/rspec'
16
17
  gem "rspec", "~> 2.3.0"
17
18
  gem 'net-http-spy', :require => nil
19
+ gem 'awesome_print', :require => nil
18
20
  end
@@ -1,23 +1,26 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- activesupport (3.0.10)
4
+ activesupport (3.1.3)
5
+ multi_json (~> 1.0)
5
6
  addressable (2.2.6)
6
- crack (0.1.8)
7
+ awesome_print (1.0.1)
8
+ bluecloth (2.2.0)
9
+ crack (0.3.1)
7
10
  diff-lcs (1.1.3)
8
11
  git (1.2.5)
9
- httparty (0.8.0)
12
+ httparty (0.8.1)
10
13
  multi_json
11
14
  multi_xml
12
- i18n (0.5.0)
15
+ i18n (0.6.0)
13
16
  jeweler (1.6.4)
14
17
  bundler (~> 1.0)
15
18
  git (>= 1.2.5)
16
19
  rake
17
- multi_json (1.0.3)
18
- multi_xml (0.4.0)
20
+ multi_json (1.0.4)
21
+ multi_xml (0.4.1)
19
22
  net-http-spy (0.2.1)
20
- rake (0.9.2)
23
+ rake (0.9.2.2)
21
24
  rspec (2.3.0)
22
25
  rspec-core (~> 2.3.0)
23
26
  rspec-expectations (~> 2.3.0)
@@ -26,17 +29,19 @@ GEM
26
29
  rspec-expectations (2.3.0)
27
30
  diff-lcs (~> 1.1.2)
28
31
  rspec-mocks (2.3.0)
29
- virtus (0.0.8)
30
- webmock (1.7.6)
31
- addressable (~> 2.2, > 2.2.5)
32
+ virtus (0.0.10)
33
+ webmock (1.7.8)
34
+ addressable (> 2.2.5, ~> 2.2)
32
35
  crack (>= 0.1.7)
33
- yard (0.6.8)
36
+ yard (0.7.4)
34
37
 
35
38
  PLATFORMS
36
39
  ruby
37
40
 
38
41
  DEPENDENCIES
39
- activesupport (~> 3.0.1)
42
+ activesupport (>= 3.0.1)
43
+ awesome_print
44
+ bluecloth
40
45
  bundler (~> 1.0.0)
41
46
  httparty
42
47
  i18n
@@ -45,4 +50,4 @@ DEPENDENCIES
45
50
  rspec (~> 2.3.0)
46
51
  virtus (~> 0.0.5)
47
52
  webmock
48
- yard (~> 0.6.0)
53
+ yard (~> 0.7.0)
data/README.md CHANGED
@@ -4,7 +4,7 @@ Integrate with the [Survey Gizmo API](http://developer.surveygizmo.com/resources
4
4
 
5
5
  ## Installation
6
6
 
7
- The gem hasn't been pushed to rubygems.org yet, so for now just install from the repo with rake.
7
+ gem install survey-gizmo-ruby
8
8
 
9
9
  ## Basic Usage
10
10
 
@@ -13,10 +13,19 @@ The gem hasn't been pushed to rubygems.org yet, so for now just install from the
13
13
  # somewhere in your app define your survey gizmo login credentials.
14
14
  SurveyGizmo.setup(:user => 'you@somewhere.com', :password => 'mypassword')
15
15
 
16
- SurveyGizmo::API::Survey.first(:id => 12345)
16
+ survey = SurveyGizmo::API::Survey.first(:id => 12345)
17
+ survey.title # => My Title
18
+ survey.pages # => [page1, page2,...]
19
+
20
+ question = SurveyGizmo::API::Question.create(:survey_id => survey.id, :title => 'Do you like ruby?', :type => 'checkbox')
21
+ question.title = "Do you LOVE Ruby?"
22
+ question.save # => true
23
+ question.saved? # => true
24
+
25
+ # Error handling
26
+ question.save # => false
27
+ question.errors # => ['There was an error']
17
28
 
18
- SurveyGizmo::API::Question.create(:survey_id => 1234, :page_id => 1, :title => 'Do you like ruby?', :type => 'checkbox')
19
-
20
29
  ## Adding API Objects
21
30
 
22
31
  Currently, the following API objects are included in the gem: `Survey`, `Question`, `Option`, `Page`. 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 `SurveyGizmo::API::Survey` class:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.0
@@ -1,16 +1,19 @@
1
1
  module SurveyGizmo; module API
2
+ # @see SurveyGizmo::Resource::ClassMethods
2
3
  class Option
3
4
  include SurveyGizmo::Resource
4
5
 
6
+ # @macro [attach] virtus_attribute
7
+ # @return [$2]
5
8
  attribute :id, Integer
6
9
  attribute :title, String
7
- attribute :value, String
10
+ attribute :value, String
8
11
  attribute :survey_id, Integer
9
12
  attribute :page_id, Integer
10
13
  attribute :question_id, Integer
11
14
 
12
15
  # routing
13
- route '/survey/:survey_id/surveypage/:page_id/surveyquestion/:question_id/surveyoption', :via => :create
16
+ route '/survey/:survey_id/surveypage/:page_id/surveyquestion/:question_id/surveyoption', :via => :create
14
17
  route '/survey/:survey_id/surveypage/:page_id/surveyquestion/:question_id/surveyoption/:id', :via => [:get, :update, :delete]
15
18
 
16
19
  # survey gizmo sends a hash back for :title
@@ -21,8 +24,10 @@ module SurveyGizmo; module API
21
24
 
22
25
  alias_method_chain :title=, :multilingual
23
26
 
27
+ # @see SurveyGizmo::Resource#to_param_options
24
28
  def to_param_options
25
29
  {:id => self.id, :survey_id => self.survey_id, :page_id => self.page_id, :question_id => self.question_id}
26
30
  end
31
+
27
32
  end
28
33
  end; end
@@ -1,7 +1,10 @@
1
1
  module SurveyGizmo; module API
2
+ # @see SurveyGizmo::Resource::ClassMethods
2
3
  class Page
3
4
  include SurveyGizmo::Resource
4
5
 
6
+ # @macro [attach] virtus_attribute
7
+ # @return [$2]
5
8
  attribute :id, Integer
6
9
  attribute :title, String
7
10
  attribute :description, String
@@ -14,6 +17,7 @@ module SurveyGizmo; module API
14
17
  route '/survey/:survey_id/surveypage', :via => :create
15
18
  route '/survey/:survey_id/surveypage/:id', :via => [:get, :update, :delete]
16
19
 
20
+ # @macro collection
17
21
  collection :questions
18
22
 
19
23
  # survey gizmo sends a hash back for :title
@@ -24,6 +28,7 @@ module SurveyGizmo; module API
24
28
 
25
29
  alias_method_chain :title=, :multilingual
26
30
 
31
+ # @see SurveyGizmo::Resource#to_param_options
27
32
  def to_param_options
28
33
  {:id => self.id, :survey_id => self.survey_id}
29
34
  end
@@ -1,7 +1,10 @@
1
1
  module SurveyGizmo; module API
2
+ # @see SurveyGizmo::Resource::ClassMethods
2
3
  class Question
3
4
  include SurveyGizmo::Resource
4
5
 
6
+ # @macro [attach] virtus_attribute
7
+ # @return [$2]
5
8
  attribute :id, Integer
6
9
  attribute :title, String
7
10
  attribute :type, String
@@ -9,15 +12,15 @@ module SurveyGizmo; module API
9
12
  attribute :properties, Hash
10
13
  attribute :after, Integer
11
14
  attribute :survey_id, Integer
12
- attribute :page_id, Integer
15
+ attribute :page_id, Integer, :default => 1
13
16
 
14
17
  alias_attribute :_subtype, :type
15
18
 
16
- # routing
17
19
  route '/survey/:survey_id/surveyquestion/:id', :via => :get
18
20
  route '/survey/:survey_id/surveypage/:page_id/surveyquestion', :via => :create
19
21
  route '/survey/:survey_id/surveypage/:page_id/surveyquestion/:id', :via => [:update, :delete]
20
22
 
23
+ # @macro collection
21
24
  collection :options
22
25
 
23
26
  # survey gizmo sends a hash back for :title
@@ -28,6 +31,7 @@ module SurveyGizmo; module API
28
31
 
29
32
  alias_method_chain :title=, :multilingual
30
33
 
34
+ # @see SurveyGizmo::Resource#to_param_options
31
35
  def to_param_options
32
36
  {:id => self.id, :survey_id => self.survey_id, :page_id => self.page_id}
33
37
  end
@@ -0,0 +1,23 @@
1
+ module SurveyGizmo; module API
2
+ # @see SurveyGizmo::Resource::ClassMethods
3
+ class Response
4
+ include SurveyGizmo::Resource
5
+
6
+ # @macro [attach] virtus_attribute
7
+ # @return [$2] the attribute +$1+ as a $2
8
+ attribute :id, Integer
9
+ attribute :data, String
10
+ attribute :status, String
11
+ attribute :survey_id, Integer
12
+
13
+ # routing
14
+ route '/survey/:survey_id/surveyresponse', :via => :create
15
+ route '/survey/:survey_id/surveyresponse/:id', :via => [:get, :update, :delete]
16
+
17
+ # @see SurveyGizmo::Resource#to_param_options
18
+ def to_param_options
19
+ {:id => self.id, :survey_id => self.survey_id}
20
+ end
21
+
22
+ end
23
+ end; end
@@ -1,18 +1,24 @@
1
1
  module SurveyGizmo; module API
2
+ # @see SurveyGizmo::Resource::ClassMethods
2
3
  class Survey
3
4
  include SurveyGizmo::Resource
4
5
 
6
+ # @macro [attach] virtus_attribute
7
+ # @return [$2]
5
8
  attribute :id, Integer
6
- attribute :title, String
9
+ attribute :title, String
7
10
  attribute :status, String
8
11
  attribute :type, String, :default => 'survey'
12
+ attribute :links, Hash
9
13
  attribute :created_on, DateTime
10
14
 
11
15
  route '/survey/:id', :via => [:get, :update, :delete]
12
16
  route '/survey', :via => :create
13
17
 
18
+ # @macro collection
14
19
  collection :pages
15
-
20
+
21
+ # @see SurveyGizmo::Resource#to_param_options
16
22
  def to_param_options
17
23
  {:id => self.id}
18
24
  end
@@ -5,7 +5,7 @@ module SurveyGizmo
5
5
  private
6
6
  # @param [Class] resource
7
7
  # @param [Symbol] name
8
- # @param [Array] values
8
+ # @param [Array] values in hashes
9
9
  def initialize(resource, name, values)
10
10
  @array = Array(values)
11
11
  @collection = []
@@ -15,23 +15,28 @@ module SurveyGizmo
15
15
 
16
16
  public
17
17
 
18
+ # @private
18
19
  def length
19
20
  @array.length
20
21
  end
21
22
 
23
+ # @private
22
24
  def each
23
25
  lazy_load
24
26
  if block_given?
25
- @collection.each{ |o| yield(o)}
27
+ @collection.each{ |o| yield(o) }
26
28
  else
27
29
  @collection.each
28
30
  end
29
31
  end
30
32
 
33
+ # @private
31
34
  def method_missing(meth, *args, &blk)
35
+ lazy_load
32
36
  @collection.send(meth, *args, &blk)
33
37
  end
34
38
 
39
+ # @private
35
40
  def model
36
41
  return @model if defined?(@model)
37
42
  return (@model = options[:target]) if options[:target].is_a?(Class)
@@ -11,47 +11,41 @@ module SurveyGizmo
11
11
  SurveyGizmo::Resource.descendants << self
12
12
  end
13
13
 
14
+ # @return [Set] Every class that includes SurveyGizmo::Resource
14
15
  def self.descendants
15
16
  @descendants ||= Set.new
16
17
  end
17
18
 
19
+ # These are methods that every API resource has to access resources
20
+ # in Survey Gizmo
18
21
  module ClassMethods
19
22
 
20
23
  # Get a list of resources
21
24
  # @param [Hash] conditions
22
- # @return [SurveGizmo::Collection, false]
25
+ # @return [SurveyGizmo::Collection, Array]
23
26
  def all(conditions = {})
24
- response = SurveyGizmo.get(handle_route(:create, conditions))
25
- if response.parsed_response['result_ok']
26
- collection = SurveyGizmo::Collection.new(self, nil, response.parsed_response['data'])
27
- collection.send(:options=, {:target => self, :parent => self})
28
- collection
27
+ response = Response.new SurveyGizmo.get(handle_route(:create, conditions))
28
+ if response.ok?
29
+ _collection = SurveyGizmo::Collection.new(self, nil, response.data)
30
+ _collection.send(:options=, {:target => self, :parent => self})
31
+ _collection
29
32
  else
30
- # do something
31
- # e = response.parsed_response['message']
32
- false
33
+ []
33
34
  end
34
35
  end
35
36
 
36
37
  # Get the first resource
37
38
  # @param [Hash] conditions
38
- # @return [Object, false]
39
+ # @return [Object, nil]
39
40
  def first(conditions)
40
- response = SurveyGizmo.get(handle_route(:get, conditions))
41
- if response.parsed_response['result_ok']
42
- resource = new(conditions.merge(response.parsed_response['data']))
43
- resource.__send__(:clean!)
44
- resource
45
- else
46
- # do something
47
- # e = response.parsed_response['message']
48
- false
49
- end
41
+ response = Response.new SurveyGizmo.get(handle_route(:get, conditions))
42
+ response.ok? ? load(conditions.merge(response.data)) : nil
50
43
  end
51
44
 
52
45
  # Create a new resource
53
46
  # @param [Hash] attributes
54
- # @return [Object]
47
+ # @return [Resource]
48
+ # The newly created Resource instance
55
49
  def create(attributes = {})
56
50
  resource = new(attributes)
57
51
  resource.__send__(:_create)
@@ -59,8 +53,12 @@ module SurveyGizmo
59
53
  end
60
54
 
61
55
  # Define the path where a resource is located
62
- # @param [String] path the path in Survey Gizmo for the resource
63
- # @param [Hash] options must include `:via` which is `:get`, `:create`, `:update`, `:delete`, or `:any`
56
+ # @param [String] path
57
+ # the path in Survey Gizmo for the resource
58
+ # @param [Hash] options
59
+ # @option options [Array] :via
60
+ # which is `:get`, `:create`, `:update`, `:delete`, or `:any`
61
+ # @scope class
64
62
  def route(path, options)
65
63
  methods = options[:via]
66
64
  methods = [:get, :create, :update, :delete] if methods == :any
@@ -68,13 +66,20 @@ module SurveyGizmo
68
66
  nil
69
67
  end
70
68
 
71
-
69
+ # @api private
72
70
  def load(attributes = {})
73
71
  resource = new(attributes)
74
72
  resource.__send__(:clean!)
75
73
  resource
76
74
  end
77
75
 
76
+ # Defines a new collection. These are child objects of the resource.
77
+ # @macro [new] collection
78
+ # @param [Symbol] resource_name the name of the collection, pluralized
79
+ # @param [Class] model and optional class name if the class name does not match the resource_name
80
+ # @return [Collection]
81
+ # the $1 collection
82
+ # @scope instance
78
83
  def collection(resource_name, model = nil)
79
84
  @collections[resource_name] = {:parent => self, :target => (model ? model : resource_name)} # workaround for weird bug with passing a class to Collection
80
85
  class_eval(<<-EOS)
@@ -88,10 +93,12 @@ module SurveyGizmo
88
93
  EOS
89
94
  end
90
95
 
96
+ # @api private
91
97
  def collections
92
- @collections
98
+ @collections.dup.freeze
93
99
  end
94
100
 
101
+ # @api private
95
102
  def handle_route(key, *interp)
96
103
  path = @paths[key]
97
104
  raise "No routes defined for `#{key}` in #{self.name}" unless path
@@ -99,56 +106,76 @@ module SurveyGizmo
99
106
  path.gsub(/:(\w+)/){|m| options[$1.to_sym] }
100
107
  end
101
108
  end
102
-
109
+
110
+ # Updates attributes and saves this Resource instance
111
+ #
112
+ # @param [Hash] attributes
113
+ # attributes to be updated
114
+ #
115
+ # @return [Boolean]
116
+ # true if resource is saved
103
117
  def update(attributes = {})
104
118
  self.attributes = attributes
105
119
  self.save
106
120
  end
107
121
 
122
+ # Save the instance to Survey Gizmo
123
+ #
124
+ # @return [Boolean]
125
+ # true if Resource instance is saved
108
126
  def save
109
- response = SurveyGizmo.post(handle_route(:update), :query => self.attributes_without_blanks)
110
- _result = response.parsed_response['result_ok']
111
- saved! if _result
112
- _result
127
+ if new?
128
+ _create
129
+ else
130
+ handle_response SurveyGizmo.post(handle_route(:update), :query => self.attributes_without_blanks), do
131
+ _response.ok? ? saved! : false
132
+ end
133
+ end
113
134
  end
114
135
 
115
136
  # fetch resource from SurveyGizmo and reload the attributes
137
+ # @return [self, false]
138
+ # Returns the object, if saved. Otherwise returns false.
116
139
  def reload
117
- response = SurveyGizmo.get(handle_route(:get))
118
- if response.parsed_response['result_ok']
119
- self.attributes = response.parsed_response['data']
120
- clean!
121
- self
122
- else
123
- # do something
124
- # e = response.parsed_response['message']
125
- false
140
+ handle_response SurveyGizmo.get(handle_route(:get)), do
141
+ if _response.ok?
142
+ self.attributes = _response.data
143
+ clean!
144
+ else
145
+ false
146
+ end
126
147
  end
127
148
  end
128
149
 
150
+ # Deleted the Resource from Survey Gizmo
151
+ # @return [Boolean]
129
152
  def destroy
130
- return false if new?
131
- response = SurveyGizmo.delete(handle_route(:delete))
132
- _result = response.parsed_response['result_ok']
133
- destroyed! if _result
134
- _result
153
+ return false if new? || destroyed?
154
+ handle_response SurveyGizmo.delete(handle_route(:delete)), do
155
+ _response.ok? ? destroyed! : false
156
+ end
135
157
  end
136
158
 
159
+ # The state of the current Resource
160
+ # @api private
137
161
  def new?
138
162
  @_state.nil?
139
163
  end
140
164
 
141
165
  # @todo This seemed like a good way to prevent accidently trying to perform an action
142
- # on a record at a point when it would fail. Not sure if it's really necessary though.
166
+ # on a record at a point when it would fail. Not sure if it's really necessary though.
143
167
  [:clean, # stored and not dirty
144
168
  :saved, # stored and not modified
145
169
  :destroyed, # duh!
146
170
  :zombie # needs to be stored
147
171
  ].each do |state|
172
+ # Change the method state to $1
148
173
  define_method("#{state}!") do
149
174
  @_state = state
175
+ true
150
176
  end
151
177
 
178
+ # Inquire about the method state if $1
152
179
  define_method("#{state}?") do
153
180
  @_state == state
154
181
  end
@@ -157,11 +184,18 @@ module SurveyGizmo
157
184
  end
158
185
 
159
186
  # Sets the hash that will be used to interpolate values in routes. It needs to be defined per model.
160
- # @return [Hash] a hash of the values needed in routing. ie. {:id => self.id}
187
+ # @return [Hash] a hash of the values needed in routing
161
188
  def to_param_options
162
189
  raise "Define #to_param_options in #{self.class.name}"
163
190
  end
164
191
 
192
+ # Any errors returned by Survey Gizmo
193
+ # @return [Array]
194
+ def errors
195
+ @errors ||= []
196
+ end
197
+
198
+ # @visibility private
165
199
  def inspect
166
200
  attrs = self.class.attributes.map do |attrib|
167
201
  value = attrib.get!(self).inspect
@@ -171,29 +205,63 @@ module SurveyGizmo
171
205
 
172
206
  "#<#{self.class.name}:#{self.object_id} #{attrs.join(' ')}>"
173
207
  end
174
-
208
+
209
+ # This class normalizes the response returned by Survey Gizmo
210
+ class Response
211
+ def ok?
212
+ @response['result_ok']
213
+ end
214
+
215
+ # The parsed JSON data of the response
216
+ def data
217
+ @_data ||= (@response['data'] || {})
218
+ end
219
+
220
+ # The error message if there is one
221
+ def message
222
+ @_message ||= @response['message']
223
+ end
224
+
225
+ private
226
+ def initialize(response)
227
+ @response = response.parsed_response
228
+ end
229
+ end
230
+
175
231
  protected
176
232
 
233
+ def attributes_without_blanks
234
+ self.attributes.reject{|k,v| v.blank? }
235
+ end
236
+
237
+ private
238
+ attr_reader :_response
239
+
240
+ def set_response(http)
241
+ @_response = Response.new(http)
242
+ end
243
+
177
244
  def handle_route(key)
178
245
  self.class.handle_route(key, to_param_options)
179
246
  end
180
247
 
181
- # @private
182
- def _create(attributes = {})
183
- response = SurveyGizmo.put(handle_route(:create), :query => self.attributes_without_blanks)
184
- if response.parsed_response['result_ok']
185
- self.attributes = response.parsed_response['data']
186
- saved!
187
- else
188
- # do something
189
- # e = response.parsed_response['message']
190
- false
191
- end
248
+ def handle_response(resp, &block)
249
+ set_response(resp)
250
+ (self.errors << _response.message) unless _response.ok?
251
+ self.errors.clear if !self.errors.empty? && _response.ok?
252
+ instance_eval(&block)
192
253
  end
193
254
 
194
- # @private
195
- def attributes_without_blanks
196
- self.attributes.reject{|k,v| v.blank? }
255
+ def _create(attributes = {})
256
+ http = SurveyGizmo.put(handle_route(:create), :query => self.attributes_without_blanks)
257
+ handle_response http, do
258
+ if _response.ok?
259
+ self.attributes = _response.data
260
+ saved!
261
+ else
262
+ false
263
+ end
264
+ end
197
265
  end
198
266
 
199
267
  end
@@ -13,15 +13,25 @@ require "survey_gizmo/api/survey"
13
13
  require "survey_gizmo/api/question"
14
14
  require "survey_gizmo/api/option"
15
15
  require "survey_gizmo/api/page"
16
+ require "survey_gizmo/api/response"
16
17
 
17
18
  module SurveyGizmo
18
19
  include HTTParty
19
20
 
20
21
  format :json
22
+
23
+ # The base uri for this version of the API is $1
21
24
  base_uri 'https://restapi.surveygizmo.com/v1'
25
+
22
26
  @@options = {}
23
27
  mattr_accessor :options
24
28
 
29
+ # Setup the account credentials to access the API
30
+ # @param [Hash] opts
31
+ # @option opts [#to_s] :user
32
+ # The username for your account. Usually your email address
33
+ # @option opts [#to_s] :password
34
+ # The account password
25
35
  def self.setup(opts = {})
26
36
  self.options = opts
27
37
  default_params({"user:pass" => opts.values_at(:user, :password).join(':')})
@@ -0,0 +1,124 @@
1
+ require "spec_helper"
2
+ describe "Survey Gizmo Resource" do
3
+
4
+ describe SurveyGizmo::Resource do
5
+ before(:each) do
6
+ SurveyGizmo.setup(:user => 'test@test.com', :password => 'password')
7
+ end
8
+
9
+ let(:described_class) { SurveyGizmoSpec::ResourceTest }
10
+
11
+ let(:create_attributes){ {:title => 'Spec', :test_id => 5} }
12
+ let(:get_attributes) { create_attributes.merge(:id => 1) }
13
+ let(:update_attributes){ {:title => 'Updated'} }
14
+ let(:first_params){ {:id => 1} }
15
+ let(:uri_paths){
16
+ {
17
+ :get => '/test/1',
18
+ :create => '/test/5/resource',
19
+ :update => '/test/5/resource/1',
20
+ :delete => '/test/5/resource/1'
21
+ }
22
+ }
23
+
24
+ it "#new?" do
25
+ described_class.new.should be_new
26
+ end
27
+
28
+
29
+ it '#reload' do
30
+ stub_request(:get, /#{@base}/).to_return(json_response(true, get_attributes))
31
+ obj = described_class.new(create_attributes)
32
+ obj.attributes.reject{|k,v| v.blank? }.should == create_attributes
33
+ obj.reload
34
+ obj.attributes.reject{|k,v| v.blank? }.should == get_attributes
35
+ end
36
+
37
+ it '#valid?'
38
+
39
+ it "should track descendants" do
40
+ SurveyGizmo::Resource.descendants.should include(SurveyGizmoSpec::ResourceTest)
41
+ end
42
+
43
+ it_should_behave_like 'an API object'
44
+ it_should_behave_like 'an object with errors'
45
+ end
46
+
47
+ describe SurveyGizmo::API::Survey do
48
+ let(:create_attributes){ {:title => 'Spec', :type => 'survey', :status => 'In Design'} }
49
+ let(:get_attributes) { create_attributes.merge(:id => 1234) }
50
+ let(:update_attributes){ {:title => 'Updated'} }
51
+ let(:first_params){ {:id => 1234} }
52
+ let(:uri_paths){
53
+ h = { :create => '/survey' }
54
+ h.default = '/survey/1234'
55
+ h
56
+ }
57
+
58
+ it_should_behave_like 'an API object'
59
+ it_should_behave_like 'an object with errors'
60
+ end
61
+
62
+ describe SurveyGizmo::API::Question do
63
+ let(:create_attributes){ {:survey_id => 1234, :page_id => 1, :title => 'Spec Question', :type => 'radio', :properties => {"required" => true, "option_sort" => false} } }
64
+ let(:get_attributes) {
65
+ create_attributes.merge(:id => 1)
66
+ }
67
+ let(:update_attributes){ {:survey_id => 1234, :page_id => 1, :title => 'Updated'} }
68
+ let(:first_params){ {:id => 1, :survey_id => 1234} }
69
+ let(:uri_paths){
70
+ { :get => '/survey/1234/surveyquestion/1',
71
+ :create => '/survey/1234/surveypage/1/surveyquestion',
72
+ :update => '/survey/1234/surveypage/1/surveyquestion/1',
73
+ :delete => '/survey/1234/surveypage/1/surveyquestion/1'
74
+ }
75
+ }
76
+
77
+ it_should_behave_like 'an API object'
78
+ it_should_behave_like 'an object with errors'
79
+
80
+ it "should handle the title hash returned from the API" do
81
+ @question = described_class.new('title' => {'English' => 'Some title'})
82
+ @question.title.should == 'Some title'
83
+ end
84
+
85
+ it "should handle the _subtype key" do
86
+ @question = described_class.new(:_subtype => 'radio')
87
+ @question.type.should == 'radio'
88
+ end
89
+ end
90
+
91
+ describe SurveyGizmo::API::Option do
92
+ let(:create_attributes){ {:survey_id => 1234, :page_id => 1, :question_id => 1, :title => 'Spec Question', :value => 'Spec Answer'} }
93
+ let(:get_attributes) {
94
+ create_attributes.merge(:id => 1)
95
+ }
96
+ let(:update_attributes){ {:survey_id => 1234, :page_id => 1, :question_id => 1, :title => 'Updated'} }
97
+ let(:first_params){ {:id => 1, :survey_id => 1234, :page_id => 1, :question_id => 1} }
98
+ let(:uri_paths){
99
+ h = { :create => '/survey/1234/surveypage/1/surveyquestion/1/surveyoption' }
100
+ h.default = '/survey/1234/surveypage/1/surveyquestion/1/surveyoption/1'
101
+ h
102
+ }
103
+
104
+ it_should_behave_like 'an API object'
105
+ it_should_behave_like 'an object with errors'
106
+ end
107
+
108
+ describe SurveyGizmo::API::Page do
109
+ let(:create_attributes){ {:survey_id => 1234, :title => 'Spec Page'} }
110
+ let(:get_attributes) {
111
+ create_attributes.merge(:id => 1)
112
+ }
113
+ let(:update_attributes){ {:survey_id => 1234, :title => 'Updated'} }
114
+ let(:first_params){ {:id => 1, :survey_id => 1234 } }
115
+ let(:uri_paths){
116
+ h = { :create => '/survey/1234/surveypage' }
117
+ h.default = '/survey/1234/surveypage/1'
118
+ h
119
+ }
120
+
121
+ it_should_behave_like 'an API object'
122
+ it_should_behave_like 'an object with errors'
123
+ end
124
+ end
@@ -8,10 +8,16 @@ require "active_support/ordered_hash"
8
8
 
9
9
  # Requires supporting files with custom matchers and macros, etc,
10
10
  # in ./support/ and its subdirectories.
11
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
11
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f }
12
12
 
13
13
  RSpec.configure do |config|
14
- config.after(:all) do
14
+ config.include SurveyGizmoSpec::Methods
15
+
16
+ config.before(:each) do
17
+ @base = 'https://restapi.surveygizmo.com/v1'
18
+ end
19
+
20
+ config.after(:suite) do
15
21
  SurveyGizmoSpec.cleanup_models
16
22
  end
17
23
  end
@@ -0,0 +1,17 @@
1
+ module SurveyGizmoSpec
2
+ module Methods
3
+ def stub_api_call(method, result = true)
4
+ stub_request(method, /#{@base}/).to_return(json_response(result, {}))
5
+ end
6
+
7
+ def request_params(opts = {})
8
+ {"user:pass" => 'test@test.com:password'}.merge(opts)
9
+ end
10
+
11
+ def json_response(result, data)
12
+ body = {:result_ok => result}
13
+ result ? body.merge!(:data => data) : body.merge!(:message => data)
14
+ {:headers => {'Content-Type' => 'application/json'}, :body => body.to_json}
15
+ end
16
+ end
17
+ end
@@ -38,7 +38,7 @@ shared_examples_for 'an API object' do
38
38
 
39
39
  it "should return false if the request fails" do
40
40
  stub_request(:get, /#{@base}/).to_return(json_response(false, "something is wrong"))
41
- described_class.first(first_params).should == false
41
+ described_class.first(first_params).should == nil
42
42
  end
43
43
  end
44
44
 
@@ -103,7 +103,32 @@ shared_examples_for 'an API object' do
103
103
  end
104
104
  end
105
105
 
106
+ context '#save' do
107
+ it "should call create on a new resource" do
108
+ stub_api_call(:put)
109
+ obj = described_class.new(create_attributes)
110
+ obj.save
111
+ a_request(:put, /#{@base}#{uri_paths[:create]}/).should have_been_made
112
+ end
113
+
114
+ it "should call update on a created resource" do
115
+ obj = described_class.new(get_attributes)
116
+ obj.__send__(:clean!)
117
+ stub_api_call(:post)
118
+ obj.save
119
+ a_request(:post, /#{@base}#{uri_paths[:update]}/).should have_been_made
120
+ end
121
+ end
122
+
106
123
  context '#all' do
124
+ before(:all) do
125
+ @array = [
126
+ {:id => 1, :title => 'resource 1'},
127
+ {:id => 2, :title => 'resource 2'},
128
+ {:id => 3, :title => 'resource 3'}
129
+ ]
130
+ end
131
+
107
132
  it "should make a get request" do
108
133
  stub_request(:get, /#{@base}/).to_return(json_response(true, []))
109
134
  described_class.all(get_attributes)
@@ -111,17 +136,22 @@ shared_examples_for 'an API object' do
111
136
  end
112
137
 
113
138
  it "should create a collection using the class" do
114
- @array = [
115
- {:id => 1, :title => 'resource 1'},
116
- {:id => 2, :title => 'resource 2'},
117
- {:id => 3, :title => 'resource 3'}
118
- ]
119
-
120
139
  stub_request(:get, /#{@base}/).to_return(json_response(true, @array))
121
140
  collection = described_class.all(get_attributes)
122
141
  collection.should be_instance_of(SurveyGizmo::Collection)
123
- collection.first.should be_instance_of(described_class)
124
142
  end
143
+
144
+ it "should return instances of the class" do
145
+ stub_request(:get, /#{@base}/).to_return(json_response(true, @array))
146
+ collection = described_class.all(get_attributes)
147
+ collection.first.should be_instance_of(described_class)
148
+ end
149
+
150
+ it "should include all elements" do
151
+ stub_request(:get, /#{@base}/).to_return(json_response(true, @array))
152
+ collection = described_class.all(get_attributes)
153
+ collection.length.should == 3
154
+ end
125
155
  end
126
156
 
127
157
  end
@@ -0,0 +1,36 @@
1
+ shared_examples_for 'an object with errors' do
2
+ before(:each) do
3
+ SurveyGizmo.setup(:user => 'test@test.com', :password => 'password')
4
+ stub_request(:any, /#{@base}/).to_return(json_response(false, 'There was an error!'))
5
+ end
6
+
7
+ it "should be in zombie state if requests fail"
8
+
9
+ context "class methods" do
10
+ it { described_class.first(get_attributes).should be_nil }
11
+ it { described_class.all(get_attributes).should be_empty }
12
+ end
13
+
14
+ context "instance methods" do
15
+ before(:each) do
16
+ @obj = described_class.new(create_attributes)
17
+ end
18
+
19
+ it "should have an errors array" do
20
+ @obj.errors.should == []
21
+ end
22
+
23
+ it "should add errors on failed requests" do
24
+ @obj.save.should == false
25
+ @obj.errors.should include('There was an error!')
26
+ end
27
+
28
+ it "should empty the errors array if object gets saved" do
29
+ stub_request(:any, /#{@base}/).to_return(json_response(false, 'There was an error!'), json_response(true, get_attributes))
30
+ @obj.save.should == false
31
+ @obj.errors.should_not be_empty
32
+ @obj.save.should == true
33
+ @obj.errors.should be_empty
34
+ end
35
+ end
36
+ end
@@ -1,10 +1,6 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
- describe "SurveyGizmo" do
4
- before(:each) do
5
- @base = 'https://restapi.surveygizmo.com/v1'
6
- end
7
-
3
+ describe "SurveyGizmo" do
8
4
  it "should have a base uri" do
9
5
  SurveyGizmo.base_uri.should == 'https://restapi.surveygizmo.com/v1'
10
6
  end
@@ -14,127 +10,7 @@ describe "SurveyGizmo" do
14
10
  SurveyGizmo.default_options[:default_params].should == {'user:pass' => 'test@test.com:password'}
15
11
  end
16
12
 
17
- it "should raise an error if auth isn't configured"
18
-
19
- describe SurveyGizmo::Resource do
20
- before(:each) do
21
- SurveyGizmo.setup(:user => 'test@test.com', :password => 'password')
22
- end
23
-
24
- let(:described_class) { SurveyGizmoSpec::ResourceTest }
25
-
26
- let(:create_attributes){ {:title => 'Spec', :test_id => 5} }
27
- let(:get_attributes) { create_attributes.merge(:id => 1) }
28
- let(:update_attributes){ {:title => 'Updated'} }
29
- let(:first_params){ {:id => 1} }
30
- let(:uri_paths){
31
- {
32
- :get => '/test/1',
33
- :create => '/test/5/resource',
34
- :update => '/test/5/resource/1',
35
- :delete => '/test/5/resource/1'
36
- }
37
- }
38
-
39
- it "#new?" do
40
- described_class.new.should be_new
41
- end
42
-
43
-
44
- it '#reload' do
45
- stub_request(:get, /#{@base}/).to_return(json_response(true, get_attributes))
46
- obj = described_class.new(create_attributes)
47
- obj.attributes.reject{|k,v| v.blank? }.should == create_attributes
48
- obj.reload
49
- obj.attributes.reject{|k,v| v.blank? }.should == get_attributes
50
- end
51
-
52
- it '#valid?'
53
- it "should be in zombie state if requests fail"
54
-
55
- it "should track descendants" do
56
- SurveyGizmo::Resource.descendants.should include(SurveyGizmoSpec::ResourceTest)
57
- end
58
-
59
- it_should_behave_like 'an API object'
60
- end
61
-
62
- describe SurveyGizmo::API::Survey do
63
- let(:create_attributes){ {:title => 'Spec', :type => 'survey', :status => 'In Design'} }
64
- let(:get_attributes) { create_attributes.merge(:id => 1234) }
65
- let(:update_attributes){ {:title => 'Updated'} }
66
- let(:first_params){ {:id => 1234} }
67
- let(:uri_paths){
68
- h = { :create => '/survey' }
69
- h.default = '/survey/1234'
70
- h
71
- }
72
-
73
- it_should_behave_like 'an API object'
74
- end
75
-
76
- describe SurveyGizmo::API::Question do
77
- let(:create_attributes){ {:survey_id => 1234, :page_id => 1, :title => 'Spec Question', :type => 'radio', :properties => {"required" => true, "option_sort" => false} } }
78
- let(:get_attributes) {
79
- create_attributes.merge(:id => 1)
80
- }
81
- let(:update_attributes){ {:survey_id => 1234, :page_id => 1, :title => 'Updated'} }
82
- let(:first_params){ {:id => 1, :survey_id => 1234} }
83
- let(:uri_paths){
84
- { :get => '/survey/1234/surveyquestion/1',
85
- :create => '/survey/1234/surveypage/1/surveyquestion',
86
- :update => '/survey/1234/surveypage/1/surveyquestion/1',
87
- :delete => '/survey/1234/surveypage/1/surveyquestion/1'
88
- }
89
- }
90
-
91
- it_should_behave_like 'an API object'
92
-
93
- it "should handle the title hash returned from the API" do
94
- @question = described_class.new('title' => {'English' => 'Some title'})
95
- @question.title.should == 'Some title'
96
- end
97
-
98
- it "should handle the _subtype key" do
99
- @question = described_class.new(:_subtype => 'radio')
100
- @question.type.should == 'radio'
101
- end
102
- end
103
-
104
- describe SurveyGizmo::API::Option do
105
- let(:create_attributes){ {:survey_id => 1234, :page_id => 1, :question_id => 1, :title => 'Spec Question', :value => 'Spec Answer'} }
106
- let(:get_attributes) {
107
- create_attributes.merge(:id => 1)
108
- }
109
- let(:update_attributes){ {:survey_id => 1234, :page_id => 1, :question_id => 1, :title => 'Updated'} }
110
- let(:first_params){ {:id => 1, :survey_id => 1234, :page_id => 1, :question_id => 1} }
111
- let(:uri_paths){
112
- h = { :create => '/survey/1234/surveypage/1/surveyquestion/1/surveyoption' }
113
- h.default = '/survey/1234/surveypage/1/surveyquestion/1/surveyoption/1'
114
- h
115
- }
116
-
117
- it_should_behave_like 'an API object'
118
-
119
- end
120
-
121
- describe SurveyGizmo::API::Page do
122
- let(:create_attributes){ {:survey_id => 1234, :title => 'Spec Page'} }
123
- let(:get_attributes) {
124
- create_attributes.merge(:id => 1)
125
- }
126
- let(:update_attributes){ {:survey_id => 1234, :title => 'Updated'} }
127
- let(:first_params){ {:id => 1, :survey_id => 1234 } }
128
- let(:uri_paths){
129
- h = { :create => '/survey/1234/surveypage' }
130
- h.default = '/survey/1234/surveypage/1'
131
- h
132
- }
133
-
134
- it_should_behave_like 'an API object'
135
-
136
- end
137
-
13
+ it "should raise an error if auth isn't configured"
138
14
 
139
15
  describe "Collection" do
140
16
  before(:each) do
@@ -226,19 +102,5 @@ describe "SurveyGizmo" do
226
102
  obj.resources.last.generic_resources.first.should be_instance_of(SurveyGizmoSpec::GenericResource)
227
103
  end
228
104
  end
229
- end
230
-
231
- def stub_api_call(method, result = true)
232
- stub_request(method, /#{@base}/).to_return(json_response(result, {}))
233
- end
234
-
235
- def request_params(opts = {})
236
- {"user:pass" => 'test@test.com:password'}.merge(opts)
237
- end
238
-
239
- def json_response(result, data)
240
- body = {:result_ok => result}
241
- result ? body.merge!(:data => data) : body.merge!(:message => data)
242
- {:headers => {'Content-Type' => 'application/json'}, :body => body.to_json}
243
- end
105
+ end
244
106
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: survey-gizmo-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-30 00:00:00.000000000Z
12
+ date: 2011-12-13 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70260063096500 !ruby/object:Gem::Requirement
16
+ requirement: &70195630027920 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: 3.0.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70260063096500
24
+ version_requirements: *70195630027920
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: i18n
27
- requirement: &70260063389380 !ruby/object:Gem::Requirement
27
+ requirement: &70195630026500 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70260063389380
35
+ version_requirements: *70195630026500
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: virtus
38
- requirement: &70260063597440 !ruby/object:Gem::Requirement
38
+ requirement: &70195630025000 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.0.5
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70260063597440
46
+ version_requirements: *70195630025000
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: httparty
49
- requirement: &70260063748800 !ruby/object:Gem::Requirement
49
+ requirement: &70195630006520 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,21 +54,32 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70260063748800
57
+ version_requirements: *70195630006520
58
+ - !ruby/object:Gem::Dependency
59
+ name: bluecloth
60
+ requirement: &70195630005200 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70195630005200
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: yard
60
- requirement: &70260064153320 !ruby/object:Gem::Requirement
71
+ requirement: &70195630002980 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ~>
64
75
  - !ruby/object:Gem::Version
65
- version: 0.6.0
76
+ version: 0.7.0
66
77
  type: :development
67
78
  prerelease: false
68
- version_requirements: *70260064153320
79
+ version_requirements: *70195630002980
69
80
  - !ruby/object:Gem::Dependency
70
81
  name: bundler
71
- requirement: &70260065755920 !ruby/object:Gem::Requirement
82
+ requirement: &70195629996380 !ruby/object:Gem::Requirement
72
83
  none: false
73
84
  requirements:
74
85
  - - ~>
@@ -76,10 +87,10 @@ dependencies:
76
87
  version: 1.0.0
77
88
  type: :development
78
89
  prerelease: false
79
- version_requirements: *70260065755920
90
+ version_requirements: *70195629996380
80
91
  - !ruby/object:Gem::Dependency
81
92
  name: jeweler
82
- requirement: &70260067262120 !ruby/object:Gem::Requirement
93
+ requirement: &70195629994020 !ruby/object:Gem::Requirement
83
94
  none: false
84
95
  requirements:
85
96
  - - ~>
@@ -87,7 +98,7 @@ dependencies:
87
98
  version: 1.6.4
88
99
  type: :development
89
100
  prerelease: false
90
- version_requirements: *70260067262120
101
+ version_requirements: *70195629994020
91
102
  description: ''
92
103
  email: self@ripthejacker.com
93
104
  executables: []
@@ -106,13 +117,17 @@ files:
106
117
  - lib/survey_gizmo/api/option.rb
107
118
  - lib/survey_gizmo/api/page.rb
108
119
  - lib/survey_gizmo/api/question.rb
120
+ - lib/survey_gizmo/api/response.rb
109
121
  - lib/survey_gizmo/api/survey.rb
110
122
  - lib/survey_gizmo/collection.rb
111
123
  - lib/survey_gizmo/resource.rb
112
124
  - lib/survey_gizmo/survey_gizmo.rb
125
+ - spec/resource_spec.rb
113
126
  - spec/spec_helper.rb
127
+ - spec/support/methods.rb
114
128
  - spec/support/model_cleanup.rb
115
129
  - spec/support/spec_shared_api_object.rb
130
+ - spec/support/spec_shared_object_with_errors.rb
116
131
  - spec/support/test_resource_classes.rb
117
132
  - spec/survey-gizmo-ruby_spec.rb
118
133
  - spec/test_json/page.json
@@ -133,7 +148,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
133
148
  version: '0'
134
149
  segments:
135
150
  - 0
136
- hash: -2566715168940454907
151
+ hash: -3511147689201295286
137
152
  required_rubygems_version: !ruby/object:Gem::Requirement
138
153
  none: false
139
154
  requirements: