adapi 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +3 -0
  2. data/README.markdown +176 -0
  3. data/Rakefile +32 -0
  4. data/adapi.gemspec +7 -4
  5. data/examples/add_ad_group.rb +1 -0
  6. data/examples/add_bare_ad_group.rb +2 -6
  7. data/examples/add_bare_campaign.rb +1 -0
  8. data/examples/add_campaign.rb +1 -0
  9. data/examples/add_campaign_targets.rb +1 -0
  10. data/examples/add_invalid_ad_group.rb +1 -0
  11. data/examples/add_keywords.rb +13 -1
  12. data/examples/custom_settings.yml +2 -2
  13. data/examples/customize_configuration.rb +2 -0
  14. data/examples/delete_keyword.rb +27 -0
  15. data/examples/find_all_campaigns.rb +13 -0
  16. data/examples/find_campaign.rb +39 -0
  17. data/examples/find_campaign_ad_groups.rb +25 -0
  18. data/examples/log_to_specific_account.rb +1 -0
  19. data/examples/rollback_campaign.rb +1 -0
  20. data/lib/adapi.rb +8 -5
  21. data/lib/adapi/ad.rb +2 -0
  22. data/lib/adapi/ad/text_ad.rb +15 -0
  23. data/lib/adapi/ad_group.rb +45 -6
  24. data/lib/adapi/ad_group_criterion.rb +14 -0
  25. data/lib/adapi/api.rb +6 -0
  26. data/lib/adapi/campaign.rb +48 -5
  27. data/lib/adapi/campaign_target.rb +67 -8
  28. data/lib/adapi/config.rb +1 -0
  29. data/lib/adapi/keyword.rb +78 -11
  30. data/lib/adapi/version.rb +9 -1
  31. data/lib/httpi_request_monkeypatch.rb +1 -0
  32. data/test/factories/ad_group_factory.rb +4 -13
  33. data/test/factories/ad_text_factory.rb +1 -0
  34. data/test/test_helper.rb +3 -0
  35. data/test/unit/ad/ad_text_test.rb +2 -0
  36. data/test/unit/ad_group_test.rb +11 -2
  37. data/test/unit/ad_test.rb +2 -0
  38. data/test/unit/campaign_target_test.rb +15 -0
  39. metadata +67 -32
  40. data/README.rdoc +0 -162
  41. data/lib/collection.rb +0 -429
