gnib-ads-api 0.3

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 (75) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +121 -0
  4. data/Rakefile +38 -0
  5. data/lib/gnib-ads-api.rb +44 -0
  6. data/lib/gnib-ads-api.yml +355 -0
  7. data/lib/gnib-ads-api/api_exception.rb +42 -0
  8. data/lib/gnib-ads-api/client_proxy.rb +147 -0
  9. data/lib/gnib-ads-api/config.rb +75 -0
  10. data/lib/gnib-ads-api/constants.rb +150 -0
  11. data/lib/gnib-ads-api/data/accounts_info.rb +72 -0
  12. data/lib/gnib-ads-api/data/ad.rb +119 -0
  13. data/lib/gnib-ads-api/data/ad_group.rb +121 -0
  14. data/lib/gnib-ads-api/data/campaign.rb +40 -0
  15. data/lib/gnib-ads-api/data/report_request.rb +78 -0
  16. data/lib/gnib-ads-api/data/report_request_status.rb +48 -0
  17. data/lib/gnib-ads-api/data/reporting/account_performance_report_request.rb +176 -0
  18. data/lib/gnib-ads-api/data/reporting/campaign_performance_report_request.rb +186 -0
  19. data/lib/gnib-ads-api/data/reporting/helpers/column_helper.rb +65 -0
  20. data/lib/gnib-ads-api/data/reporting/helpers/filter_helper.rb +124 -0
  21. data/lib/gnib-ads-api/data/reporting/helpers/scope_helper.rb +51 -0
  22. data/lib/gnib-ads-api/data/reporting/helpers/time_helper.rb +69 -0
  23. data/lib/gnib-ads-api/data/reporting/performance_report_request.rb +78 -0
  24. data/lib/gnib-ads-api/data_object.rb +35 -0
  25. data/lib/gnib-ads-api/fault/ad_api_error.rb +15 -0
  26. data/lib/gnib-ads-api/fault/ad_api_fault_detail.rb +67 -0
  27. data/lib/gnib-ads-api/fault/api_fault_detail.rb +97 -0
  28. data/lib/gnib-ads-api/fault/application_fault.rb +18 -0
  29. data/lib/gnib-ads-api/fault/batch_error.rb +47 -0
  30. data/lib/gnib-ads-api/fault/operation_error.rb +22 -0
  31. data/lib/gnib-ads-api/fault/partial_errors.rb +75 -0
  32. data/lib/gnib-ads-api/service.rb +176 -0
  33. data/lib/gnib-ads-api/service/campaign_management.rb +483 -0
  34. data/lib/gnib-ads-api/service/customer_management.rb +83 -0
  35. data/lib/gnib-ads-api/service/reporting.rb +101 -0
  36. data/lib/gnib-ads-api/soap_hasheable.rb +160 -0
  37. data/lib/gnib-ads-api/version.rb +6 -0
  38. data/lib/locales/es.yml +174 -0
  39. data/lib/tasks/gnib-ads-api_tasks.rake +4 -0
  40. data/test/campaign_management_test.rb +463 -0
  41. data/test/customer_management_test.rb +44 -0
  42. data/test/data_object_test.rb +46 -0
  43. data/test/dummy/README.rdoc +261 -0
  44. data/test/dummy/Rakefile +7 -0
  45. data/test/dummy/app/assets/javascripts/application.js +15 -0
  46. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  47. data/test/dummy/app/controllers/application_controller.rb +3 -0
  48. data/test/dummy/app/helpers/application_helper.rb +2 -0
  49. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  50. data/test/dummy/config.ru +4 -0
  51. data/test/dummy/config/application.rb +56 -0
  52. data/test/dummy/config/boot.rb +10 -0
  53. data/test/dummy/config/database.yml +25 -0
  54. data/test/dummy/config/environment.rb +5 -0
  55. data/test/dummy/config/environments/development.rb +37 -0
  56. data/test/dummy/config/environments/production.rb +67 -0
  57. data/test/dummy/config/environments/test.rb +37 -0
  58. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  59. data/test/dummy/config/initializers/inflections.rb +15 -0
  60. data/test/dummy/config/initializers/mime_types.rb +5 -0
  61. data/test/dummy/config/initializers/secret_token.rb +7 -0
  62. data/test/dummy/config/initializers/session_store.rb +8 -0
  63. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  64. data/test/dummy/config/locales/en.yml +5 -0
  65. data/test/dummy/config/routes.rb +58 -0
  66. data/test/dummy/public/404.html +26 -0
  67. data/test/dummy/public/422.html +26 -0
  68. data/test/dummy/public/500.html +25 -0
  69. data/test/dummy/public/favicon.ico +0 -0
  70. data/test/dummy/script/rails +6 -0
  71. data/test/gnib-ads-api_test.rb +172 -0
  72. data/test/report_request_test.rb +312 -0
  73. data/test/reporting_test.rb +145 -0
  74. data/test/test_helper.rb +11 -0
  75. metadata +193 -0
