gnip 0.4.2

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 (89) hide show
  1. data/README +144 -0
  2. data/Rakefile +53 -0
  3. data/TODO +72 -0
  4. data/bin/gnip +651 -0
  5. data/doc/api.html +1201 -0
  6. data/gemspec.rb +47 -0
  7. data/gnip-0.4.2.gem +0 -0
  8. data/lib/gnip.rb +71 -0
  9. data/lib/gnip/activity.rb +663 -0
  10. data/lib/gnip/api.rb +191 -0
  11. data/lib/gnip/arguments.rb +21 -0
  12. data/lib/gnip/blankslate.rb +5 -0
  13. data/lib/gnip/config.rb +144 -0
  14. data/lib/gnip/filter.rb +304 -0
  15. data/lib/gnip/list.rb +126 -0
  16. data/lib/gnip/options.rb +96 -0
  17. data/lib/gnip/orderedhash.rb +199 -0
  18. data/lib/gnip/publisher.rb +309 -0
  19. data/lib/gnip/resource.rb +301 -0
  20. data/lib/gnip/template.rb +44 -0
  21. data/lib/gnip/util.rb +120 -0
  22. data/sample/data/activity.yml +21 -0
  23. data/test/auth.rb +60 -0
  24. data/test/config.yml +2 -0
  25. data/test/data/activity.xml +14 -0
  26. data/test/data/activity_only_required.xml +4 -0
  27. data/test/data/activity_with_payload.xml +22 -0
  28. data/test/data/activity_with_place.xml +18 -0
  29. data/test/data/activity_with_place_wo_bounds.xml +36 -0
  30. data/test/data/activity_with_unbounded_media_urls.xml +44 -0
  31. data/test/data/activity_without_bounds.xml +24 -0
  32. data/test/helper.rb +115 -0
  33. data/test/helper.rb.bak +28 -0
  34. data/test/integration/auth.rb +12 -0
  35. data/test/integration/publisher.rb +86 -0
  36. data/test/lib/shoulda.rb +9 -0
  37. data/test/lib/shoulda/action_controller.rb +28 -0
  38. data/test/lib/shoulda/action_controller/helpers.rb +47 -0
  39. data/test/lib/shoulda/action_controller/macros.rb +277 -0
  40. data/test/lib/shoulda/action_controller/matchers.rb +37 -0
  41. data/test/lib/shoulda/action_controller/matchers/assign_to_matcher.rb +109 -0
  42. data/test/lib/shoulda/action_controller/matchers/filter_param_matcher.rb +57 -0
  43. data/test/lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb +81 -0
  44. data/test/lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb +70 -0
  45. data/test/lib/shoulda/action_controller/matchers/respond_with_matcher.rb +77 -0
  46. data/test/lib/shoulda/action_controller/matchers/route_matcher.rb +93 -0
  47. data/test/lib/shoulda/action_controller/matchers/set_session_matcher.rb +83 -0
  48. data/test/lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb +85 -0
  49. data/test/lib/shoulda/action_mailer.rb +10 -0
  50. data/test/lib/shoulda/action_mailer/assertions.rb +38 -0
  51. data/test/lib/shoulda/action_view.rb +10 -0
  52. data/test/lib/shoulda/action_view/macros.rb +56 -0
  53. data/test/lib/shoulda/active_record.rb +16 -0
  54. data/test/lib/shoulda/active_record/assertions.rb +69 -0
  55. data/test/lib/shoulda/active_record/helpers.rb +40 -0
  56. data/test/lib/shoulda/active_record/macros.rb +586 -0
  57. data/test/lib/shoulda/active_record/matchers.rb +42 -0
  58. data/test/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +83 -0
  59. data/test/lib/shoulda/active_record/matchers/allow_value_matcher.rb +102 -0
  60. data/test/lib/shoulda/active_record/matchers/association_matcher.rb +226 -0
  61. data/test/lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb +87 -0
  62. data/test/lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb +141 -0
  63. data/test/lib/shoulda/active_record/matchers/have_db_column_matcher.rb +169 -0
  64. data/test/lib/shoulda/active_record/matchers/have_index_matcher.rb +105 -0
  65. data/test/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +125 -0
  66. data/test/lib/shoulda/active_record/matchers/have_readonly_attribute_matcher.rb +59 -0
  67. data/test/lib/shoulda/active_record/matchers/validate_acceptance_of_matcher.rb +41 -0
  68. data/test/lib/shoulda/active_record/matchers/validate_numericality_of_matcher.rb +39 -0
  69. data/test/lib/shoulda/active_record/matchers/validate_presence_of_matcher.rb +60 -0
  70. data/test/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +148 -0
  71. data/test/lib/shoulda/active_record/matchers/validation_matcher.rb +56 -0
  72. data/test/lib/shoulda/assertions.rb +59 -0
  73. data/test/lib/shoulda/autoload_macros.rb +46 -0
  74. data/test/lib/shoulda/context.rb +304 -0
  75. data/test/lib/shoulda/helpers.rb +8 -0
  76. data/test/lib/shoulda/macros.rb +73 -0
  77. data/test/lib/shoulda/private_helpers.rb +20 -0
  78. data/test/lib/shoulda/proc_extensions.rb +14 -0
  79. data/test/lib/shoulda/rails.rb +13 -0
  80. data/test/lib/shoulda/rspec.rb +9 -0
  81. data/test/lib/shoulda/tasks.rb +3 -0
  82. data/test/lib/shoulda/tasks/list_tests.rake +29 -0
  83. data/test/lib/shoulda/tasks/yaml_to_shoulda.rake +28 -0
  84. data/test/lib/shoulda/test_unit.rb +19 -0
  85. data/test/lib/xmlsimple.rb +1021 -0
  86. data/test/loader.rb +25 -0
  87. data/test/unit/activity.rb +26 -0
  88. data/test/unit/util.rb +39 -0
  89. metadata +198 -0