@@ -1,429 +0,0 @@
1
- # = Collection
2
- #
3
- # Module which allows to use a proxy class for wrapping collections of all sorts.
4
- #
5
- # Let's take a collection of articles, for example (see also the test suite below).
6
- #
7
- # The collection item class could look like this:
8
- #
9
- # class Article
10
- # attr_reader :title
11
- # def initialize(title); @title = title; end
12
- # end
13
- #
14
- # The collection class could look like this, using the provided DSL:
15
- #
16
- # class ArticleCollection
17
- # include Collection
18
- #
19
- # item_class Article # 1)
20
- # item_key :title # 2)
21
- # load_collection do |*args| # 3)
22
- # args.pop.map { |title| item_class.new(title) }
23
- # end
24
- # end
25
- #
26
- # As you can see, you include the module and specify, which class should be collection items wrapped in [1],
27
- # what is the main attribute for a collection item [2], and how you would like to load the collection [3].
28
- #
29
- # Note, that you can also override the corresponding methods directly (see tests below).
30
- #
31
- # This allows to do following operations with the collection:
32
- #
33
- # articles = ArticleCollection.new ['one', 'two']
34
- #
35
- # puts "\n~~~ The collection..."
36
- # p articles
37
- #
38
- # puts "\n~~~ Last item..."
39
- # p articles.last
40
- #
41
- # puts "\n~~~ Add 'three' and 'four'..."
42
- # articles << 'three'
43
- # articles.add 'four'
44
- #
45
- # p articles
46
- #
47
- # puts "\n~~~ Deleting 'three' and 'four'..."
48
- # articles >> 'three'
49
- # articles.delete Article.new('four')
50
- #
51
- # p articles
52
- #
53
- # puts "\n~~~ Iteration..."
54
- # articles.each_with_index do |a, i|
55
- # puts "#{i+1}. #{a.title}"
56
- # end
57
- #
58
- # puts "\n~~~ Mapping..."
59
- # p articles.map { |a| a.title }
60
- #
61
- # puts "\n~~~ Accessors..."
62
- # p articles['one']
63
- # p articles.find 'two'
64
- #
65
- # puts "\n~~~ Size..."
66
- # p articles.size
67
- #
68
- # You may want to customize adding/removing items to the collection, for example.
69
- #
70
- # That's easy: just re-implement the `<<` or `>>` methods with custom logic, and call `super()`:
71
- #
72
- # def << item
73
- # return false unless Tag.new(:article => @article, :value => item).valid?
74
- #
75
- # @article.tags = super(:article => @article, :value => item)
76
- # self
77
- # end
78
- # alias :add :<<
79
- #
80
- # -----------------------------------
81
- # (c) 2001 Karel Minarik; MIT License
82
- #
83
- module Collection
84
- include Enumerable
85
-
86
- def self.included(base)
87
- base.extend DSL
88
- base.class_eval do
89
- def self.method_added(name)
90
- case name
91
- when :<< then alias_method :add, name
92
- when :>> then alias_method :delete, name
93
- when :[] then alias_method :find, name
94
- end
95
- end
96
- end
97
- end
98
-
99
- module DSL
100
-
101
- def item_class klass=nil
102
- klass ? @item_class = klass : @item_class
103
- end
104
-
105
- def item_key key=nil
106
- key ? @item_key = key : @item_key
107
- end
108
-
109
- def load_collection &block
110
- block_given? ? @load_collection = block : @load_collection
111
- end
112
-
113
- end
114
-
115
- def initialize(*args)
116
- if self.class.instance_variable_defined?(:@load_collection)
117
- @collection = load_collection.call(*args)
118
- else
119
- @collection = load_collection(*args)
120
- end
121
- end
122
-
123
- def << item
124
- item = item_class.new(item) unless item.is_a? item_class
125
- @collection << item
126
- self
127
- end
128
- alias :add :<<
129
-
130
- def >> item
131
- item = item.send(item_key) if item.respond_to? item_key
132
- @collection.reject! { |a| a.send(item_key) == item }
133
- self
134
- end
135
- alias :delete :>>
136
-
137
- def [] key
138
- @collection.select { |a| a.send(item_key) == key }.first
139
- end
140
- alias :find :[]
141
-
142
- def last
143
- @collection.reverse.first
144
- end
145
-
146
- def <=> other
147
- self <=> other
148
- end
149
-
150
- def each(&block)
151
- @collection.each(&block)
152
- end
153
-
154
- def include? value
155
- @collection.any? { |i| i.send(item_key) == value }
156
- end
157
-
158
- def empty?
159
- @collection.empty?
160
- end
161
-
162
- def to_a
163
- @collection.map { |i| i.send(item_key) }
164
- end
165
-
166
- def size
167
- @collection.size
168
- end
169
-
170
- def inspect
171
- %Q|<#{self.class.name} #{@collection.inspect}>|
172
- end
173
-
174
- def load_collection
175
- self.class.load_collection ||
176
- raise(NoMethodError, "Please implement 'load_collection' method in your collection class")
177
- end
178
-
179
- def item_class
180
- self.class.item_class ||
181
- raise(NoMethodError, "Please implement 'item_class' method in your collection class")
182
- end
183
-
184
- def item_key
185
- self.class.item_key ||
186
- raise(NoMethodError, "Please implement 'item_key' method in your collection class")
187
- end
188
-
189
- end
190
-
191
-
192
- if $0 == __FILE__
193
- require 'rubygems'
194
- require 'test/unit'
195
- require 'shoulda'
196
- require 'mocha'
197
-
198
- class CollectionTest < Test::Unit::TestCase
199
-
200
- context "Collection module" do
201
-
202
- setup { class MyCollection; include Collection; end }
203
-
204
- should "have abstract methods" do
205
- assert_raise(NoMethodError) do
206
- MyCollection.new.load_collection
207
- MyCollection.new.item_class
208
- MyCollection.new.item_key
209
- end
210
- end
211
-
212
- should "pass arguments from initialize to load_collection" do
213
- list = ['one', 'two']
214
- MyCollection.any_instance.expects(:load_collection).with( list ).returns( list )
215
-
216
- MyCollection.new list
217
- end
218
-
219
- should "be iterable" do
220
- MyCollection.any_instance.stubs(:load_collection).returns( [] )
221
-
222
- assert_respond_to MyCollection.new, :each
223
- assert_respond_to MyCollection.new, :size
224
- assert_respond_to MyCollection.new, :empty?
225
- end
226
-
227
- end
228
-
229
- context "Collection module included" do
230
-
231
- setup do
232
- class Article
233
- attr_reader :title
234
- def initialize(title); @title = title; end
235
- end
236
-
237
- class ArticleCollection
238
- include Collection
239
-
240
- item_class Article
241
- item_key :title
242
- load_collection do |*args|
243
- args.pop.map { |title| item_class.new(title) }
244
- end
245
- end
246
-
247
- @articles = ArticleCollection.new ['One', 'Two']
248
- end
249
-
250
- should "set item_class" do
251
- assert_equal Article, @articles.item_class
252
- end
253
-
254
- should "set item_key" do
255
- assert_equal :title, @articles.item_key
256
- end
257
-
258
- should "load the collection" do
259
- assert_equal 2, @articles.size
260
- assert_same_elements ['One', 'Two'], @articles.to_a
261
- end
262
-
263
- should "walk like an Enumerable" do
264
- assert_same_elements ['One', 'Two'], @articles.map { |a| a.title }
265
- end
266
-
267
- should "answer to empty?" do
268
- assert ! @articles.empty?
269
- end
270
-
271
- should "return size" do
272
- assert_equal 2, @articles.size
273
- end
274
-
275
- should "return first" do
276
- assert_equal 'One', @articles.first.title
277
- end
278
-
279
- should "return last" do
280
- assert_equal 'Two', @articles.last.title
281
- end
282
-
283
- should "add item by key" do
284
- assert @articles << 'Three'
285
- assert_equal 3, @articles.size
286
- end
287
-
288
- should "add item instance" do
289
- assert @articles << Article.new('Three')
290
- assert_equal 3, @articles.size
291
- assert_equal 'Three', @articles.last.title
292
- end
293
-
294
- should "remove item by key" do
295
- assert @articles >> 'Two'
296
- assert_equal 1, @articles.size
297
- end
298
-
299
- should "remove item instance" do
300
- assert @articles >> Article.new('Two')
301
- assert_equal 1, @articles.size
302
- assert_equal 'One', @articles.last.title
303
- end
304
-
305
- should "get item by key" do
306
- assert_not_nil @articles['One']
307
- assert_equal 'One', @articles['One'].title
308
- end
309
-
310
- should "query for item by key" do
311
- assert @articles.include?('One'), "#{@articles.inspect} should contain 'One'"
312
- assert ! @articles.include?('FourtyTwo'), "#{@articles.inspect} should NOT contain 'FourtyTwo'"
313
- end
314
-
315
- should "serialize collection to an Array, by key" do
316
- assert_same_elements ['One', 'Two'], @articles.to_a
317
- end
318
-
319
- should "have aliases" do
320
- assert_respond_to @articles, :add
321
- assert_respond_to @articles, :delete
322
- assert_respond_to @articles, :find
323
- end
324
-
325
- end
326
-
327
- context "Collection module used without DSL" do
328
-
329
- setup do
330
- class Article
331
- attr_reader :title
332
- def initialize(title); @title = title; end
333
- end
334
-
335
- class NoDSLArticleCollection
336
- include Collection
337
-
338
- def load_collection(*args); args.pop.map { |title| item_class.new(title) }; end
339
- def item_class; Article; end
340
- def item_key; :title; end
341
- end
342
-
343
- @articles = NoDSLArticleCollection.new ['One', 'Two']
344
- end
345
-
346
- should "set item_class" do
347
- assert_equal Article, @articles.item_class
348
- end
349
-
350
- should "set item_key" do
351
- assert_equal :title, @articles.item_key
352
- end
353
-
354
- should "load the collection" do
355
- assert_equal 2, @articles.size
356
- assert_same_elements ['One', 'Two'], @articles.to_a
357
- end
358
-
359
- end
360
-
361
- context "Collection with customized manipulation methods" do
362
-
363
- setup do
364
- class Article
365
- attr_reader :title
366
- def initialize(title); @title = title; end
367
- end
368
-
369
- class ArticleCollection
370
- include Collection
371
-
372
- item_class Article
373
- item_key :title
374
- load_collection do |*args|
375
- args.pop.map { |title| item_class.new(title) }
376
- end
377
-
378
- def << item
379
- return false if item == 'foo'
380
- super
381
- end
382
-
383
- def >> item
384
- raise "Foorbidden!" if item == 'foo'
385
- super
386
- end
387
-
388
- def [] item
389
- return nil if item == 'One'
390
- super
391
- end
392
-
393
- end
394
-
395
- @articles = ArticleCollection.new ['One', 'Two']
396
- end
397
-
398
- should "return false when adding adding 'foo'" do
399
- assert ! (@articles << 'foo')
400
- assert_equal 2, @articles.size
401
- end
402
-
403
- should "raise exception when trying to remove 'foo'" do
404
- assert_raise(RuntimeError) do
405
- @articles >> 'foo'
406
- assert_equal 2, @articles.size
407
- end
408
- end
409
-
410
- should "have alias for add" do
411
- assert ! @articles.add('foo')
412
- assert_equal 2, @articles.size
413
- end
414
-
415
- should "have alias for delete" do
416
- assert_raise(RuntimeError) do
417
- @articles.delete('foo')
418
- assert_equal 2, @articles.size
419
- end
420
- end
421
-
422
- should "have alias for find" do
423
- assert_nil @articles.find('One')
424
- end
425
-
426
- end
427
-
428
- end
429
- end