tagcrumbs-tagcrumbs 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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.rb +232 -0
  29. data/lib/tagcrumbs/builders/builder.rb +45 -0
  30. data/lib/tagcrumbs/builders/json_builder.rb +38 -0
  31. data/lib/tagcrumbs/builders/xml_builder.rb +30 -0
  32. data/lib/tagcrumbs/cli.rb +268 -0
  33. data/lib/tagcrumbs/config_store.rb +35 -0
  34. data/lib/tagcrumbs/exceptions.rb +13 -0
  35. data/lib/tagcrumbs/node.rb +43 -0
  36. data/lib/tagcrumbs/parsers/json_parser.rb +79 -0
  37. data/lib/tagcrumbs/parsers/parser.rb +24 -0
  38. data/lib/tagcrumbs/parsers/xml_parser.rb +54 -0
  39. data/lib/tagcrumbs/proxy.rb +32 -0
  40. data/lib/tagcrumbs/requestor.rb +140 -0
  41. data/lib/tagcrumbs/resources/array.rb +108 -0
  42. data/lib/tagcrumbs/resources/models/accessors.rb +252 -0
  43. data/lib/tagcrumbs/resources/models/activity.rb +19 -0
  44. data/lib/tagcrumbs/resources/models/address.rb +16 -0
  45. data/lib/tagcrumbs/resources/models/city.rb +13 -0
  46. data/lib/tagcrumbs/resources/models/comment.rb +12 -0
  47. data/lib/tagcrumbs/resources/models/country.rb +15 -0
  48. data/lib/tagcrumbs/resources/models/fanship.rb +12 -0
  49. data/lib/tagcrumbs/resources/models/favorite.rb +22 -0
  50. data/lib/tagcrumbs/resources/models/filter.rb +32 -0
  51. data/lib/tagcrumbs/resources/models/flag.rb +10 -0
  52. data/lib/tagcrumbs/resources/models/friendship.rb +12 -0
  53. data/lib/tagcrumbs/resources/models/geoname.rb +8 -0
  54. data/lib/tagcrumbs/resources/models/link.rb +13 -0
  55. data/lib/tagcrumbs/resources/models/location.rb +13 -0
  56. data/lib/tagcrumbs/resources/models/model.rb +148 -0
  57. data/lib/tagcrumbs/resources/models/picture.rb +28 -0
  58. data/lib/tagcrumbs/resources/models/place.rb +17 -0
  59. data/lib/tagcrumbs/resources/models/placemark.rb +30 -0
  60. data/lib/tagcrumbs/resources/models/profile.rb +16 -0
  61. data/lib/tagcrumbs/resources/models/profile_link.rb +12 -0
  62. data/lib/tagcrumbs/resources/models/root.rb +19 -0
  63. data/lib/tagcrumbs/resources/models/settings.rb +14 -0
  64. data/lib/tagcrumbs/resources/models/state.rb +14 -0
  65. data/lib/tagcrumbs/resources/models/subscription.rb +13 -0
  66. data/lib/tagcrumbs/resources/models/suggestions.rb +11 -0
  67. data/lib/tagcrumbs/resources/models/tag.rb +6 -0
  68. data/lib/tagcrumbs/resources/models/tagcrumb.rb +58 -0
  69. data/lib/tagcrumbs/resources/models/user.rb +101 -0
  70. data/lib/tagcrumbs/resources/models/user_recommendation.rb +18 -0
  71. data/lib/tagcrumbs/resources/resource.rb +76 -0
  72. data/lib/tagcrumbs/validations.rb +301 -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 +325 -0