@@ -0,0 +1,301 @@
1
+ module Gnip
2
+ class Resource
3
+ def Resource.default
4
+ @default ||= new
5
+ end
6
+
7
+ def Resource.headers headers = {}
8
+ result = default_headers.dup
9
+
10
+ headers.each do |key, value|
11
+ key = key.to_s.downcase.split(%r/[_-]/).map{|part| part.capitalize}.join('-')
12
+ result[key] = value
13
+ end
14
+
15
+ result
16
+
17
+ =begin
18
+ default_headers.dup.merge(headers).inject({}) do |final, (key, value)|
19
+ final[key.to_s.gsub(/_/, '-').capitalize] = value.to_s
20
+ final
21
+ end
22
+ =end
23
+ end
24
+
25
+ def Resource.default_headers
26
+ @default_headers ||= {
27
+ 'Content-Type' => 'application/xml',
28
+ 'User-Agent' => 'gnip.rb',
29
+ 'Content-Encoding' => 'gzip',
30
+ 'Accept-Encoding' => 'gzip',
31
+ }
32
+ end
33
+
34
+ def Resource.compress(data)
35
+ writer = Zlib::GzipWriter.new(StringIO.new(result=''))
36
+ writer.write(data)
37
+ writer.close
38
+ result
39
+ end
40
+
41
+ def Resource.uncompress(data)
42
+ Zlib::GzipReader.new(StringIO.new(data)).read
43
+ end
44
+
45
+ attr_accessor :config
46
+
47
+ def initialize(*args)
48
+ args, options = Gnip.args_for(args)
49
+ @config = args.shift || options.getopt(:config, Gnip.default.config)
50
+ which = options.getopt(:implementation, :restclient)
51
+ @implementation = Implementation.for(self, which)
52
+ end
53
+
54
+ def method_missing(m, *a, &b)
55
+ if @implementation.respond_to?(m)
56
+ @implementation.send(m, *a, &b)
57
+ else
58
+ super
59
+ end
60
+ end
61
+
62
+ def Resource.method_missing(m, *a, &b)
63
+ if Implementation.respond_to?(m)
64
+ Implementation.send(m, *a, &b)
65
+ else
66
+ super
67
+ end
68
+ end
69
+
70
+ def uri_for(*args)
71
+ args, options = Gnip.args_for(args)
72
+ uri = config.uri.dup
73
+ uri.path = "/#{ args.shift }".squeeze('/')
74
+ options.each{|k,v| uri.send "#{ k }=", v}
75
+ uri
76
+ end
77
+
78
+ def [](*args, &block)
79
+ @implementation.send('[]', *args, &block)
80
+ end
81
+ alias_method 'endpoint', '[]'
82
+ alias_method '/', '[]'
83
+
84
+ # TODO - requires username and password?
85
+ #
86
+ class Implementation
87
+ class RestClient < Implementation
88
+ attr_accessor :interface
89
+ attr_accessor :resource
90
+
91
+ def initialize interface, options = {}
92
+ Gnip.options_for(options)
93
+ @interface = interface
94
+ uri = options.getopt(:uri, config.uri)
95
+ username = options.getopt(:username, config.username)
96
+ password = options.getopt(:password, config.password)
97
+ headers = options.getopt(:headers, default_headers)
98
+ @resource = ::RestClient::Resource.new(uri, :user => username, :password => password, :headers => headers)
99
+ end
100
+
101
+ def default_headers
102
+ {
103
+ :content_type => 'application/xml',
104
+ :user_agent => 'gnip.rb',
105
+ :content_encoding => 'gzip',
106
+ :accept_encoding => 'gzip',
107
+ }
108
+ end
109
+
110
+ def compress(data, headers = {})
111
+ key = (resource.headers.keys + headers.keys).detect{|key| key.to_s =~ /^\s*content.encoding\s*$/i}
112
+ value = resource.headers[key] || headers[key] if key
113
+ ( value.to_s =~ /gzip/ ? Util.compress(data) : data ).to_s
114
+ end
115
+
116
+ def decompress(data)
117
+ Util.decompress(data.to_s).to_s
118
+ end
119
+
120
+ def config
121
+ interface.config
122
+ end
123
+
124
+ def uri
125
+ URI.parse resource.url.to_s
126
+ end
127
+
128
+ def username
129
+ resource.user
130
+ end
131
+
132
+ def password
133
+ resource.password
134
+ end
135
+
136
+ def [] path
137
+ subresource = resource[relative_path(path)]
138
+ subclient = dup
139
+ subclient.resource = subresource
140
+ subclient
141
+ end
142
+ alias_method 'endpoint', '[]'
143
+ alias_method '/', '[]'
144
+
145
+ def for options = {}
146
+ Gnip.options_for(options)
147
+ path = options.getopt(:path)
148
+ if path
149
+ uri = URI.parse(resource.uri)
150
+ uri.path = absolute_path(path)
151
+ self.class.new(interface, :uri => uri, :username => username, :password => password)
152
+ else
153
+ raise ArgumentError
154
+ end
155
+ end
156
+
157
+ class Error < ::StandardError
158
+ attr :error
159
+ def initialize message = nil, error = nil
160
+ super(message.to_s)
161
+ @error = error
162
+ end
163
+ end
164
+
165
+ def wrapping_errors
166
+ begin
167
+ yield
168
+ rescue Exception => error
169
+ message = []
170
+ message << error.message if error.respond_to?(:message) rescue nil
171
+ message << error.response.body if error.respond_to?(:response) rescue nil
172
+ message = message.join(' #=> ')
173
+ raise Error.new(message, error)
174
+ end
175
+ end
176
+
177
+ %w[ get delete post put ].each do |verb|
178
+ define_method(verb) do |*args|
179
+ Gnip.argify!(args)
180
+ headers = args.options
181
+ data = args.shift
182
+
183
+ args = []
184
+ args.push(compress(data, headers)) if data
185
+ args.push(headers)
186
+
187
+ wrapping_errors do
188
+ log_request(verb, data, headers)
189
+ log_response(resource.send(verb, *args))
190
+ end
191
+ end
192
+ end
193
+
194
+ def inspect
195
+ options = resource.headers.dup.update(:username => username, :password => password)
196
+ "#{ resource.url }(#{ options.inspect })"
197
+ end
198
+ end
199
+
200
+ def absolute_path(*paths)
201
+ paths.join('/').squeeze('/').sub(%r|^/+|, '/')
202
+ end
203
+
204
+ def relative_path(*paths)
205
+ absolute_path(*paths).sub(%r|^/+|, '')
206
+ end
207
+
208
+ def log_request verb, data = nil, headers = {}
209
+ log {
210
+ if data
211
+ data = data.size > log_max_size ? "#{ data[0,log_max_size] }...(#{ data.size }bytes)" : data
212
+ end
213
+ "\n#{ self.inspect }.#{ verb }(#{ data.inspect }, #{ headers.inspect })"
214
+ }
215
+ end
216
+
217
+ def log_response response
218
+ log {
219
+ data = response.to_s
220
+ data = data.size > log_max_size ? "#{ data[0,log_max_size] }...(#{ data.size }bytes)" : data
221
+ "#{ data }"
222
+ }
223
+ response
224
+ end
225
+
226
+ def Implementation.log= value
227
+ @@log =
228
+ case value
229
+ when STDERR, 'stderr', :stderr
230
+ STDERR
231
+ when STDOUT, 'stdout', :stdout
232
+ STDOUT
233
+ else
234
+ if respond_to?(:write)
235
+ value
236
+ else
237
+ fd = open(value, 'w')
238
+ end
239
+ end
240
+ ensure
241
+ @@log.sync = true if @@log.respond_to?(:sync)
242
+ end
243
+
244
+ def Implementation.log
245
+ unless defined?(@@log)
246
+ if value = ENV['GNIP_HTTP_LOG']
247
+ Implementation.log = value
248
+ else
249
+ @@log = nil
250
+ end
251
+ end
252
+ @@log
253
+ end
254
+
255
+ def log &block
256
+ if Implementation.log and block
257
+ log.puts block.call
258
+ log.flush
259
+ else
260
+ Implementation.log
261
+ end
262
+ end
263
+
264
+ def Implementation.log_max_size
265
+ unless defined?(@@log_max_size)
266
+ if value = ENV['GNIP_HTTP_LOG_MAX_SIZE']
267
+ Implementation.log_max_size = value
268
+ else
269
+ @@log_max_size = 4096
270
+ end
271
+ end
272
+ @@log_max_size
273
+ end
274
+
275
+ def Implementation.log_max_size= value
276
+ @@log_max_size = Integer value
277
+ end
278
+
279
+ def log_max_size
280
+ Implementation.log_max_size
281
+ end
282
+
283
+ def Implementation.list
284
+ @list ||= [
285
+ RestClient
286
+ ]
287
+ end
288
+
289
+ def Implementation.for endpoint, which
290
+ implementation =
291
+ case which = which.to_s.downcase.strip.to_sym
292
+ when :restclient
293
+ RestClient
294
+ else
295
+ raise ArgumentError, "unknown implementation #{ which }"
296
+ end
297
+ implementation.new(endpoint)
298
+ end
299
+ end
300
+ end
301
+ end
@@ -0,0 +1,44 @@
1
+ module Gnip
2
+ class Template < ERB
3
+ def Template.for(*args, &block)
4
+ new(*args, &block)
5
+ end
6
+
7
+ def initialize(*args, &block)
8
+ args, options = Gnip.args_for(args)
9
+ @context = options.getopt(:context, options.getopt(:object))
10
+ string = args.shift || block.call
11
+ super(Gnip.util.unindent(string), safe_mode=nil, trim_mode='%')
12
+ end
13
+
14
+ def expand context = nil, &block
15
+ context ||= block.binding if block
16
+ context ||= @context
17
+ raise ArgumentError, 'no context' unless context
18
+ context = context.instance_eval('binding') unless context.respond_to?('binding')
19
+ block.call(self) if block
20
+ result(context)
21
+ end
22
+
23
+ class Xml < Template
24
+ Declaration = '<?xml version="1.0" encoding="UTF-8"?>'
25
+
26
+ def initialize(string = '', options = {}, &block)
27
+ Gnip.optify!(options)
28
+
29
+ declaration = options.getopt(:declaration)
30
+ case declaration
31
+ when TrueClass, FalseClass, NilClass
32
+ declaration = Declaration if declaration
33
+ else
34
+ declaration = declaration.to_s
35
+ end
36
+ string = "#{ declaration }\n#{ Gnip.util.unindent(string) }" if declaration
37
+
38
+ super(string, options, &block)
39
+ end
40
+ end
41
+
42
+ def Template.xml() Xml end
43
+ end
44
+ end
data/lib/gnip/util.rb ADDED
@@ -0,0 +1,120 @@
1
+ module Gnip
2
+ module Util
3
+ def homedir
4
+ homedir =
5
+ catch :home do
6
+ ["HOME", "USERPROFILE"].each do |key|
7
+ throw(:home, ENV[key]) if ENV[key]
8
+ end
9
+
10
+ if ENV["HOMEDRIVE"] and ENV["HOMEPATH"]
11
+ throw(:home, "#{ ENV['HOMEDRIVE'] }:#{ ENV['HOMEPATH'] }")
12
+ end
13
+
14
+ File.expand_path("~") rescue(File::ALT_SEPARATOR ? "C:/" : "/")
15
+ end
16
+ File.expand_path homedir
17
+ end
18
+
19
+ def unindent! s
20
+ indent = nil
21
+ s.each do |line|
22
+ next if line =~ %r/^\s*$/
23
+ indent = line[%r/^\s*/] and break
24
+ end
25
+ s.gsub! %r/^#{ indent }/, "" if indent
26
+ s
27
+ end
28
+
29
+ def unindent s
30
+ unindent! "#{ s }"
31
+ end
32
+
33
+ def indent! s, n = 2
34
+ n = Integer n
35
+ margin = ' ' * n
36
+ unindent! s
37
+ s.gsub! %r/^/, margin
38
+ s
39
+ end
40
+
41
+ def indent s, n = 2
42
+ indent!(s.to_s.dup, n)
43
+ end
44
+
45
+ def inline! s
46
+ s.gsub! %r/\n/, ' '
47
+ s.squeeze! ' '
48
+ s
49
+ end
50
+
51
+ def inline s
52
+ inline!(s.dup)
53
+ end
54
+
55
+ def random_string options = {}
56
+ Gnip.options_for(options)
57
+
58
+ Kernel.srand
59
+
60
+ default_size = 6
61
+ size = Integer(options.getopt(:size, default_size))
62
+
63
+ default_chars = ( ('a' .. 'z').to_a + ('A' .. 'Z').to_a + (0 .. 9).to_a )
64
+ %w( 0 O l ).each{|char| default_chars.delete(char)}
65
+
66
+ chars = options.getopt(:chars, default_chars)
67
+ size = options.getopt(:chars, default_size)
68
+
69
+ Array.new(size).map{ chars[rand(2**32)%chars.size, 1] }.join
70
+ end
71
+
72
+ def snake_case(camel_cased_word)
73
+ camel_cased_word.to_s.gsub(/::/, '/').
74
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
75
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
76
+ tr("-", "_").
77
+ downcase
78
+ end
79
+
80
+ def camel_case(lower_case_and_underscored_word, first_letter_in_uppercase = true)
81
+ if first_letter_in_uppercase
82
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
83
+ else
84
+ camel_case(lower_case_and_underscored_word).sub(%r/^(.)/){ $1.downcase }
85
+ end
86
+ end
87
+
88
+ def normalize!(s)
89
+ s.to_s.gsub!(%r/\s/, ' ')
90
+ s
91
+ end
92
+
93
+ def number_for(arg)
94
+ arg = arg.to_s
95
+ arg.gsub! %r/^[0\s]+/, ''
96
+ Integer(arg) rescue Float(arg)
97
+ end
98
+
99
+ def compress(data)
100
+ writer = Zlib::GzipWriter.new(StringIO.new(result=''))
101
+ writer.write(data.to_s)
102
+ writer.close
103
+ result
104
+ end
105
+
106
+ def decompress(data)
107
+ Zlib::GzipReader.new(StringIO.new(data.to_s)).read
108
+ end
109
+
110
+ def encode(data)
111
+ Base64.encode64(compress(data))
112
+ end
113
+
114
+ def decode(data)
115
+ decompress(Base64.decode64(data.to_s))
116
+ end
117
+
118
+ extend self
119
+ end
120
+ end