spark_api 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/History.txt +12 -0
  2. data/README.md +7 -0
  3. data/Rakefile +1 -0
  4. data/VERSION +1 -1
  5. data/lib/spark_api/authentication.rb +0 -3
  6. data/lib/spark_api/authentication/oauth2.rb +1 -1
  7. data/lib/spark_api/configuration.rb +6 -1
  8. data/lib/spark_api/models.rb +6 -2
  9. data/lib/spark_api/models/activity.rb +10 -0
  10. data/lib/spark_api/models/base.rb +25 -5
  11. data/lib/spark_api/models/comment.rb +9 -0
  12. data/lib/spark_api/models/concerns/destroyable.rb +1 -1
  13. data/lib/spark_api/models/concerns/savable.rb +3 -6
  14. data/lib/spark_api/models/contact.rb +38 -1
  15. data/lib/spark_api/models/dirty.rb +1 -1
  16. data/lib/spark_api/models/fields.rb +12 -0
  17. data/lib/spark_api/models/listing_cart.rb +6 -34
  18. data/lib/spark_api/models/portal.rb +37 -0
  19. data/lib/spark_api/models/saved_search.rb +36 -0
  20. data/lib/spark_api/models/vow_account.rb +44 -0
  21. data/lib/spark_api/request.rb +1 -1
  22. data/spec/fixtures/activities/get.json +22 -0
  23. data/spec/fixtures/base.json +2 -2
  24. data/spec/fixtures/comments/get.json +32 -0
  25. data/spec/fixtures/comments/new.json +7 -0
  26. data/spec/fixtures/comments/post.json +19 -0
  27. data/spec/fixtures/contacts/my.json +1 -0
  28. data/spec/fixtures/contacts/vow_accounts/edit.json +5 -0
  29. data/spec/fixtures/contacts/vow_accounts/get.json +15 -0
  30. data/spec/fixtures/contacts/vow_accounts/new.json +12 -0
  31. data/spec/fixtures/contacts/vow_accounts/post.json +10 -0
  32. data/spec/fixtures/fields/order.json +22 -0
  33. data/spec/fixtures/fields/order_a.json +39 -0
  34. data/spec/fixtures/portal/disable.json +5 -0
  35. data/spec/fixtures/portal/enable.json +5 -0
  36. data/spec/fixtures/portal/my.json +15 -0
  37. data/spec/fixtures/portal/my_non_existant.json +6 -0
  38. data/spec/fixtures/portal/new.json +7 -0
  39. data/spec/fixtures/portal/post.json +10 -0
  40. data/spec/fixtures/saved_searches/get.json +4 -1
  41. data/spec/spec_helper.rb +11 -7
  42. data/spec/unit/spark_api/authentication/oauth2_impl/faraday_middleware_spec.rb +2 -2
  43. data/spec/unit/spark_api/authentication/oauth2_impl/grant_type_base_spec.rb +1 -2
  44. data/spec/unit/spark_api/authentication/oauth2_spec.rb +3 -4
  45. data/spec/unit/spark_api/models/activity_spec.rb +29 -0
  46. data/spec/unit/spark_api/models/base_spec.rb +23 -0
  47. data/spec/unit/spark_api/models/concerns/destroyable_spec.rb +1 -1
  48. data/spec/unit/spark_api/models/concerns/savable_spec.rb +8 -4
  49. data/spec/unit/spark_api/models/contact_spec.rb +144 -21
  50. data/spec/unit/spark_api/models/fields_spec.rb +56 -0
  51. data/spec/unit/spark_api/models/listing_cart_spec.rb +1 -1
  52. data/spec/unit/spark_api/models/portal_spec.rb +50 -0
  53. data/spec/unit/spark_api/models/saved_search_spec.rb +60 -0
  54. data/spec/unit/spark_api/models/shared_listing_spec.rb +1 -1
  55. data/spec/unit/spark_api/models/vow_account_spec.rb +64 -0
  56. data/spec/unit/spark_api/request_spec.rb +1 -1
  57. data/spec/unit/spark_api_spec.rb +1 -1
  58. metadata +362 -360
  59. data/lib/spark_api/models/subscription.rb +0 -52
  60. data/spec/fixtures/subscriptions/get.json +0 -19
  61. data/spec/fixtures/subscriptions/new.json +0 -13
  62. data/spec/fixtures/subscriptions/post.json +0 -10
  63. data/spec/fixtures/subscriptions/put.json +0 -12
  64. data/spec/fixtures/subscriptions/subscribe.json +0 -5
  65. data/spec/fixtures/subscriptions/update.json +0 -6
  66. data/spec/json_hash_test_support.rb +0 -251
  67. data/spec/json_helper.rb +0 -76
  68. data/spec/mock_helper.rb +0 -132
  69. data/spec/oauth2_helper.rb +0 -70
  70. data/spec/unit/spark_api/models/subscription_spec.rb +0 -106