@@ -0,0 +1,176 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module GnibAdsApi
4
+
5
+ # Public : Base class for service object
6
+ #
7
+ # Author:: jlopezn@neonline.cl
8
+ #
9
+ class Service
10
+
11
+ attr_accessor :client_proxy, :environment
12
+
13
+ # Default logger for services
14
+ LOGGER = Logger.new(STDOUT)
15
+
16
+
17
+ # Public : Constructor
18
+ #
19
+ # Author:: jlopezn@neonline.cl
20
+ #
21
+ # === Parameters
22
+ # * +options+ - Hash with autentication and environment settings
23
+ #
24
+ # === Options
25
+ # * environment - +:production+ or +:sandbox+
26
+ # * username - Bing Ads username
27
+ # * passwrod - Bing Ads user's sign-in password
28
+ # * developer_token - client application's developer access token
29
+ # * customer_id - identifier for the customer that owns the account
30
+ # * account_id - identifier of the account that own the entities in the request
31
+ # * proxy - Hash with any Client Proxy additional options (such as header, logger or enconding)
32
+ #
33
+ # === Examples
34
+ # service = GnibAdsApi::Service.new(
35
+ # :environment => :sandbox,
36
+ # :username => 'username',
37
+ # :password => 'pass',
38
+ # :developer_token => 'SOME_TOKEN',
39
+ # :account_id => 123456,
40
+ # :customer_id => 654321,
41
+ # :proxy => {:logger => Rails.logger}
42
+ # )
43
+ # # => <Service>
44
+ def initialize(options={})
45
+
46
+ # Service Environment
47
+ self.environment = options[:environment]
48
+
49
+ # ClientProxy settings
50
+ clientProxySettings = {
51
+ :username => options[:username],
52
+ :password => options[:password],
53
+ :developer_token => options[:developer_token],
54
+ :account_id => options[:account_id],
55
+ :customer_id => options[:customer_id],
56
+ :wsdl_url => options[:wdsl] || solve_wsdl_url
57
+ }
58
+
59
+ # Additionsl ClientProxy settings
60
+ clientProxySettings[:proxy] = options[:proxy] if options[:proxy]
61
+
62
+ # ClientProxy creation
63
+ self.client_proxy = GnibAdsApi::ClientProxy.new(clientProxySettings)
64
+
65
+ end
66
+
67
+
68
+ # Public : This is a utility wrapper for calling services into the
69
+ # +ClientProxy+. This methods handle all the +Novas::Client+ Exceptions
70
+ # and returns a Hash with the call response
71
+ #
72
+ # Author:: jlopezn@neonline.cl
73
+ #
74
+ # === Parameters
75
+ # +operation+ - name of the operation to be called
76
+ # +message+ - hash with the parameters to the operation
77
+ #
78
+ # === Examples
79
+ # service.call(:some_operation, {key: value})
80
+ # # => <Hash>
81
+ #
82
+ # Returns:: Hash with the result of the service call
83
+ # Raises:: ServiceError if the SOAP call, the ClientProxy fails or the response is invalid
84
+ def call(operation, message, &block)
85
+ raise "You must provide an operation" if operation.nil?
86
+ begin
87
+ LOGGER.debug "GnibAdsApi Service"
88
+ LOGGER.debug " Calling #{operation.to_s}"
89
+ LOGGER.debug " Message: #{message}"
90
+ response = self.client_proxy.call(operation.to_sym,
91
+ message: message)
92
+
93
+ LOGGER.debug "response header:"
94
+ LOGGER.debug "\t#{response.header}"
95
+
96
+ LOGGER.info "Operation #{operation.to_s} call success"
97
+ return response.hash
98
+ rescue Novas::SOAPFault => error
99
+ LOGGER.error "SOAP Error calling #{operation.to_s}: #{error.http.code}"
100
+ fault_detail = error.to_hash[:fault][:detail]
101
+ if fault_detail.key?(:api_fault_detail)
102
+ api_fault_detail = GnibAdsApi::ApiFaultDetail.new(fault_detail[:api_fault_detail])
103
+ raise GnibAdsApi::ApiException.new(
104
+ api_fault_detail, "SOAP Error calling #{operation.to_s}")
105
+ elsif fault_detail.key?(:ad_api_fault_detail)
106
+ ad_api_fault_detail = GnibAdsApi::AdApiFaultDetail.new(fault_detail[:ad_api_fault_detail])
107
+ raise GnibAdsApi::ApiException.new(
108
+ ad_api_fault_detail, "SOAP Error calling #{operation.to_s}")
109
+ else
110
+ raise
111
+ end
112
+ rescue Novas::HTTPError => error
113
+ LOGGER.error "Http Error calling #{operation.to_s}: #{error.http.code}"
114
+ raise
115
+ rescue Novas::InvalidResponseError => error
116
+ LOGGER.error "Invalid server reponse calling #{operation.to_s}"
117
+ raise
118
+ end
119
+ end
120
+
121
+
122
+ # Public : Extracts the actual response from the entire response hash.
123
+ # For example, if you specify 'AddCampaigns', this method will return
124
+ # the content of 'AddCampaignsResponse' tag as a Hash
125
+ #
126
+ # Author:: jlopezn@neonline.cl
127
+ #
128
+ # === Parameters
129
+ # response - The complete response hash received from a Operation call
130
+ # method - Name of the method of with the 'reponse' tag is require
131
+ #
132
+ # === Examples
133
+ # service.get_response_hash(Hash, 'add_campaigns')
134
+ # # => Hash
135
+ #
136
+ # Returns:: Hash with the inner structure of the method response hash
137
+ # Raises:: exception
138
+ def get_response_hash(response, method)
139
+ return response[:envelope][:body]["#{method}_response".to_sym]
140
+ end
141
+
142
+ private
143
+
144
+ # Private : This method must be overriden by specific services.
145
+ # Returns:: the service name
146
+ #
147
+ # Author:: jlopezn@neonline.cl
148
+ #
149
+ # Examples
150
+ # get_service_name
151
+ # # => "service_name"
152
+ #
153
+ # Returns:: String with the service name
154
+ # Raises:: exception if the specific Service class hasn't overriden this method
155
+ def get_service_name
156
+ raise "Should return the a service name from config.wsdl keys"
157
+ end
158
+
159
+
160
+ # Private : Solves the service WSDL URL based on his service name
161
+ # and environment values
162
+ #
163
+ # Author:: jlopezn@neonline.cl
164
+ #
165
+ # Examples
166
+ # solve_wsdl_url
167
+ # # => "https://bing.wsdl.url.com"
168
+ #
169
+ # Returns:: String with the Service url
170
+ def solve_wsdl_url
171
+ config = GnibAdsApi::Config.instance
172
+ return config.service_wsdl(environment, get_service_name)
173
+ end
174
+ end
175
+
176
+ end
@@ -0,0 +1,483 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module GnibAdsApi
3
+
4
+
5
+ # Public : This class represents the Campaign Management Services
6
+ # defined in the Bing Ads API, to manage advertising campaigns
7
+ #
8
+ # Author:: jlopezn@neonline.cl
9
+ #
10
+ # Examples
11
+ # options = {
12
+ # :environment => :sandbox,
13
+ # :username => "username",
14
+ # :password => "pass",
15
+ # :developer_token => "SOME_TOKEN",
16
+ # :customer_id => "1234567",
17
+ # :account_id => "9876543" }
18
+ # service = GnibAdsApi::CampaignManagement.new(options)
19
+ class CampaignManagement < GnibAdsApi::Service
20
+
21
+
22
+ # Public : Constructor
23
+ #
24
+ # Author:: jlopezn@neonline.cl
25
+ #
26
+ # options - Hash with the parameters for the client proxy and the environment
27
+ #
28
+ # Examples
29
+ # options = {
30
+ # :environment => :sandbox,
31
+ # :username => "username",
32
+ # :password => "password",
33
+ # :developer_token => "DEV_TOKEN",
34
+ # :customer_id => "123456",
35
+ # :account_id => "654321"
36
+ # }
37
+ # service = GnibAdsApi::CampaignManagement.new(options)
38
+ def initialize(options={})
39
+ super(options)
40
+ end
41
+
42
+
43
+ #########################
44
+ ## Operations Wrappers ##
45
+ #########################
46
+
47
+ # Public : Returns all the campaigns found in the specified account
48
+ #
49
+ # Author:: jlopezn@neonline.cl
50
+ #
51
+ # === Parameters
52
+ # account_id - account who owns the campaigns
53
+ #
54
+ # === Examples
55
+ # campaign_management_service.get_campaigns_by_account_id(1)
56
+ # # => Array[GnibAdsApi::Campaign]
57
+ #
58
+ # Returns:: Array of GnibAdsApi::Campaign
59
+ #
60
+ # Raises:: exception
61
+ def get_campaigns_by_account_id(account_id)
62
+ response = call(:get_campaigns_by_account_id,
63
+ {account_id: account_id})
64
+ response_hash = get_response_hash(response, __method__)
65
+ campaigns = response_hash[:campaigns][:campaign].map do |camp_hash|
66
+ GnibAdsApi::Campaign.new(camp_hash)
67
+ end
68
+ return campaigns
69
+ end
70
+
71
+
72
+ # Public : Adds a campaign to the specified account
73
+ #
74
+ # Author:: jlopezn@neonline.cl
75
+ #
76
+ # === Parameters
77
+ # account_id - account who will own the newly campaigns
78
+ # campaigns - An array of GnibAdsApi::Campaign
79
+ #
80
+ # === Examples
81
+ # service.add_campaigns(1, [<GnibAdsApi::Campaign>])
82
+ # # => <Hash>
83
+ #
84
+ # Returns:: hash with the 'add_campaigns_response' structure
85
+ #
86
+ # Raises:: exception
87
+ def add_campaigns(account_id, campaigns)
88
+
89
+ camps = []
90
+ if campaigns.is_a? Array
91
+ camps = campaigns.map{ |camp| camp.to_hash(:camelcase) }
92
+ elsif campaigns.is_a? GnibAdsApi::Campaign
93
+ camps = campaigns.to_hash
94
+ else
95
+ raise "campaigns must be an array of GnibAdsApi::Campaigns"
96
+ end
97
+ message = {
98
+ :account_id => account_id,
99
+ :campaigns => {:campaign => camps} }
100
+ puts message
101
+ response = call(:add_campaigns, message)
102
+ return get_response_hash(response, __method__)
103
+ end
104
+
105
+
106
+ # Public : Updates on or more campaigns for the specified account
107
+ #
108
+ # Author:: jlopezn@neonline.cl
109
+ #
110
+ # === Parameters
111
+ # account_id - account who own the updated campaigns
112
+ # campaigns - Array with the campaigns to be updated
113
+ #
114
+ # === Examples
115
+ # service_update_campaigns(1, [<GnibAdsApi::Campaign])
116
+ # # => true
117
+ #
118
+ # Returns:: boolean. true if the update was successful. false otherwise
119
+ #
120
+ # Raises:: exception
121
+ def update_campaigns(account_id, campaigns)
122
+ camps = []
123
+ if campaigns.is_a? Array
124
+ camps = campaigns.map do |camp|
125
+ camp.to_hash(:camelcase)
126
+ end
127
+ elsif campaigns.is_a? GnibAdsApi::Campaign
128
+ camps = campaigns.to_hash
129
+ else
130
+ raise "campaigns must be an array of GnibAdsApi::Campaigns"
131
+ end
132
+ message = {
133
+ :account_id => account_id,
134
+ :campaigns => {:campaign => camps} }
135
+ puts message
136
+ response = call(:update_campaigns, message)
137
+ return get_response_hash(response, __method__)
138
+
139
+ end
140
+
141
+
142
+ # Public : Returns all the ad groups that belongs to the
143
+ # specified campaign
144
+ #
145
+ # Author:: jlopezn@neonline.cl
146
+ #
147
+ # === Parameters
148
+ # campaign_id - campaign id
149
+ #
150
+ # === Examples
151
+ # service.get_ad_groups_by_campaign_id(1)
152
+ # # => Array[AdGroups]
153
+ #
154
+ # Returns:: Array with all the ad groups present in campaign_id
155
+ #
156
+ # Raises:: exception
157
+ def get_ad_groups_by_campaign_id(campaign_id)
158
+ response = call(:get_ad_groups_by_campaign_id,
159
+ {campaign_id: campaign_id})
160
+ response_hash = get_response_hash(response, __method__)
161
+ ad_groups = response_hash[:ad_groups][:ad_group].map do |ad_group_hash|
162
+ GnibAdsApi::AdGroup.new(ad_group_hash)
163
+ end
164
+ return ad_groups
165
+ end
166
+
167
+
168
+ # Public : Returns the specified ad groups that belongs to the
169
+ # specified campaign
170
+ #
171
+ # Author:: jlopezn@neonline.cl
172
+ #
173
+ # === Parameters
174
+ # campaign_id - campaign id
175
+ # ad_groups_ids - array with ids from ad groups
176
+ #
177
+ # === Examples
178
+ # service.get_ad_groups_by_ids(1, [1,2,3])
179
+ # # => Array[AdGroups]
180
+ #
181
+ # Returns:: Array with the ad groups specified in the ad_groups_ids array
182
+ #
183
+ # Raises:: exception
184
+ def get_ad_groups_by_ids(campaign_id, ad_groups_ids)
185
+
186
+ message = {
187
+ :campaign_id => campaign_id,
188
+ :ad_group_ids => {"ins1:long" => ad_groups_ids} }
189
+ response = call(:get_ad_groups_by_ids, message)
190
+ response_hash = get_response_hash(response, __method__)
191
+ ad_groups = response_hash[:ad_groups][:ad_group].map do |ad_group_hash|
192
+ GnibAdsApi::AdGroup.new(ad_group_hash)
193
+ end
194
+ return ad_groups
195
+
196
+ end
197
+
198
+
199
+ # Public : Adds 1 or more AdGroups to a Campaign
200
+ #
201
+ # Author:: jlopezn@neonline.cl
202
+ #
203
+ # === Parameters
204
+ # campaing_id - the campaign id where the ad groups will be added
205
+ # ad_groups - Array[GnibAdsApi::AdGroup] ad groups to be added
206
+ #
207
+ # === Examples
208
+ # service.add_ad_groups(1, [<GnibAdsApi::AdGroup>])
209
+ # # => <Hash>
210
+ #
211
+ # Returns:: Hash with the 'add_ad_groups_response' structure
212
+ #
213
+ # Raises:: exception
214
+ def add_ad_groups(campaign_id, ad_groups)
215
+
216
+ groups = []
217
+ if ad_groups.is_a? Array
218
+ groups = ad_groups.map{ |gr| gr.to_hash(:camelcase) }
219
+ elsif ad_groups.is_a? GnibAdsApi::AdGroup
220
+ groups = ad_groups.to_hash
221
+ else
222
+ raise "ad_groups must be an array of GnibAdsApi::AdGroup"
223
+ end
224
+ message = {
225
+ :campaign_id => campaign_id,
226
+ :ad_groups => {:ad_group => groups} }
227
+ puts message
228
+ response = call(:add_ad_groups, message)
229
+ return get_response_hash(response, __method__)
230
+ end
231
+
232
+
233
+ # Public : Updates on or more ad groups in a specified campaign
234
+ #
235
+ # Author:: jlopezn@neonline.cl
236
+ #
237
+ # === Parameters
238
+ # campaign_id - campaign who owns the updated ad groups
239
+ #
240
+ # === Examples
241
+ # service.update_ad_groups(1, [<GnibAdsApi::AdGroup])
242
+ # # => true
243
+ #
244
+ # Returns:: boolean. true if the updates is successfull. false otherwise
245
+ #
246
+ # Raises:: exception
247
+ def update_ad_groups(campaign_id, ad_groups)
248
+ groups = []
249
+ if ad_groups.is_a? Array
250
+ groups = ad_groups.map{ |gr| gr.to_hash(:camelcase) }
251
+ elsif ad_groups.is_a? GnibAdsApi::AdGroup
252
+ groups = ad_groups.to_hash(:camelcase)
253
+ else
254
+ raise "ad_groups must be an array or instance of GnibAdsApi::AdGroup"
255
+ end
256
+ message = {
257
+ :campaign_id => campaign_id,
258
+ :ad_groups => {:ad_group => groups} }
259
+ puts message
260
+ response = call(:update_ad_groups, message)
261
+ return get_response_hash(response, __method__)
262
+ end
263
+
264
+
265
+ # Public : Obtains all the ads associated to the specified ad group
266
+ #
267
+ # Author:: jlopezn@neonline.cl
268
+ #
269
+ # === Parameters
270
+ # ad_group_id - long with the ad group id
271
+ #
272
+ # === Examples
273
+ # service.get_ads_by_ad_group_id(1)
274
+ # # => [<GnibAdsApi::Ad]
275
+ #
276
+ # Returns:: An array of GnibAdsApi::Ad
277
+ #
278
+ # Raises:: exception
279
+ def get_ads_by_ad_group_id(ad_group_id)
280
+ response = call(:get_ads_by_ad_group_id,
281
+ {ad_group_id: ad_group_id})
282
+ response_hash = get_response_hash(response, __method__)
283
+
284
+ if response_hash[:ads][:ad].is_a?(Array)
285
+ ads = response_hash[:ads][:ad].map do |ad_hash|
286
+ initialize_ad(ad_hash)
287
+ end
288
+ else
289
+ ads = [ initialize_ad(response_hash[:ads][:ad]) ]
290
+ end
291
+ return ads
292
+ end
293
+
294
+
295
+ # Public : Obtains the ads indicated in ad_ids associated to the specified ad group
296
+ #
297
+ # Author:: jlopezn@neonline.cl
298
+ #
299
+ # === Parameters
300
+ # ad_group_id - long with the ad group id
301
+ # ads_id - an Array io ads ids, that are associated to the ad_group_id provided
302
+ #
303
+ # === Examples
304
+ # service.get_ads_by_ids(1, [1,2,3])
305
+ # # => [<GnibAdsApi::Ad>]
306
+ #
307
+ # Returns:: An array of GnibAdsApi::Ad
308
+ #
309
+ # Raises:: exception
310
+ def get_ads_by_ids(ad_group_id, ad_ids)
311
+
312
+
313
+ message = {
314
+ :ad_group_id => ad_group_id,
315
+ :ad_ids => {"ins1:long" => ad_ids} }
316
+ response = call(:get_ads_by_ids, message)
317
+ response_hash = get_response_hash(response, __method__)
318
+
319
+ if response_hash[:ads][:ad].is_a?(Array)
320
+ ads = response_hash[:ads][:ad].map do |ad_hash|
321
+ initialize_ad(ad_hash)
322
+ end
323
+ else
324
+ ads = [ initialize_ad(response_hash[:ads][:ad]) ]
325
+ end
326
+ return ads
327
+ end
328
+
329
+
330
+ # Public : Add ads into a specified ad group
331
+ #
332
+ # Author:: jlopezn@neonline.cl
333
+ #
334
+ # === Parameters
335
+ # ad_group_id - a number with the id where the ads should be added
336
+ # ads - an array of GnibAdsApi::Ad instances
337
+ #
338
+ # === Examples
339
+ # # if the operation returns partial errors
340
+ # service.add_ads(1, [GnibAdsApi::Ad])
341
+ # # => {:ad_ids => [], :partial_errors => GnibAdsApi::PartialErrors }
342
+ #
343
+ # # if the operation doesn't return partial errors
344
+ # service.add_ads(1, [GnibAdsApi::Ad])
345
+ # # => {:ad_ids => [] }
346
+ #
347
+ # Returns:: Hash with the AddAdsResponse structure.
348
+ # If the operation returns 'PartialErrors' key,
349
+ # this methods returns those errors as an GnibAdsApi::PartialErrors
350
+ # instance
351
+ #
352
+ # Raises:: exception
353
+ def add_ads(ad_group_id, ads)
354
+
355
+ ads_for_soap = []
356
+ if ads.is_a? Array
357
+ ads_for_soap = ads.map{ |ad| ad_to_hash(ad, :camelcase) }
358
+ elsif ads.is_a? GnibAdsApi::Ad
359
+ ads_for_soap = ad_to_hash(ads, :camelcase)
360
+ else
361
+ raise "ads must be an array or instance of GnibAdsApi::Ad"
362
+ end
363
+ message = {
364
+ :ad_group_id => ad_group_id,
365
+ :ads => {:ad => ads_for_soap} }
366
+ puts message
367
+ response = call(:add_ads, message)
368
+
369
+ response_hash = get_response_hash(response, __method__)
370
+
371
+ # Checks if there are partial errors in the request
372
+ if response_hash[:partial_errors].key?(:batch_error)
373
+ partial_errors = GnibAdsApi::PartialErrors.new(
374
+ response_hash[:partial_errors])
375
+ response_hash[:partial_errors] = partial_errors
376
+ else
377
+ response_hash.delete(:partial_errors)
378
+ end
379
+
380
+ return response_hash
381
+ end
382
+
383
+
384
+ # Public : Updates ads for the specified ad group
385
+ #
386
+ # Author:: jlopezn@neonline.cl
387
+ #
388
+ # === Parameters
389
+ # ad_group_id - long with the ad group id
390
+ # ads - array of GnibAdsApi::Ad subclasses instances to update
391
+ #
392
+ # === Examples
393
+ # service.update_ads(1, [<GnibAdsApi::Ad>])
394
+ # # => Hash
395
+ #
396
+ # Returns:: Hash with the UpdateAddsResponse structure
397
+ #
398
+ # Raises:: exception
399
+ def update_ads(ad_group_id, ads)
400
+
401
+ ads_for_soap = []
402
+ if ads.is_a? Array
403
+ ads_for_soap = ads.map{ |ad| ad_to_hash(ad, :camelcase) }
404
+ elsif ads.is_a? GnibAdsApi::Ad
405
+ ads_for_soap = ad_to_hash(ads, :camelcase)
406
+ else
407
+ raise "ads must be an array or instance of GnibAdsApi::Ad"
408
+ end
409
+ message = {
410
+ :ad_group_id => ad_group_id,
411
+ :ads => {:ad => ads_for_soap} }
412
+ puts message
413
+ response = call(:update_ads, message)
414
+
415
+ response_hash = get_response_hash(response, __method__)
416
+
417
+ # Checks if there are partial errors in the request
418
+ if response_hash[:partial_errors].key?(:batch_error)
419
+ partial_errors = GnibAdsApi::PartialErrors.new(
420
+ response_hash[:partial_errors])
421
+ response_hash[:partial_errors] = partial_errors
422
+ else
423
+ response_hash.delete(:partial_errors)
424
+ end
425
+
426
+ return response_hash
427
+ end
428
+
429
+
430
+ private
431
+ def get_service_name
432
+ "campaign_management"
433
+ end
434
+
435
+ # Private : Returns an instance of any of the subclases of GnibAdsApi::Ad based on the '@i:type' value in the hash
436
+ #
437
+ # Author:: jlopezn@neonline.cl
438
+ #
439
+ # ad_hash - Hash returned by the SOAP request with the Ad attributes
440
+ #
441
+ # Examples
442
+ # initialize_ad({:device_preference=>"0", :editorial_status=>"Active",
443
+ # :forward_compatibility_map=>{:"@xmlns:a"=>"http://schemas.datacontract.org/2004/07/System.Collections.Generic"},
444
+ # :id=>"1", :status=>"Active", :type=>"Text",
445
+ # :destination_url=>"www.some-url.com", :display_url=>"http://www.some-url.com",
446
+ # :text=>"My Page", :title=>"My Page",
447
+ # :"@i:type"=>"TextAd"})
448
+ # # => GnibAdsApi::TextAd
449
+ #
450
+ # Returns:: GnibAdsApi::Ad subclass instance
451
+ def initialize_ad(ad_hash)
452
+ ad = GnibAdsApi::Ad.new(ad_hash)
453
+ case ad_hash["@i:type".to_sym]
454
+ when "TextAd"
455
+ ad = GnibAdsApi::TextAd.new(ad_hash)
456
+ when "MobileAd"
457
+ ad = GnibAdsApi::MobileAd.new(ad_hash)
458
+ when "ProductAd"
459
+ ad = GnibAdsApi::ProductAd.new(ad_hash)
460
+ end
461
+ return ad
462
+ end
463
+
464
+
465
+ # Private : Helper method to correctly assemble the Ad XML for SOAP requests
466
+ #
467
+ # Author:: jlopezn@neonline.cl
468
+ #
469
+ # ad - GnibAdsApi::Ad subclass instance
470
+ #
471
+ # Examples
472
+ # ad_to_hash(GnibAdsApi::Ad, :camelcase)
473
+ # # => Hash
474
+ #
475
+ # Returns:: The same hash that ad.to_hash returns plus the needed key for the Ad Type
476
+ def ad_to_hash(ad, keys)
477
+ hash = ad.to_hash(keys)
478
+ hash["@xsi:type"] = self.client_proxy.class::NAMESPACE.to_s + ":" + ad.class.to_s.demodulize
479
+ return hash
480
+ end
481
+ end
482
+
483
+ end