@@ -0,0 +1,45 @@
1
+ module Tagcrumbs
2
+ class Builder
3
+ attr_accessor :model
4
+
5
+ def initialize(model, options={})
6
+ self.model = model
7
+ end
8
+
9
+ def build
10
+ ''
11
+ end
12
+
13
+ # also include the name as we might have some exceptions based on name someday
14
+ def typecast(name, value)
15
+ if value.class == Time
16
+ value.iso8601
17
+ elsif value.is_a?(Tagcrumbs::Model)
18
+ value.resource_url
19
+ else
20
+ value
21
+ end
22
+ end
23
+
24
+ # also include the name as we might have some exceptions based on name someday
25
+ def determine_type(name, value)
26
+ type = {}
27
+ type.merge!(:nil => true) if value.nil?
28
+
29
+ if value.class == Time
30
+ type.merge!(:type => :timestamp)
31
+ elsif value.class == TrueClass || value.class == FalseClass
32
+ type.merge!(:type => :boolean)
33
+ elsif value.class == Float
34
+ type.merge!(:type => :float)
35
+ elsif value.class == Fixnum
36
+ type.merge!(:type => :integer)
37
+ elsif value.is_a?(Tagcrumbs::Model)
38
+ type.merge!(:type => value.class_name)
39
+ end
40
+
41
+ type
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,38 @@
1
+ module Tagcrumbs
2
+ class JsonBuilder < Builder
3
+ def build(options={})
4
+ options.reverse_merge!(:to_json => true)
5
+
6
+ attributes = {}
7
+
8
+ if options[:badgerfish] # build badgerfish style json
9
+ model.attributes(options).each do |key, value|
10
+ attributes[key] = {'$' => typecast(key, value)}.merge(badgerfish_attributes(determine_type(key, value)))
11
+ end
12
+
13
+ hash = {model.class_name.underscore => attributes.merge(badgerfish_attributes(:type => model.class_name))}
14
+ else # build plain json
15
+ model.attributes(options).each do |key, value|
16
+ attributes[key] = typecast(key, value)
17
+ end
18
+
19
+ hash = {model.class_name.underscore => attributes}
20
+ end
21
+
22
+ options[:to_json] ? hash.to_json : hash # makes testing easier
23
+ end
24
+
25
+
26
+ private
27
+
28
+ def badgerfish_attributes(attributes)
29
+ hash = {}
30
+
31
+ attributes.each do |k, v|
32
+ hash["@#{k}"] = v
33
+ end
34
+
35
+ hash
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ module Tagcrumbs
2
+ class XmlBuilder < Builder
3
+ def build(options={})
4
+ result = ''
5
+
6
+ xml = ::Builder::XmlMarkup.new(:indent => 1, :target => result)
7
+ xml.instruct! :xml, :version => "1.0"
8
+
9
+ xml.tag!(model.class_name.underscore, :type => model.class_name, 'xmlns:xlink' => "http://www.w3.org/1999/xlink") do
10
+ attributes = model.attributes(options)
11
+ attribute_keys = attributes.keys
12
+ attribute_keys.sort!{|a, b| a.to_s <=> b.to_s} if options[:sorted_attributes] # for testing, otherwise output order is random
13
+
14
+ attribute_keys.each do |key|
15
+ if attributes[key].is_a?(Hash) # nested attributes like the address attributes on creation of a placemark
16
+ xml.tag!(key) do
17
+ attributes[key].each do |k, v|
18
+ xml.tag!(k, typecast(k, v), determine_type(k, v))
19
+ end
20
+ end
21
+ else
22
+ xml.tag!(key, typecast(key, attributes[key]), determine_type(key, attributes[key]))
23
+ end
24
+ end
25
+ end
26
+
27
+ result
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,268 @@
1
+ require 'optparse'
2
+ require 'ostruct'
3
+ require File.dirname(__FILE__) + '/../tagcrumbs'
4
+
5
+ module Tagcrumbs
6
+ class CLI
7
+ attr_reader :options, :stdout, :stdin
8
+
9
+ def self.execute(stdout, stdin, stderr, arguments = [])
10
+ self.new.execute(stdout, stdin, stderr, arguments)
11
+ end
12
+
13
+ def initialize
14
+ @options = {}
15
+
16
+ trap(:INT) { exit } # no backtrace on ^C
17
+ end
18
+
19
+ def execute(stdout, stdin, stderr, arguments = [])
20
+ @stdout = stdout
21
+ @stdin = stdin
22
+ @stderr = stderr
23
+
24
+ @config_store = Tagcrumbs::ConfigStore.load(ENV['HOME'] + '/.tagcrumbs')
25
+ Tagcrumbs.configure(@config_store.options)
26
+
27
+ if Tagcrumbs.valid_credentials?
28
+ if arguments.present?
29
+ option_parser.parse!(arguments)
30
+ execute_new_placemark
31
+ else
32
+ execute_interactive_mode
33
+ end
34
+ else
35
+ execute_authorize
36
+ end
37
+ end
38
+
39
+ protected
40
+
41
+ def option_parser
42
+ option_parser = OptionParser.new do |opts|
43
+ opts.banner = "Usage: #{$0} [options]"
44
+
45
+ @options[:placemark] = {}
46
+ @options[:placemark][:address_attributes] = {}
47
+
48
+ opts.on('-v', '--version') do
49
+ output_version
50
+ exit 0
51
+ end
52
+
53
+ # GENERAL OPTIONS
54
+ opts.on('-h', '--help') do
55
+ output_help
56
+ exit 0
57
+ end
58
+
59
+ opts.on('-V', '--verbose') do
60
+ @options[:verbose] = true
61
+ end
62
+
63
+ # PLACEMARK OPTIONS
64
+ opts.on("-n", "--name NAME", "Give your tagcrumb a name") do |name|
65
+ @options[:placemark][:name] = name
66
+ end
67
+
68
+ opts.on("-N", "--notes NOTES", "Add some notes") do |notes|
69
+ @options[:placemark][:notes] = notes
70
+ end
71
+
72
+ opts.on("-t", "--tags tag1,tag2,tagX", "Add tags") do |tags|
73
+ @options[:placemark][:tags] = tags
74
+ end
75
+
76
+ opts.on("-y", "--latitude LATITUDE", Float, "Set the latitude") do |latitude|
77
+ @options[:placemark][:latitude] = latitude
78
+ end
79
+
80
+ opts.on("-x", "--longitude LATITUDE", Float, "Set the longitude") do |longitude|
81
+ @options[:placemark][:longitude] = longitude
82
+ end
83
+
84
+ opts.on("-p", "--private", "Make it private") do
85
+ @options[:placemark][:private] = true
86
+ end
87
+
88
+ opts.on("-g", "--guess-city", "Make a guess on the correct city") do
89
+ @options[:placemark][:guess_city] = true
90
+ end
91
+
92
+ opts.on("-w", "--websites url1,url2,urlX", ::Array, "List of websites") do |links|
93
+ @options[:placemark][:links] = links
94
+ end
95
+
96
+
97
+ opts.on("--address-street STREET", "The street address") do |street|
98
+ @options[:placemark][:address_attributes][:street] = street
99
+ end
100
+
101
+ opts.on("--address-postal-code ZIP", "The postal code") do |postal_code|
102
+ @options[:placemark][:address_attributes][:postal_code] = postal_code
103
+ end
104
+
105
+ opts.on("--address-city CITY", "The city name as it will be put in the address") do |city|
106
+ @options[:placemark][:address_attributes][:city] = city
107
+ end
108
+
109
+ opts.on("--address-state STATE", "The state name as it will be put in the address") do |state|
110
+ @options[:placemark][:address_attributes][:state] = state
111
+ end
112
+
113
+ opts.on("--address-country COUNTRY", "The country name as it will be put in the address") do |country|
114
+ @options[:placemark][:address_attributes][:country] = country
115
+ end
116
+
117
+ opts.separator ""
118
+ opts.separator "Create a new placemark with command line arguments:"
119
+ opts.separator "#{$0} -n 'name of the tagcrumb' -x 9.012 -y 49.9"
120
+ opts.separator ""
121
+ opts.separator "Create a new placemark in interactive mode:"
122
+ opts.separator "#{$0}"
123
+ end
124
+ end
125
+
126
+ def output_version
127
+ @stdout.puts "#{$0} version #{Tagcrumbs::VERSION}"
128
+ end
129
+
130
+ def output_help
131
+ output_version
132
+ @stdout.puts
133
+ @stdout.puts option_parser.help
134
+ end
135
+
136
+ def verbose_puts(msg)
137
+ @stdout.puts msg if @options[:verbose]
138
+ end
139
+
140
+ def execute_authorize
141
+ @stdout.puts "Connecting to Tagcrumbs..."
142
+
143
+ authorize_url = Tagcrumbs.authorize_url
144
+ %x(open #{authorize_url})
145
+
146
+ @stdout.print "Please authorize the application in your browser: #{authorize_url}.\nPress Enter after you authorized the application to continue..."
147
+ @stdin.gets
148
+
149
+ if Tagcrumbs.exchange_request_token!
150
+ @stdout.puts "The application is now authorized. You won't have to do this again the next time you run the application."
151
+ @config_store.update(Tagcrumbs.options.slice(:access_token, :access_secret))
152
+ else
153
+ @stdout.puts "The application could not be authorized."
154
+ end
155
+ end
156
+
157
+ def execute_new_placemark
158
+ links = @options[:placemark].delete(:links)
159
+
160
+ placemark = Tagcrumbs::Placemark.new(@options[:placemark])
161
+
162
+ if placemark.save
163
+ verbose_puts "Saved: " + placemark.resource_url
164
+
165
+ if links.present?
166
+ links.each do |url|
167
+ link = Tagcrumbs::Link.new(:url => url, :placemark => placemark)
168
+
169
+ if link.save
170
+ verbose_puts "Saved Link: " + link.resource_url
171
+ else
172
+ @stderr.puts "** Link Errors: \n"
173
+ @stderr.puts link.errors.full_messages.join("\n")
174
+ end
175
+ end
176
+ end
177
+ else
178
+ @stderr.puts "** Placemark could not be created!"
179
+
180
+ @stderr.puts "** Placemark Errors: \n"
181
+ @stderr.puts placemark.errors.full_messages.join("\n")
182
+ end # end placemark.save
183
+ end
184
+
185
+ def execute_interactive_mode
186
+ @stdout.puts "== Create a new Placemark on tagcrumbs.com"
187
+ @stdout.puts "You can also use arguments to create a placemark, type #{$0} -h to find out how.\n"
188
+
189
+ begin
190
+ placemark = Tagcrumbs::Placemark.new
191
+
192
+ @stdout.print "Latitude: "
193
+ placemark.latitude = @stdin.gets.chomp
194
+
195
+ @stdout.print "Longitude: "
196
+ placemark.longitude = @stdin.gets.chomp
197
+
198
+ @stdout.print "\n== Loading suggestions... \n"
199
+ suggestions = placemark.suggestions
200
+
201
+ if suggestions.names.present?
202
+ @stdout.puts "\n== Select a name"
203
+
204
+ suggestions.names.each_with_index do |value, index|
205
+ @stdout.puts " #{index+1}. #{value}"
206
+ end
207
+
208
+ @stdout.puts " 0. Enter your own name"
209
+
210
+ @stdout.print "Select a number: "
211
+ number = @stdin.gets.chomp
212
+
213
+ if number.to_i == 0
214
+ @stdout.print "Enter a name: "
215
+ placemark.name = @stdin.gets.chomp
216
+ else
217
+ placemark.name = suggestions.names[number.to_i-1]
218
+ end
219
+ else
220
+ @stdout.puts "No suggestions found."
221
+ @stdout.print "Enter a name: "
222
+ placemark.name = @stdin.gets.chomp
223
+ end
224
+
225
+ @stdout.puts "\n== Enter tags (comma separated)"
226
+
227
+ @stdout.puts "Popular tags: #{suggestions.popular_tags.map{|t| t.name}.join(', ')}" if suggestions.popular_tags.present?
228
+ @stdout.puts "Recommended tags: #{suggestions.recommended_tags.map{|t| t.name}.join(', ')}" if suggestions.recommended_tags.present?
229
+ @stdout.print "Enter tags: "
230
+
231
+ placemark.tag_list = @stdin.gets.chomp
232
+
233
+ @stdout.print "\n== Enter notes: "
234
+ placemark.notes = @stdin.gets.chomp
235
+
236
+
237
+ if suggestions.cities.present?
238
+ @stdout.puts "\n== Which city?"
239
+
240
+ suggestions.cities.each_with_index do |city, index|
241
+ @stdout.puts " #{index+1}. #{city.name}"
242
+ end
243
+
244
+ @stdout.puts " 0. Middle of Nowhere"
245
+
246
+ @stdout.print "Select a city: "
247
+ number = @stdin.gets.chomp
248
+ placemark.city = (number == '0') ? nil : suggestions.cities[number.to_i-1]
249
+ end
250
+
251
+ @stdout.print "== Save the placemark? (y/n): "
252
+ save = @stdin.gets.chomp
253
+
254
+ if placemark.save
255
+ @stdout.puts "Saved (#{placemark.resource_url})"
256
+ else
257
+ @stdout.puts "Could not be saved:"
258
+ @stderr.puts placemark.errors.full_messages.join("\n")
259
+ end
260
+
261
+ @stdout.print "== Create another placemark? (y/n): "
262
+ start_over = @stdin.gets.chomp
263
+ end while(start_over == 'y')
264
+
265
+ end
266
+
267
+ end
268
+ end
@@ -0,0 +1,35 @@
1
+ module Tagcrumbs
2
+ # Use the ConfigStore to save configuration options to a yaml file (tokens)
3
+ class ConfigStore
4
+ attr_accessor :filename, :options
5
+
6
+ def initialize(filename, options ={})
7
+ @filename = filename
8
+ @options = options
9
+ end
10
+
11
+ # Load a filename and read it with YAML
12
+ def self.load(filename)
13
+ config = File.exist?(filename) ? YAML::load(open(filename)) : {}
14
+ new(filename, config)
15
+ end
16
+
17
+ # Update the current options and save the file
18
+ def update(c={})
19
+ @options.merge!(c)
20
+ save
21
+ self
22
+ end
23
+
24
+ # Save the current options into the file in YAML format
25
+ def save
26
+ File.open(filename, 'w') { |f| f.write(YAML.dump(@options)) }
27
+ self
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+
34
+
35
+
@@ -0,0 +1,13 @@
1
+ module Tagcrumbs
2
+ class UnsupportedFormat < StandardError; end
3
+
4
+ class CreateURLMissing < StandardError; end
5
+ class ResourceURLMissing < StandardError; end
6
+
7
+ class CreateImpossible < StandardError; end
8
+ class UpdateImpossible < StandardError; end
9
+ class DestroyImpossible < StandardError; end
10
+
11
+ class InvalidRequest < StandardError; end
12
+
13
+ end
@@ -0,0 +1,43 @@
1
+ module Tagcrumbs
2
+ class Node
3
+ attr_accessor :name, :value
4
+ attr_writer :properties
5
+
6
+ def initialize(name, value, properties={})
7
+ self.name = name
8
+ self.properties = properties
9
+ self.value = typecast_value(value)
10
+ end
11
+
12
+ # The XML/JSON properties of a node, they are used to typecast the value and kept around
13
+ # so that it is also possible to look at them later
14
+ def properties
15
+ @properties ||= {}
16
+ end
17
+
18
+ private
19
+ # typecast value depending on the properties that are set and read from the webservice
20
+ def typecast_value(value)
21
+ return nil if value.nil?
22
+
23
+ if value.is_a?(String)
24
+ if properties['nil'] == 'true'
25
+ nil
26
+ else
27
+ case properties['type']
28
+ when 'timestamp': value.to_time
29
+ when 'float': value.to_f
30
+ when 'integer': value.to_i
31
+ when 'boolean': value == 'true' ? true : false
32
+ else
33
+ coder = HTMLEntities.new
34
+ coder.decode(value)
35
+ end
36
+ end
37
+ else
38
+ value
39
+ end
40
+ end
41
+
42
+ end
43
+ end