@@ -1,52 +0,0 @@
1
- module SparkApi
2
- module Models
3
-
4
- class Subscription < Base
5
- extend Finders
6
- include Concerns::Savable,
7
- Concerns::Destroyable
8
-
9
- self.element_name = "subscriptions"
10
-
11
- # list subscribers (private role)
12
- def subscribers
13
- return {} unless persisted?
14
- results = connection.get("#{self.class.path}/#{@attributes["Id"]}/subscribers")
15
- @attributes['RecipientIds'] = results.first['RecipientIds']
16
- results
17
- end
18
-
19
- # subscribe/unsubscribe contact (private role)
20
- [:subscribe, :unsubscribe].each do |action|
21
- method = (action == :subscribe ? :put : :delete)
22
- define_method(action) do |contact|
23
- return false unless persisted?
24
- self.errors = []
25
- contact_id = contact.is_a?(Contact) ? contact.Id : contact
26
- begin
27
- connection.send(method, "#{self.class.path}/#{@attributes["Id"]}/subscribers/#{contact_id}")
28
- rescue BadResourceRequest, NotFound => e
29
- self.errors << { :code => e.code, :message => e.message }
30
- SparkApi.logger.error("Failed to #{action} contact #{contact}: #{e.message}")
31
- return false
32
- end
33
- update_recipients(action, contact_id)
34
- true
35
- end
36
- end
37
-
38
- private
39
-
40
- def update_recipients(method, contact_id)
41
- @attributes['RecipientIds'] = [] if @attributes['RecipientIds'].nil?
42
- if method == :subscribe
43
- @attributes['RecipientIds'] << contact_id
44
- else
45
- @attributes['RecipientIds'].delete contact_id
46
- end
47
- end
48
-
49
- end
50
-
51
- end
52
- end
@@ -1,19 +0,0 @@
1
- {
2
- "D": {
3
- "Success": true,
4
- "Results": [
5
- {
6
- "Id":"20101230223226074204000000",
7
- "ResourceUri":"/v1/contacts/20101230223226074204000000",
8
- "Name":"First subscription",
9
- "RecipientIds": ["20101230223226074307000000"]
10
- },
11
- {
12
- "Id":"20101230223226074205000000",
13
- "ResourceUri":"/v1/contacts/20101230223226074205000000",
14
- "Name":"Second subscription",
15
- "RecipientIds": []
16
- }
17
- ]
18
- }
19
- }
@@ -1,13 +0,0 @@
1
- {
2
- "D": {
3
- "Subscriptions": [
4
- {
5
- "Name":"A new subscription name",
6
- "SearchId":"20101230223226074204000000",
7
- "RecipientIds": ["20101230223226074204000000"],
8
- "Subject": "my subject",
9
- "Message": "my message"
10
- }
11
- ]
12
- }
13
- }
@@ -1,10 +0,0 @@
1
- {
2
- "D": {
3
- "Success": true,
4
- "Results": [
5
- {
6
- "ResourceUri":"/v1/subscriptions/20101230223226074204000000"
7
- }
8
- ]
9
- }
10
- }
@@ -1,12 +0,0 @@
1
- {
2
- "D": {
3
- "Success": true,
4
- "Results": [
5
- {
6
- "Id":"20101230223226074204000000",
7
- "ResourceUri":"/v1/contacts/20101230223226074204000000",
8
- "Name":"A new subscription name"
9
- }
10
- ]
11
- }
12
- }
@@ -1,5 +0,0 @@
1
- {
2
- "D":{
3
- "Success":true
4
- }
5
- }
@@ -1,6 +0,0 @@
1
- {
2
- "D": {
3
- "Name":"A new subscription name"
4
- }
5
- }
6
-
@@ -1,251 +0,0 @@
1
- # Several workarounds to get our test setup working in multiple ruby environments credit is
2
- # attributed to all the projects that found solutions to these test headaches!
3
-
4
-
5
- module SparkApiTest
6
- # directly taken from Rails 3.1's OrderedHash
7
- # see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/ordered_hash.rb
8
-
9
- # The order of iteration over hashes in Ruby 1.8 is undefined. For example, you do not know the
10
- # order in which +keys+ will return keys, or +each+ yield pairs. <tt>ActiveSupport::OrderedHash</tt>
11
- # implements a hash that preserves insertion order, as in Ruby 1.9:
12
- #
13
- # oh = ActiveSupport::OrderedHash.new
14
- # oh[:a] = 1
15
- # oh[:b] = 2
16
- # oh.keys # => [:a, :b], this order is guaranteed
17
- #
18
- # <tt>ActiveSupport::OrderedHash</tt> is namespaced to prevent conflicts with other implementations.
19
- class OrderedHash < ::Hash #:nodoc:
20
- def to_yaml_type
21
- "!tag:yaml.org,2002:omap"
22
- end
23
-
24
- def encode_with(coder)
25
- coder.represent_seq '!omap', map { |k,v| { k => v } }
26
- end
27
-
28
- def to_yaml(opts = {})
29
- if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck?
30
- return super
31
- end
32
-
33
- YAML.quick_emit(self, opts) do |out|
34
- out.seq(taguri) do |seq|
35
- each do |k, v|
36
- seq.add(k => v)
37
- end
38
- end
39
- end
40
- end
41
-
42
- def nested_under_indifferent_access
43
- self
44
- end
45
-
46
- # Hash is ordered in Ruby 1.9!
47
- if RUBY_VERSION < '1.9'
48
-
49
- # In MRI the Hash class is core and written in C. In particular, methods are
50
- # programmed with explicit C function calls and polymorphism is not honored.
51
- #
52
- # For example, []= is crucial in this implementation to maintain the @keys
53
- # array but hash.c invokes rb_hash_aset() originally. This prevents method
54
- # reuse through inheritance and forces us to reimplement stuff.
55
- #
56
- # For instance, we cannot use the inherited #merge! because albeit the algorithm
57
- # itself would work, our []= is not being called at all by the C code.
58
-
59
- def initialize(*args, &block)
60
- super
61
- @keys = []
62
- end
63
-
64
- def self.[](*args)
65
- ordered_hash = new
66
-
67
- if (args.length == 1 && args.first.is_a?(Array))
68
- args.first.each do |key_value_pair|
69
- next unless (key_value_pair.is_a?(Array))
70
- ordered_hash[key_value_pair[0]] = key_value_pair[1]
71
- end
72
-
73
- return ordered_hash
74
- end
75
-
76
- unless (args.size % 2 == 0)
77
- raise ArgumentError.new("odd number of arguments for Hash")
78
- end
79
-
80
- args.each_with_index do |val, ind|
81
- next if (ind % 2 != 0)
82
- ordered_hash[val] = args[ind + 1]
83
- end
84
-
85
- ordered_hash
86
- end
87
-
88
- def initialize_copy(other)
89
- super
90
- # make a deep copy of keys
91
- @keys = other.keys
92
- end
93
-
94
- def []=(key, value)
95
- @keys << key unless has_key?(key)
96
- super
97
- end
98
-
99
- def delete(key)
100
- if has_key? key
101
- index = @keys.index(key)
102
- @keys.delete_at index
103
- end
104
- super
105
- end
106
-
107
- def delete_if
108
- super
109
- sync_keys!
110
- self
111
- end
112
-
113
- def reject!
114
- super
115
- sync_keys!
116
- self
117
- end
118
-
119
- def reject(&block)
120
- dup.reject!(&block)
121
- end
122
-
123
- def keys
124
- @keys.dup
125
- end
126
-
127
- def values
128
- @keys.collect { |key| self[key] }
129
- end
130
-
131
- def to_hash
132
- self
133
- end
134
-
135
- def to_a
136
- @keys.map { |key| [ key, self[key] ] }
137
- end
138
-
139
- def each_key
140
- return to_enum(:each_key) unless block_given?
141
- @keys.each { |key| yield key }
142
- self
143
- end
144
-
145
- def each_value
146
- return to_enum(:each_value) unless block_given?
147
- @keys.each { |key| yield self[key]}
148
- self
149
- end
150
-
151
- def each
152
- return to_enum(:each) unless block_given?
153
- @keys.each {|key| yield [key, self[key]]}
154
- self
155
- end
156
-
157
- alias_method :each_pair, :each
158
-
159
- alias_method :select, :find_all
160
-
161
- def clear
162
- super
163
- @keys.clear
164
- self
165
- end
166
-
167
- def shift
168
- k = @keys.first
169
- v = delete(k)
170
- [k, v]
171
- end
172
-
173
- def merge!(other_hash)
174
- if block_given?
175
- other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
176
- else
177
- other_hash.each { |k, v| self[k] = v }
178
- end
179
- self
180
- end
181
-
182
- alias_method :update, :merge!
183
-
184
- def merge(other_hash, &block)
185
- dup.merge!(other_hash, &block)
186
- end
187
-
188
- # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
189
- def replace(other)
190
- super
191
- @keys = other.keys
192
- self
193
- end
194
-
195
- def invert
196
- OrderedHash[self.to_a.map!{|key_value_pair| key_value_pair.reverse}]
197
- end
198
-
199
- private
200
- def sync_keys!
201
- @keys.delete_if {|k| !has_key?(k)}
202
- end
203
- end
204
- end
205
- end
206
-
207
- # Originally based on a fix found in Koala, a facebook client gem that has compatibile licensing.
208
- # See: https://raw.github.com/arsduo/koala/master/spec/support/json_testing_fix.rb
209
- #
210
- # when testing across Ruby versions, we found that JSON string creation inconsistently ordered keys
211
- # which is a problem because our mock testing service ultimately matches strings to see if requests are mocked
212
- # this fix solves that problem by ensuring all hashes are created with a consistent key order every time
213
- module MultiJson
214
-
215
- class << self
216
- def dump_with_ordering(object)
217
- # if it's a hash, recreate it with k/v pairs inserted in sorted-by-key order
218
- # (for some reason, REE fails if we don't assign the ternary result as a local variable
219
- # separately from calling encode_original)
220
- dump_original(sort_object(object))
221
- end
222
-
223
- alias_method :dump_original, :dump
224
- alias_method :dump, :dump_with_ordering
225
-
226
- def load_with_ordering(string)
227
- sort_object(load_original(string))
228
- end
229
-
230
- alias_method :load_original, :load
231
- alias_method :load, :load_with_ordering
232
-
233
- private
234
-
235
- def sort_object(object)
236
- if object.is_a?(Hash)
237
- sort_hash(object)
238
- elsif object.is_a?(Array)
239
- object.collect {|item| item.is_a?(Hash) ? sort_hash(item) : item}
240
- else
241
- object
242
- end
243
- end
244
-
245
- def sort_hash(unsorted_hash)
246
- sorted_hash = SparkApiTest::OrderedHash.new(sorted_hash)
247
- unsorted_hash.keys.sort {|a, b| a.to_s <=> b.to_s}.inject(sorted_hash) {|hash, k| hash[k] = unsorted_hash[k]; hash}
248
- end
249
- end
250
- end
251
-
@@ -1,76 +0,0 @@
1
- class ListingJson
2
- @counter = 0
3
- def self.next_tech_id()
4
- "#{@counter + 20110101000000000000}000000"
5
- end
6
- def self.next_list_id()
7
- "06-#{@counter + 1000}"
8
- end
9
- def self.bump()
10
- @counter += 1
11
- end
12
-
13
- def self.create
14
- bump
15
- json = <<-JSON
16
- {
17
- "ResourceUri": "/v1/listings/#{next_tech_id}",
18
- "StandardFields": #{standard_fields},
19
- "Id": "#{next_tech_id}"
20
- }
21
- JSON
22
-
23
- end
24
-
25
- def self.create_all(count = 1)
26
- listings = []
27
- count.times { listings << create }
28
- json = listings * ","
29
- end
30
-
31
- private
32
- def self.standard_fields
33
- json = <<-JSON
34
- {
35
- "StreetNumber": "7298",
36
- "Longitude": "-116.3237",
37
- "City": "Bonners Ferry",
38
- "ListingId": "#{next_list_id}",
39
- "PublicRemarks": "Afforadable home in town close to hospital,yet quiet country like setting. Good views. Must see",
40
- "BuildingAreaTotal": 924.0,
41
- "YearBuilt": 1977,
42
- "StreetName": "BIRCH",
43
- "ListPrice": 50000.0,
44
- "PostalCode": 83805,
45
- "Latitude": "48.7001",
46
- "BathsThreeQuarter": null,
47
- "BathsFull": 1.0,
48
- "BathsTotal": 1.0,
49
- "StateOrProvince": "ID",
50
- "PropertyType": "A",
51
- "StreetAdditionalInfo": null,
52
- "StreetDirPrefix": null,
53
- "BedsTotal": 3,
54
- "StreetDirSuffix": null,
55
- "ListingKey": "#{next_tech_id}",
56
- "ListOfficeName": "Century 21 On The Lake",
57
- "BathsHalf": null,
58
- "ModificationTimestamp": "2010-11-22T20:47:21Z",
59
- "CountyOrParish": "Boundary"
60
- }
61
- JSON
62
- end
63
-
64
- end
65
-
66
- def paginate_json(current_page = 1)
67
- json = <<-JSON
68
- "Pagination": {
69
- "TotalRows": 38,
70
- "PageSize": 10,
71
- "TotalPages": 4,
72
- "CurrentPage": #{current_page}
73
- }
74
- JSON
75
- end
76
-