survey-gizmo-ruby 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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: