tagcrumbs 0.3.1

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.
Files changed (178) hide show
  1. data/History.txt +9 -0
  2. data/License.txt +22 -0
  3. data/Manifest.txt +177 -0
  4. data/PostInstall.txt +2 -0
  5. data/README.rdoc +45 -0
  6. data/Rakefile +35 -0
  7. data/TODO.txt +17 -0
  8. data/bin/tagcrumbs +5 -0
  9. data/examples/address_update.rb +15 -0
  10. data/examples/comment_new.rb +19 -0
  11. data/examples/favorite_new.rb +17 -0
  12. data/examples/filter_new.rb +15 -0
  13. data/examples/friendship_create.rb +19 -0
  14. data/examples/link_new.rb +16 -0
  15. data/examples/location_update.rb +16 -0
  16. data/examples/picture_update.rb +16 -0
  17. data/examples/placemark_new_simple.rb +24 -0
  18. data/examples/placemark_new_suggestions.rb +24 -0
  19. data/examples/profile_link_new.rb +14 -0
  20. data/examples/profile_update.rb +12 -0
  21. data/examples/request_authorization.rb +25 -0
  22. data/examples/settings_update.rb +12 -0
  23. data/examples/subscription_new.rb +15 -0
  24. data/examples/tagcrumbs_find.rb +25 -0
  25. data/examples/tagcrumbs_search.rb +7 -0
  26. data/examples/user.rb +28 -0
  27. data/examples/user_recommendation_new.rb +15 -0
  28. data/lib/tagcrumbs/builders/builder.rb +45 -0
  29. data/lib/tagcrumbs/builders/json_builder.rb +38 -0
  30. data/lib/tagcrumbs/builders/xml_builder.rb +30 -0
  31. data/lib/tagcrumbs/cli.rb +268 -0
  32. data/lib/tagcrumbs/config_store.rb +35 -0
  33. data/lib/tagcrumbs/exceptions.rb +13 -0
  34. data/lib/tagcrumbs/node.rb +43 -0
  35. data/lib/tagcrumbs/parsers/json_parser.rb +79 -0
  36. data/lib/tagcrumbs/parsers/parser.rb +24 -0
  37. data/lib/tagcrumbs/parsers/xml_parser.rb +54 -0
  38. data/lib/tagcrumbs/proxy.rb +32 -0
  39. data/lib/tagcrumbs/requestor.rb +140 -0
  40. data/lib/tagcrumbs/resources/array.rb +108 -0
  41. data/lib/tagcrumbs/resources/models/accessors.rb +252 -0
  42. data/lib/tagcrumbs/resources/models/activity.rb +19 -0
  43. data/lib/tagcrumbs/resources/models/address.rb +16 -0
  44. data/lib/tagcrumbs/resources/models/city.rb +13 -0
  45. data/lib/tagcrumbs/resources/models/comment.rb +12 -0
  46. data/lib/tagcrumbs/resources/models/country.rb +15 -0
  47. data/lib/tagcrumbs/resources/models/fanship.rb +12 -0
  48. data/lib/tagcrumbs/resources/models/favorite.rb +22 -0
  49. data/lib/tagcrumbs/resources/models/filter.rb +32 -0
  50. data/lib/tagcrumbs/resources/models/flag.rb +10 -0
  51. data/lib/tagcrumbs/resources/models/friendship.rb +12 -0
  52. data/lib/tagcrumbs/resources/models/geoname.rb +8 -0
  53. data/lib/tagcrumbs/resources/models/link.rb +13 -0
  54. data/lib/tagcrumbs/resources/models/location.rb +13 -0
  55. data/lib/tagcrumbs/resources/models/model.rb +148 -0
  56. data/lib/tagcrumbs/resources/models/picture.rb +28 -0
  57. data/lib/tagcrumbs/resources/models/place.rb +17 -0
  58. data/lib/tagcrumbs/resources/models/placemark.rb +30 -0
  59. data/lib/tagcrumbs/resources/models/profile.rb +16 -0
  60. data/lib/tagcrumbs/resources/models/profile_link.rb +12 -0
  61. data/lib/tagcrumbs/resources/models/root.rb +19 -0
  62. data/lib/tagcrumbs/resources/models/settings.rb +14 -0
  63. data/lib/tagcrumbs/resources/models/state.rb +14 -0
  64. data/lib/tagcrumbs/resources/models/subscription.rb +13 -0
  65. data/lib/tagcrumbs/resources/models/suggestions.rb +11 -0
  66. data/lib/tagcrumbs/resources/models/tag.rb +6 -0
  67. data/lib/tagcrumbs/resources/models/tagcrumb.rb +58 -0
  68. data/lib/tagcrumbs/resources/models/user.rb +101 -0
  69. data/lib/tagcrumbs/resources/models/user_recommendation.rb +18 -0
  70. data/lib/tagcrumbs/resources/resource.rb +76 -0
  71. data/lib/tagcrumbs/validations.rb +301 -0
  72. data/lib/tagcrumbs.rb +232 -0
  73. data/script/console +10 -0
  74. data/script/destroy +14 -0
  75. data/script/generate +14 -0
  76. data/spec/fixtures/activity.json +210 -0
  77. data/spec/fixtures/activity.xml +66 -0
  78. data/spec/fixtures/address.json +183 -0
  79. data/spec/fixtures/address.xml +58 -0
  80. data/spec/fixtures/city.json +88 -0
  81. data/spec/fixtures/city.xml +34 -0
  82. data/spec/fixtures/comment.json +286 -0
  83. data/spec/fixtures/comment.xml +87 -0
  84. data/spec/fixtures/country.json +32 -0
  85. data/spec/fixtures/country.xml +13 -0
  86. data/spec/fixtures/fanship.json +180 -0
  87. data/spec/fixtures/fanship.xml +54 -0
  88. data/spec/fixtures/favorite.json +332 -0
  89. data/spec/fixtures/favorite.xml +109 -0
  90. data/spec/fixtures/filter.json +243 -0
  91. data/spec/fixtures/filter.xml +80 -0
  92. data/spec/fixtures/friendship.json +180 -0
  93. data/spec/fixtures/friendship.xml +54 -0
  94. data/spec/fixtures/geoname.json +18 -0
  95. data/spec/fixtures/geoname.xml +6 -0
  96. data/spec/fixtures/json_parser.json +25 -0
  97. data/spec/fixtures/link.json +288 -0
  98. data/spec/fixtures/link.xml +88 -0
  99. data/spec/fixtures/location.json +204 -0
  100. data/spec/fixtures/location.xml +71 -0
  101. data/spec/fixtures/picture.json +154 -0
  102. data/spec/fixtures/picture.png +0 -0
  103. data/spec/fixtures/picture.xml +49 -0
  104. data/spec/fixtures/placemark.json +357 -0
  105. data/spec/fixtures/placemark.xml +58 -0
  106. data/spec/fixtures/placemarks.json +887 -0
  107. data/spec/fixtures/placemarks.xml +348 -0
  108. data/spec/fixtures/profile.json +282 -0
  109. data/spec/fixtures/profile.xml +100 -0
  110. data/spec/fixtures/profile_link.json +156 -0
  111. data/spec/fixtures/profile_link.xml +49 -0
  112. data/spec/fixtures/root.json +46 -0
  113. data/spec/fixtures/root.xml +14 -0
  114. data/spec/fixtures/settings.json +147 -0
  115. data/spec/fixtures/settings.xml +45 -0
  116. data/spec/fixtures/state.json +62 -0
  117. data/spec/fixtures/state.xml +23 -0
  118. data/spec/fixtures/subscription.json +283 -0
  119. data/spec/fixtures/subscription.xml +86 -0
  120. data/spec/fixtures/suggestions.json +1877 -0
  121. data/spec/fixtures/suggestions.xml +724 -0
  122. data/spec/fixtures/tag.json +9 -0
  123. data/spec/fixtures/tag.xml +4 -0
  124. data/spec/fixtures/user.json +105 -0
  125. data/spec/fixtures/user.xml +31 -0
  126. data/spec/fixtures/user_recommendation.json +349 -0
  127. data/spec/fixtures/user_recommendation.xml +106 -0
  128. data/spec/fixtures/validation_errors.json +5 -0
  129. data/spec/fixtures/validation_errors.xml +5 -0
  130. data/spec/fixtures/xml_parser.xml +13 -0
  131. data/spec/spec.opts +1 -0
  132. data/spec/spec_helper.rb +75 -0
  133. data/spec/tagcrumbs/builders/builder_spec.rb +57 -0
  134. data/spec/tagcrumbs/builders/json_builder_spec.rb +47 -0
  135. data/spec/tagcrumbs/builders/xml_builder_spec.rb +34 -0
  136. data/spec/tagcrumbs/exceptions_spec.rb +16 -0
  137. data/spec/tagcrumbs/node_spec.rb +42 -0
  138. data/spec/tagcrumbs/parsers/json_parser_spec.rb +117 -0
  139. data/spec/tagcrumbs/parsers/parser_spec.rb +25 -0
  140. data/spec/tagcrumbs/parsers/xml_parser_spec.rb +117 -0
  141. data/spec/tagcrumbs/proxy_spec.rb +48 -0
  142. data/spec/tagcrumbs/requestor_spec.rb +62 -0
  143. data/spec/tagcrumbs/resources/array_spec.rb +62 -0
  144. data/spec/tagcrumbs/resources/models/accessors_spec.rb +123 -0
  145. data/spec/tagcrumbs/resources/models/activity_spec.rb +33 -0
  146. data/spec/tagcrumbs/resources/models/address_spec.rb +24 -0
  147. data/spec/tagcrumbs/resources/models/city_spec.rb +33 -0
  148. data/spec/tagcrumbs/resources/models/comment_spec.rb +23 -0
  149. data/spec/tagcrumbs/resources/models/country_spec.rb +26 -0
  150. data/spec/tagcrumbs/resources/models/fanship_spec.rb +28 -0
  151. data/spec/tagcrumbs/resources/models/favorite_spec.rb +28 -0
  152. data/spec/tagcrumbs/resources/models/filter_spec.rb +43 -0
  153. data/spec/tagcrumbs/resources/models/flag_spec.rb +5 -0
  154. data/spec/tagcrumbs/resources/models/friendship_spec.rb +28 -0
  155. data/spec/tagcrumbs/resources/models/geoname_spec.rb +18 -0
  156. data/spec/tagcrumbs/resources/models/link_spec.rb +24 -0
  157. data/spec/tagcrumbs/resources/models/location_spec.rb +28 -0
  158. data/spec/tagcrumbs/resources/models/model_spec.rb +27 -0
  159. data/spec/tagcrumbs/resources/models/picture_spec.rb +42 -0
  160. data/spec/tagcrumbs/resources/models/place_spec.rb +12 -0
  161. data/spec/tagcrumbs/resources/models/placemark_spec.rb +61 -0
  162. data/spec/tagcrumbs/resources/models/profile_link_spec.rb +29 -0
  163. data/spec/tagcrumbs/resources/models/profile_spec.rb +43 -0
  164. data/spec/tagcrumbs/resources/models/root_spec.rb +57 -0
  165. data/spec/tagcrumbs/resources/models/settings_spec.rb +32 -0
  166. data/spec/tagcrumbs/resources/models/state_spec.rb +30 -0
  167. data/spec/tagcrumbs/resources/models/subscription_spec.rb +28 -0
  168. data/spec/tagcrumbs/resources/models/suggestions_spec.rb +33 -0
  169. data/spec/tagcrumbs/resources/models/tag_spec.rb +16 -0
  170. data/spec/tagcrumbs/resources/models/tagcrumb_spec.rb +21 -0
  171. data/spec/tagcrumbs/resources/models/user_recommendation_spec.rb +35 -0
  172. data/spec/tagcrumbs/resources/models/user_spec.rb +128 -0
  173. data/spec/tagcrumbs/resources/resource_spec.rb +62 -0
  174. data/spec/tagcrumbs/validations_spec.rb +27 -0
  175. data/spec/tagcrumbs_spec.rb +103 -0
  176. data/tagcrumbs.gemspec +59 -0
  177. data/tasks/rspec.rake +21 -0
  178. metadata +327 -0
@@ -0,0 +1,301 @@
1
+ module Tagcrumbs
2
+ class ResourceInvalid# < ClientError #:nodoc:
3
+ end
4
+
5
+ # == Borrowed from ActiveResource
6
+
7
+ # Active Resource validation is reported to and from this object, which is used by Base#save
8
+ # to determine whether the object in a valid state to be saved. See usage example in Validations.
9
+ class Errors
10
+ include Enumerable
11
+ attr_reader :errors
12
+
13
+ delegate :empty?, :to => :errors
14
+
15
+ def initialize(base) # :nodoc:
16
+ @base, @errors = base, {}
17
+ end
18
+
19
+ # Add an error to the base Active Resource object rather than an attribute.
20
+ #
21
+ # ==== Examples
22
+ # my_folder = Folder.find(1)
23
+ # my_folder.errors.add_to_base("You can't edit an existing folder")
24
+ # my_folder.errors.on_base
25
+ # # => "You can't edit an existing folder"
26
+ #
27
+ # my_folder.errors.add_to_base("This folder has been tagged as frozen")
28
+ # my_folder.valid?
29
+ # # => false
30
+ # my_folder.errors.on_base
31
+ # # => ["You can't edit an existing folder", "This folder has been tagged as frozen"]
32
+ #
33
+ def add_to_base(msg)
34
+ add(:base, msg)
35
+ end
36
+
37
+ # Adds an error to an Active Resource object's attribute (named for the +attribute+ parameter)
38
+ # with the error message in +msg+.
39
+ #
40
+ # ==== Examples
41
+ # my_resource = Node.find(1)
42
+ # my_resource.errors.add('name', 'can not be "base"') if my_resource.name == 'base'
43
+ # my_resource.errors.on('name')
44
+ # # => 'can not be "base"!'
45
+ #
46
+ # my_resource.errors.add('desc', 'can not be blank') if my_resource.desc == ''
47
+ # my_resource.valid?
48
+ # # => false
49
+ # my_resource.errors.on('desc')
50
+ # # => 'can not be blank!'
51
+ #
52
+ def add(attribute, msg)
53
+ @errors[attribute.to_s] = [] if @errors[attribute.to_s].nil?
54
+ @errors[attribute.to_s] << msg
55
+ end
56
+
57
+ # Returns true if the specified +attribute+ has errors associated with it.
58
+ #
59
+ # ==== Examples
60
+ # my_resource = Disk.find(1)
61
+ # my_resource.errors.add('location', 'must be Main') unless my_resource.location == 'Main'
62
+ # my_resource.errors.on('location')
63
+ # # => 'must be Main!'
64
+ #
65
+ # my_resource.errors.invalid?('location')
66
+ # # => true
67
+ # my_resource.errors.invalid?('name')
68
+ # # => false
69
+ def invalid?(attribute)
70
+ !@errors[attribute.to_s].nil?
71
+ end
72
+
73
+ # A method to return the errors associated with +attribute+, which returns nil, if no errors are
74
+ # associated with the specified +attribute+, the error message if one error is associated with the specified +attribute+,
75
+ # or an array of error messages if more than one error is associated with the specified +attribute+.
76
+ #
77
+ # ==== Examples
78
+ # my_person = Person.new(params[:person])
79
+ # my_person.errors.on('login')
80
+ # # => nil
81
+ #
82
+ # my_person.errors.add('login', 'can not be empty') if my_person.login == ''
83
+ # my_person.errors.on('login')
84
+ # # => 'can not be empty'
85
+ #
86
+ # my_person.errors.add('login', 'can not be longer than 10 characters') if my_person.login.length > 10
87
+ # my_person.errors.on('login')
88
+ # # => ['can not be empty', 'can not be longer than 10 characters']
89
+ def on(attribute)
90
+ errors = @errors[attribute.to_s]
91
+ return nil if errors.nil?
92
+ errors.size == 1 ? errors.first : errors
93
+ end
94
+
95
+ alias :[] :on
96
+
97
+ # A method to return errors assigned to +base+ object through add_to_base, which returns nil, if no errors are
98
+ # associated with the specified +attribute+, the error message if one error is associated with the specified +attribute+,
99
+ # or an array of error messages if more than one error is associated with the specified +attribute+.
100
+ #
101
+ # ==== Examples
102
+ # my_account = Account.find(1)
103
+ # my_account.errors.on_base
104
+ # # => nil
105
+ #
106
+ # my_account.errors.add_to_base("This account is frozen")
107
+ # my_account.errors.on_base
108
+ # # => "This account is frozen"
109
+ #
110
+ # my_account.errors.add_to_base("This account has been closed")
111
+ # my_account.errors.on_base
112
+ # # => ["This account is frozen", "This account has been closed"]
113
+ #
114
+ def on_base
115
+ on(:base)
116
+ end
117
+
118
+ # Yields each attribute and associated message per error added.
119
+ #
120
+ # ==== Examples
121
+ # my_person = Person.new(params[:person])
122
+ #
123
+ # my_person.errors.add('login', 'can not be empty') if my_person.login == ''
124
+ # my_person.errors.add('password', 'can not be empty') if my_person.password == ''
125
+ # messages = ''
126
+ # my_person.errors.each {|attr, msg| messages += attr.to_s.humanize + " " + msg + "<br />"}
127
+ # messages
128
+ # # => "Login can not be empty<br />Password can not be empty<br />"
129
+ #
130
+ def each
131
+ @errors.each_key { |attr| @errors[attr].each { |msg| yield attr, msg } }
132
+ end
133
+
134
+ # Yields each full error message added. So Person.errors.add("first_name", "can't be empty") will be returned
135
+ # through iteration as "First name can't be empty".
136
+ #
137
+ # ==== Examples
138
+ # my_person = Person.new(params[:person])
139
+ #
140
+ # my_person.errors.add('login', 'can not be empty') if my_person.login == ''
141
+ # my_person.errors.add('password', 'can not be empty') if my_person.password == ''
142
+ # messages = ''
143
+ # my_person.errors.each_full {|msg| messages += msg + "<br/>"}
144
+ # messages
145
+ # # => "Login can not be empty<br />Password can not be empty<br />"
146
+ #
147
+ def each_full
148
+ full_messages.each { |msg| yield msg }
149
+ end
150
+
151
+ # Returns all the full error messages in an array.
152
+ #
153
+ # ==== Examples
154
+ # my_person = Person.new(params[:person])
155
+ #
156
+ # my_person.errors.add('login', 'can not be empty') if my_person.login == ''
157
+ # my_person.errors.add('password', 'can not be empty') if my_person.password == ''
158
+ # messages = ''
159
+ # my_person.errors.full_messages.each {|msg| messages += msg + "<br/>"}
160
+ # messages
161
+ # # => "Login can not be empty<br />Password can not be empty<br />"
162
+ #
163
+ def full_messages
164
+ full_messages = []
165
+
166
+ @errors.each_key do |attr|
167
+ @errors[attr].each do |msg|
168
+ next if msg.nil?
169
+
170
+ if attr == "base"
171
+ full_messages << msg
172
+ else
173
+ full_messages << [attr.to_s.humanize, msg].join(' ')
174
+ end
175
+ end
176
+ end
177
+ full_messages
178
+ end
179
+
180
+ def clear
181
+ @errors = {}
182
+ end
183
+
184
+ # Returns the total number of errors added. Two errors added to the same attribute will be counted as such
185
+ # with this as well.
186
+ #
187
+ # ==== Examples
188
+ # my_person = Person.new(params[:person])
189
+ # my_person.errors.size
190
+ # # => 0
191
+ #
192
+ # my_person.errors.add('login', 'can not be empty') if my_person.login == ''
193
+ # my_person.errors.add('password', 'can not be empty') if my_person.password == ''
194
+ # my_person.error.size
195
+ # # => 2
196
+ #
197
+ def size
198
+ @errors.values.inject(0) { |error_count, attribute| error_count + attribute.size }
199
+ end
200
+
201
+ alias_method :count, :size
202
+ alias_method :length, :size
203
+
204
+ def from_format(document, format)
205
+ case format
206
+ when :xml: from_xml(document)
207
+ when :json: from_json(document)
208
+ end
209
+ end
210
+
211
+ # Grabs errors from the XML response.
212
+ def from_xml(xml)
213
+ clear
214
+ humanized_attributes = @base.attributes.keys.inject({}) { |h, attr_name| h.update(attr_name.to_s.humanize => attr_name) }
215
+ messages = ::Array.wrap(Hash.from_xml(xml)['errors']['error']) rescue []
216
+ messages.each do |message|
217
+ attr_message = humanized_attributes.keys.detect do |attr_name|
218
+ if message[0, attr_name.size + 1] == "#{attr_name} "
219
+ add humanized_attributes[attr_name], message[(attr_name.size + 1)..-1]
220
+ end
221
+ end
222
+
223
+ add_to_base message if attr_message.nil?
224
+ end
225
+ end
226
+
227
+ # Grabs errors from the JSON response.
228
+ # Added for Tagcrumbs
229
+ def from_json(json)
230
+ clear
231
+ humanized_attributes = @base.attributes.keys.inject({}) { |h, attr_name| h.update(attr_name.to_s.humanize => attr_name) }
232
+
233
+ messages = JSON.parse(json)['errors']['error'] rescue []
234
+ messages.each do |message|
235
+ attr_message = humanized_attributes.keys.detect do |attr_name|
236
+ if message[0, attr_name.size + 1] == "#{attr_name} "
237
+ add humanized_attributes[attr_name], message[(attr_name.size + 1)..-1]
238
+ end
239
+ end
240
+
241
+ add_to_base message if attr_message.nil?
242
+ end
243
+ end
244
+ end
245
+
246
+ # Module to support validation and errors with Active Resource objects. The module overrides
247
+ # Base#save to rescue ActiveResource::ResourceInvalid exceptions and parse the errors returned
248
+ # in the web service response. The module also adds an +errors+ collection that mimics the interface
249
+ # of the errors provided by ActiveRecord::Errors.
250
+ #
251
+ # ==== Example
252
+ #
253
+ # Consider a Person resource on the server requiring both a +first_name+ and a +last_name+ with a
254
+ # <tt>validates_presence_of :first_name, :last_name</tt> declaration in the model:
255
+ #
256
+ # person = Person.new(:first_name => "Jim", :last_name => "")
257
+ # person.save # => false (server returns an HTTP 422 status code and errors)
258
+ # person.valid? # => false
259
+ # person.errors.empty? # => false
260
+ # person.errors.count # => 1
261
+ # person.errors.full_messages # => ["Last name can't be empty"]
262
+ # person.errors.on(:last_name) # => "can't be empty"
263
+ # person.last_name = "Halpert"
264
+ # person.save # => true (and person is now saved to the remote service)
265
+ #
266
+ module Validations
267
+ # def self.included(base) # :nodoc:
268
+ # base.class_eval do
269
+ # alias_method_chain :save, :validation
270
+ # end
271
+ # end
272
+ #
273
+ # # Validate a resource and save (POST) it to the remote web service.
274
+ # def save_with_validation
275
+ # save_without_validation
276
+ # true
277
+ # rescue ResourceInvalid => error
278
+ # errors.from_xml(error.response.body)
279
+ # false
280
+ # end
281
+
282
+ # Checks for errors on an object (i.e., is resource.errors empty?).
283
+ #
284
+ # ==== Examples
285
+ # my_person = Person.create(params[:person])
286
+ # my_person.valid?
287
+ # # => true
288
+ #
289
+ # my_person.errors.add('login', 'can not be empty') if my_person.login == ''
290
+ # my_person.valid?
291
+ # # => false
292
+ def valid?
293
+ errors.empty?
294
+ end
295
+
296
+ # Returns the Errors object that holds all information about attribute error messages.
297
+ def errors
298
+ @errors ||= Errors.new(self)
299
+ end
300
+ end
301
+ end
data/lib/tagcrumbs.rb ADDED
@@ -0,0 +1,232 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'rubygems'
5
+ #require 'ruby-debug'
6
+
7
+ gem 'activesupport', '2.3.2'
8
+ require 'active_support'
9
+
10
+ gem 'hpricot', '0.8.1'
11
+ require 'hpricot'
12
+
13
+ gem 'htmlentities', '4.0.0'
14
+ require 'htmlentities'
15
+
16
+ gem 'json', '1.1.6'
17
+ require 'JSON'
18
+
19
+ gem 'oauth', '0.3.4'
20
+ require 'oauth'
21
+
22
+ gem 'mime-types', '1.16'
23
+ require 'mime/types'
24
+
25
+ gem 'builder', '2.1.2'
26
+ require 'builder'
27
+
28
+ # Inflections must be available before classes are loaded, needed to automatically find the correct classes
29
+ ActiveSupport::Inflector.inflections do |inflect|
30
+ inflect.irregular 'address', 'address'
31
+ inflect.uncountable "settings"
32
+ inflect.uncountable "suggestions"
33
+ end
34
+
35
+ require 'tagcrumbs/validations'
36
+ require 'tagcrumbs/config_store'
37
+ require 'tagcrumbs/exceptions'
38
+
39
+ # parsers
40
+ require 'tagcrumbs/parsers/parser'
41
+ require 'tagcrumbs/parsers/json_parser'
42
+ require 'tagcrumbs/parsers/xml_parser'
43
+
44
+ # builders
45
+ require 'tagcrumbs/builders/builder'
46
+ require 'tagcrumbs/builders/json_builder'
47
+ require 'tagcrumbs/builders/xml_builder'
48
+
49
+ # general
50
+ require 'tagcrumbs/node'
51
+ require 'tagcrumbs/requestor'
52
+ require 'tagcrumbs/proxy'
53
+
54
+ # resources
55
+ require 'tagcrumbs/resources/resource'
56
+ require 'tagcrumbs/resources/array'
57
+
58
+ # models
59
+ require 'tagcrumbs/resources/models/accessors'
60
+ require 'tagcrumbs/resources/models/model'
61
+ require 'tagcrumbs/resources/models/tagcrumb'
62
+ require 'tagcrumbs/resources/models/place'
63
+
64
+ require 'tagcrumbs/resources/models/address'
65
+ require 'tagcrumbs/resources/models/activity'
66
+ require 'tagcrumbs/resources/models/city'
67
+ require 'tagcrumbs/resources/models/comment'
68
+ require 'tagcrumbs/resources/models/country'
69
+ require 'tagcrumbs/resources/models/fanship'
70
+ require 'tagcrumbs/resources/models/favorite'
71
+ require 'tagcrumbs/resources/models/filter'
72
+ require 'tagcrumbs/resources/models/flag'
73
+ require 'tagcrumbs/resources/models/friendship'
74
+ require 'tagcrumbs/resources/models/geoname'
75
+ require 'tagcrumbs/resources/models/link'
76
+ require 'tagcrumbs/resources/models/location'
77
+ require 'tagcrumbs/resources/models/picture'
78
+ require 'tagcrumbs/resources/models/placemark'
79
+ require 'tagcrumbs/resources/models/profile'
80
+ require 'tagcrumbs/resources/models/profile_link'
81
+ require 'tagcrumbs/resources/models/root'
82
+ require 'tagcrumbs/resources/models/settings'
83
+ require 'tagcrumbs/resources/models/state'
84
+ require 'tagcrumbs/resources/models/subscription'
85
+ require 'tagcrumbs/resources/models/suggestions'
86
+ require 'tagcrumbs/resources/models/tag'
87
+ require 'tagcrumbs/resources/models/user'
88
+ require 'tagcrumbs/resources/models/user_recommendation'
89
+
90
+
91
+ module Tagcrumbs
92
+ VERSION = '0.3.1'
93
+
94
+ class << self
95
+ # Returns the default configuration options of the gem. You can overwrite the options with configure
96
+ def default_options
97
+ {
98
+ :consumer_token => 'ZQAR3nW5D3S5JgU8EAKEfA',
99
+ :consumer_secret => 'vMc7NA77eraJc9TwyImshEEMVgrEy4C8YURVlwoyrHE',
100
+ :format => :xml,
101
+ :consumer_options =>
102
+ {
103
+ :site => 'http://www.tagcrumbs.com'
104
+ #:site => 'http://localhost:2999'
105
+ }
106
+ }
107
+ end
108
+
109
+ # Returns the current configuration options
110
+ def options
111
+ @@options ||= default_options.with_indifferent_access
112
+ end
113
+
114
+ # Resets the configuration options to the default_options
115
+ def reset_options!
116
+ @@options = default_options.with_indifferent_access
117
+ end
118
+
119
+ # Overwrite the default_options with your own options. You can specify:
120
+ #
121
+ # consumer_secret:: The OAuth consumer secret of your client that you registered on www.tagcrumbs.com
122
+ # consumer_token:: The OAuth consumer token of your client that you registered on www.tagcrumbs.com
123
+ # consumer_options:: Further Options that will be passed to the OAuth Gem
124
+ # request_token:: The OAuth request token that you received that you can exchange against an access token
125
+ # request_secret:: The OAuth request secret that you received that you can exchange against an access token
126
+ # format:: The Tagcrumbs webservice supports XML and JSON. You can specify the format of your requests here
127
+ def configure(new_options={})
128
+ new_options.symbolize_keys!
129
+ new_options.assert_valid_keys(:consumer_secret, :consumer_token, :consumer_options,
130
+ :access_token, :access_secret,
131
+ :request_token, :request_secret,
132
+ :format)
133
+
134
+ self.options.merge!(new_options)
135
+ end
136
+
137
+
138
+ # A request_token that you can let the user authorize, alternatively you can directly use the authorize_url
139
+ def request_token
140
+ return @@request_token if defined?(@@request_token)
141
+ @@request_token = Requestor.new.request_token
142
+
143
+ options[:request_token] = @@request_token.token
144
+ options[:request_secret] = @@request_token.secret
145
+
146
+ @@request_token
147
+ end
148
+
149
+ # An URL that you should redirect the user to or that you should open in a browser on which the user has to approve access
150
+ # for your application
151
+ def authorize_url
152
+ request_token.authorize_url
153
+ end
154
+
155
+ # After you redirected the user to the authorize_url and after the user authorized your application you can exchange
156
+ # the request_token against an access_token that you can use to make all further signed requests.
157
+ # You should use configure to pass in your access_token and access_secret for all further web service calls.
158
+ def exchange_request_token!
159
+ return @@access_token if defined?(@@access_token)
160
+ @@access_token = request_token.get_access_token
161
+
162
+ options[:access_token] = @@access_token.token
163
+ options[:access_secret] = @@access_token.secret
164
+
165
+ @@access_token
166
+ rescue OAuth::Unauthorized
167
+ nil
168
+ end
169
+
170
+ # Returns the current user that approved the application and owns the current access_token
171
+ # This is also used internally to automatically request all the URLs to POST new resources to.
172
+ def current_user
173
+ @@current_user ||= User.load('/you')
174
+ end
175
+
176
+ # Reads the index.(xml|json) file and automatically useses the URLs for further other queries
177
+ def root
178
+ @@root ||= Root.load('/index')
179
+ end
180
+
181
+ # Constants that are used to validate query parameters in find and search queries
182
+ def constants
183
+ @@constants ||= {
184
+ :per_page => [1, 5, 7, 10, 25, 50, 100],
185
+ :from => [:you, :friends, :fans, :recommendations, :everybody, :user],
186
+ :tagcrumb_type => ['Placemark', 'Favorite'],
187
+ :within => [0.015, 0.15, 0.55],
188
+ :sort => [:date, :distance, :name, :favorites, :comments],
189
+ :order => [:asc, :desc],
190
+ :w => [:unknown, :country, :state, :city, :zip, :street, :intersection, :address, :premise, :nearby, :everywhere]
191
+ }.with_indifferent_access
192
+ end
193
+
194
+ # Validate that key has a valid value. Returns an error if it does not. The constants method returns the valid values.
195
+ def validate(key, value)
196
+ if constants[key]
197
+ raise ArgumentError.new("#{key} must be one of the following: #{constants[key].join(', ')}") unless constants[key].include?(value)
198
+ true
199
+ end
200
+ end
201
+
202
+ # Returns a Tagcrumbs Class by name
203
+ def class_by_type(class_name)
204
+ "Tagcrumbs::#{class_name.classify}".constantize
205
+ end
206
+
207
+ # The supported formats of the Gem and their MIME types
208
+ def supported_formats
209
+ {
210
+ :xml => ['application/xml', 'text/xml'],
211
+ :json => ['application/json', 'text/json']
212
+ }
213
+ end
214
+
215
+ # Checks whether there is a valid access_token and access_secret that can be used to make all further calls to the webservice.
216
+ def valid_credentials?
217
+ if options[:access_token] && options[:access_secret]
218
+ requestor = Requestor.new
219
+ requestor.get('/you')
220
+
221
+ true
222
+ else
223
+ false
224
+ end
225
+ rescue Net::HTTPServerException => error
226
+ requestor.response.code == '401' ? false : (raise error) # unauthorized
227
+ end
228
+ end
229
+
230
+ end
231
+
232
+
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/tagcrumbs.rb'}"
9
+ puts "Loading tagcrumbs gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)