sem4r 0.1.1 → 0.1.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.
- data/Gemfile +11 -0
- data/Gemfile.lock +36 -0
- data/README.rdoc +30 -0
- data/Rakefile +15 -12
- data/VERSION.yml +1 -1
- data/examples_blog/2009-11-29-hello-world.rb +0 -1
- data/examples_sem4r/01_get_account.rb +1 -1
- data/examples_sem4r/02_get_info.rb +6 -2
- data/examples_sem4r/03_list_ad.rb +1 -1
- data/examples_sem4r/04_list_keywords.rb +1 -1
- data/examples_sem4r/05_request_report.rb +1 -2
- data/examples_sem4r/05_request_report_2010.rb +19 -4
- data/examples_sem4r/06_create_campaigns.rb +1 -1
- data/examples_sem4r/07_create_campaigns_block.rb +1 -1
- data/examples_sem4r/07_create_campaigns_simple.rb +1 -1
- data/examples_sem4r/08_ad_params.rb +1 -1
- data/examples_sem4r/09_targeting_idea.rb +1 -1
- data/examples_sem4r/10_get_location.rb +1 -1
- data/examples_sem4r/11_submit_bulk_job.rb +1 -1
- data/examples_sem4r/12_list_bulk_job.rb +1 -1
- data/examples_sem4r/30_prune_empty_adgroup.rb +1 -1
- data/examples_sem4r/31_empty_accounts.rb +1 -1
- data/examples_sem4r/example_helper.rb +5 -10
- data/lib/sem4r/account.rb +3 -306
- data/lib/sem4r/ad_group/ad_group.rb +16 -14
- data/lib/sem4r/ad_group/ad_group_bids.rb +11 -10
- data/lib/sem4r/ad_group/ad_group_service.rb +5 -5
- data/lib/sem4r/ad_group_ad/ad_group_ad.rb +1 -1
- data/lib/sem4r/ad_group_ad/ad_group_ad_service.rb +5 -5
- data/lib/sem4r/ad_group_ad/ad_group_mobile_ad.rb +9 -9
- data/lib/sem4r/ad_group_ad/ad_group_text_ad.rb +9 -9
- data/lib/sem4r/ad_group_criterion/ad_group_criterion.rb +6 -6
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_bids.rb +5 -6
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_operations.rb +0 -1
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_service.rb +4 -4
- data/lib/sem4r/ad_group_criterion/criterion.rb +3 -3
- data/lib/sem4r/ad_group_criterion/criterion_keyword.rb +3 -3
- data/lib/sem4r/ad_group_criterion/criterion_placement.rb +2 -2
- data/lib/sem4r/ad_param/ad_param.rb +3 -3
- data/lib/sem4r/ad_param/ad_param_service.rb +5 -5
- data/lib/sem4r/adwords.rb +1 -0
- data/lib/sem4r/api_counters.rb +1 -0
- data/lib/sem4r/base.rb +1 -0
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job.rb +2 -2
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_account_extension.rb +59 -0
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_service.rb +5 -5
- data/lib/sem4r/campaign/campaign.rb +10 -10
- data/lib/sem4r/campaign/campaign_account_extension.rb +87 -0
- data/lib/sem4r/campaign/campaign_service.rb +6 -6
- data/lib/sem4r/campaign_target/campaign_target_service.rb +22 -22
- data/lib/sem4r/cli/cli_command.rb +1 -0
- data/lib/sem4r/cli/cli_common_args.rb +10 -3
- data/lib/sem4r/cli/cli_helpers.rb +1 -0
- data/lib/sem4r/cli/cli_sem.rb +1 -0
- data/lib/sem4r/cli/{cli_download_report.rb → commands/cli_download_report.rb} +2 -1
- data/lib/sem4r/cli/{cli_ideas.rb → commands/cli_ideas.rb} +1 -0
- data/lib/sem4r/cli/{cli_commands.rb → commands/cli_info.rb} +3 -23
- data/lib/sem4r/cli/{cli_list_ads.rb → commands/cli_list_ads.rb} +1 -0
- data/lib/sem4r/cli/commands/cli_list_campaign.rb +35 -0
- data/lib/sem4r/cli/commands/cli_list_client.rb +36 -0
- data/lib/sem4r/cli/{cli_list_keywords.rb → commands/cli_list_keywords.rb} +1 -0
- data/lib/sem4r/cli/commands/cli_list_report.rb +34 -0
- data/lib/sem4r/cli/commands/cli_repdef.rb +109 -0
- data/lib/sem4r/cli/commands/cli_report.rb +78 -0
- data/lib/sem4r/cli/{cli_request_report.rb → commands/cli_request_report.rb} +1 -0
- data/lib/sem4r/credentials.rb +1 -0
- data/lib/sem4r/extensions.rb +22 -1
- data/lib/sem4r/geo_location/geo_location_account_extension.rb +43 -0
- data/lib/sem4r/geo_location/geo_location_service.rb +4 -4
- data/lib/sem4r/info/info_account_extension.rb +48 -0
- data/lib/sem4r/info/info_selector.rb +108 -0
- data/lib/sem4r/info/info_service.rb +11 -66
- data/lib/sem4r/{common/operation.rb → operation.rb} +3 -1
- data/lib/sem4r/report_definition/report_definition.rb +75 -15
- data/lib/sem4r/report_definition/report_definition_account_extension.rb +79 -0
- data/lib/sem4r/report_definition/report_definition_operation.rb +3 -1
- data/lib/sem4r/report_definition/report_definition_service.rb +7 -7
- data/lib/sem4r/report_definition/report_field.rb +57 -0
- data/lib/sem4r/sem4r_error.rb +1 -0
- data/lib/sem4r/services/http_connector.rb +93 -0
- data/lib/sem4r/services/service.rb +1 -1
- data/lib/sem4r/services/soap_call.rb +27 -5
- data/lib/sem4r/services/soap_connector.rb +2 -147
- data/lib/sem4r/services/soap_dumper.rb +105 -0
- data/lib/sem4r/services/soap_message_v13.rb +15 -9
- data/lib/sem4r/services/{soap_message_v2009.rb → soap_message_v2010.rb} +26 -12
- data/lib/sem4r/targeting_idea/targeting_idea.rb +16 -11
- data/lib/sem4r/targeting_idea/targeting_idea_account_extension.rb +52 -0
- data/lib/sem4r/targeting_idea/targeting_idea_selector.rb +36 -10
- data/lib/sem4r/targeting_idea/targeting_idea_service.rb +5 -5
- data/lib/sem4r/v13_account/account_account_extension.rb +103 -0
- data/lib/sem4r/v13_account/billing_address.rb +10 -21
- data/lib/sem4r/v13_report/report.rb +8 -8
- data/lib/sem4r/v13_report/report_account_extension.rb +63 -0
- data/lib/sem4r/v13_report/report_job.rb +1 -1
- data/lib/sem4r.rb +27 -6
- data/lib/sem4r_cli.rb +4 -6
- data/lib/{sem4r → soap_helpers}/soap_attributes.rb +105 -13
- data/sem4r.gemspec +229 -190
- data/spec/{aggregates_spec_helper.rb → aggregates_rspec_helper.rb} +0 -0
- data/spec/build_fixtures.rb +84 -0
- data/spec/rspec_hash.rb +66 -0
- data/spec/{spec_helper.rb → rspec_helper.rb} +4 -2
- data/spec/rspec_matchers.rb +102 -0
- data/spec/rspec_sem4r_helper.rb +88 -0
- data/spec/sem4r/account_spec.rb +3 -4
- data/spec/sem4r/ad_group/ad_group_bids_spec.rb +4 -3
- data/spec/sem4r/ad_group/ad_group_service_spec.rb +8 -7
- data/spec/sem4r/ad_group/ad_group_spec.rb +5 -4
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-first-req.xml +0 -0
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-first-res.xml +0 -0
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-manual-cpm-bids-req.xml +0 -0
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-manual-cpm-bids-res.xml +0 -0
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/mutate_add-req.xml +0 -0
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/mutate_add-res.xml +0 -0
- data/spec/sem4r/ad_group_ad/ad_group_ad_operation_spec.rb +3 -3
- data/spec/sem4r/ad_group_ad/ad_group_ad_service_spec.rb +6 -5
- data/spec/sem4r/ad_group_ad/ad_group_ad_spec.rb +6 -5
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_mobile_ad-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_mobile_ad-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_text_ad-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_text_ad-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_mobile_ad-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_mobile_ad-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_text_ad-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_text_ad-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_two_criterions-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_two_criterions-res.xml +0 -0
- data/spec/sem4r/ad_group_criterion/ad_group_criterion_bids_spec.rb +5 -4
- data/spec/sem4r/ad_group_criterion/ad_group_criterion_service_spec.rb +6 -5
- data/spec/sem4r/ad_group_criterion/ad_group_criterion_spec.rb +6 -5
- data/spec/sem4r/ad_group_criterion/criterion_spec.rb +5 -4
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/get-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/get-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_keyword-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_keyword-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_placement-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_placement-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_negative_keyword-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_negative_keyword-res.xml +0 -0
- data/spec/sem4r/ad_param/ad_param_service_spec.rb +6 -5
- data/spec/sem4r/ad_param/ad_param_spec.rb +3 -2
- data/spec/{fixtures/services/ad_param → sem4r/ad_param/fixtures}/mutate_set-req.xml +0 -0
- data/spec/{fixtures/services/ad_param → sem4r/ad_param/fixtures}/mutate_set-res.xml +0 -0
- data/spec/sem4r/adwords_spec.rb +1 -1
- data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_service_spec.rb +6 -5
- data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_spec.rb +4 -3
- data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/get-req.xml +0 -0
- data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/get-res.xml +0 -0
- data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/mutate-req.xml +0 -0
- data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/mutate-res.xml +0 -0
- data/spec/sem4r/bulk_mutate_job/job_operation_spec.rb +3 -2
- data/spec/sem4r/campaign/campaign_service_spec.rb +8 -7
- data/spec/sem4r/campaign/campaign_spec.rb +3 -2
- data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/get-req.xml +0 -0
- data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/get-res.xml +0 -0
- data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/mutate_add-req.xml +0 -0
- data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/mutate_add-res.xml +0 -0
- data/spec/sem4r/cli/cli_spec.rb +2 -3
- data/spec/sem4r/credentials_spec.rb +1 -1
- data/spec/sem4r/info/account_info_extension_spec.rb +51 -0
- data/spec/sem4r/info/fixtures/get_unit_count-req.xml +34 -0
- data/spec/sem4r/info/fixtures/get_unit_count-res.xml +27 -0
- data/spec/sem4r/nokogiri_parsing_spec.rb +105 -0
- data/spec/{fixtures/services/report_definition → sem4r/report_definition/fixtures}/mutate_add-req.xml +0 -0
- data/spec/{fixtures/services/report_definition → sem4r/report_definition/fixtures}/mutate_add-req_orig.xml +0 -0
- data/spec/sem4r/report_definition/report_definition_service_spec.rb +5 -3
- data/spec/sem4r/report_definition/report_definition_spec.rb +6 -3
- data/spec/sem4r/rexml_parsing_spec.rb +22 -22
- data/spec/sem4r/services/service_spec.rb +2 -1
- data/spec/sem4r/services/soap_call_spec.rb +6 -5
- data/spec/sem4r/services/soap_message_v13_spec.rb +5 -11
- data/spec/{fixtures/services/targeting_idea → sem4r/targeting_idea/fixtures}/get-req-all-options.xml +0 -0
- data/spec/{fixtures/services/targeting_idea → sem4r/targeting_idea/fixtures}/get-req.xml +9 -11
- data/spec/sem4r/targeting_idea/fixtures/get-res.xml +2276 -0
- data/spec/sem4r/targeting_idea/targeting_idea_selector_spec.rb +30 -11
- data/spec/sem4r/targeting_idea/targeting_idea_service_spec.rb +4 -3
- data/spec/sem4r/targeting_idea/targeting_idea_spec.rb +5 -4
- data/spec/sem4r/v13_account/account_account_extension_spec.rb +47 -0
- data/spec/sem4r/v13_account/account_service_spec.rb +6 -5
- data/spec/sem4r/v13_account/billing_address_spec.rb +40 -0
- data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_account_info-req.xml +0 -0
- data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_account_info-res.xml +0 -0
- data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_client_accounts-req.xml +0 -0
- data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_client_accounts-res.xml +0 -0
- data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/get_all_jobs-req.xml +0 -0
- data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/get_all_jobs-res.xml +2 -2
- data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/schedule_report_job-req.xml +0 -0
- data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/schedule_report_job-res.xml +0 -0
- data/spec/sem4r/v13_report/report_service_spec.rb +13 -11
- data/spec/sem4r/v13_report/report_spec.rb +4 -3
- data/spec/sem4r_stubs.rb +182 -0
- data/spec/soap_helpers/soap_attributes_spec.rb +129 -0
- metadata +225 -125
- data/spec/fixtures/services/info/get_unit_count-req.xml +0 -30
- data/spec/fixtures/services/info/get_unit_count-res.xml +0 -29
- data/spec/fixtures/services/targeting_idea/get-res.xml +0 -3601
- data/spec/sem4r/soap_attributes_spec.rb +0 -116
- data/spec/sem4r_spec_helper.rb +0 -353
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -------------------------------------------------------------------------
|
|
3
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
# a copy of this software and associated documentation files (the
|
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
# the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be
|
|
14
|
+
# included in all copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
#
|
|
24
|
+
# -------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
module Sem4r
|
|
27
|
+
class CliRepDef < CliCommand
|
|
28
|
+
|
|
29
|
+
def self.command
|
|
30
|
+
"repdef"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.description
|
|
34
|
+
"report definition"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def initialize(common_args)
|
|
38
|
+
@common_args = common_args
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def command_opt_parser(options)
|
|
42
|
+
opt_parser = OptionParser.new
|
|
43
|
+
opt_parser.banner = "Usage #{self.class.command} [command_options ] [fields|list|create]"
|
|
44
|
+
opt_parser.separator ""
|
|
45
|
+
opt_parser.separator "#{self.class.description}"
|
|
46
|
+
opt_parser.on("-h", "--help", "show this message") do
|
|
47
|
+
puts opt_parser
|
|
48
|
+
options.exit = true
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def parse_and_run(argv)
|
|
53
|
+
options = OpenStruct.new
|
|
54
|
+
rest = command_opt_parser(options).parse( argv )
|
|
55
|
+
if options.exit
|
|
56
|
+
return false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if rest.empty?
|
|
60
|
+
puts "missing command"
|
|
61
|
+
return false
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
account = @common_args.account
|
|
65
|
+
|
|
66
|
+
case rest[0]
|
|
67
|
+
|
|
68
|
+
when "fields"
|
|
69
|
+
account.report_fields.each do |f|
|
|
70
|
+
puts f.to_s
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
when "list"
|
|
74
|
+
account.p_report_definitions
|
|
75
|
+
|
|
76
|
+
when "delete"
|
|
77
|
+
report_definition_id = rest[1]
|
|
78
|
+
account.report_definition_delete(report_definition_id)
|
|
79
|
+
|
|
80
|
+
when "create"
|
|
81
|
+
rd = account.report_definition do
|
|
82
|
+
name "Keywords performance report #1290336379254"
|
|
83
|
+
type "KEYWORDS_PERFORMANCE_REPORT"
|
|
84
|
+
date_range "CUSTOM_DATE"
|
|
85
|
+
from "20100101"
|
|
86
|
+
to "20100110"
|
|
87
|
+
format "CSV"
|
|
88
|
+
|
|
89
|
+
field "AdGroupId"
|
|
90
|
+
field "Id"
|
|
91
|
+
field "KeywordText"
|
|
92
|
+
field "KeywordMatchType"
|
|
93
|
+
field "Impressions"
|
|
94
|
+
field "Clicks"
|
|
95
|
+
field "Cost"
|
|
96
|
+
end
|
|
97
|
+
rd.save
|
|
98
|
+
puts rd.id
|
|
99
|
+
puts rd.to_s
|
|
100
|
+
account.p_report_definitions
|
|
101
|
+
else
|
|
102
|
+
puts "unknow command"
|
|
103
|
+
end
|
|
104
|
+
account.adwords.p_counters
|
|
105
|
+
true
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -------------------------------------------------------------------------
|
|
3
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
# a copy of this software and associated documentation files (the
|
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
# the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be
|
|
14
|
+
# included in all copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
#
|
|
24
|
+
# -------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
module Sem4r
|
|
27
|
+
class CliReport < CliCommand
|
|
28
|
+
|
|
29
|
+
def self.command
|
|
30
|
+
"report"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.description
|
|
34
|
+
"manage report"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def initialize(common_args)
|
|
38
|
+
@common_args = common_args
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def command_opt_parser(options)
|
|
42
|
+
opt_parser = OptionParser.new
|
|
43
|
+
opt_parser.banner = "Usage #{self.class.command} [command_options ] [fields|list|create]"
|
|
44
|
+
opt_parser.separator ""
|
|
45
|
+
opt_parser.separator "#{self.class.description}"
|
|
46
|
+
opt_parser.on("-h", "--help", "show this message") do
|
|
47
|
+
puts opt_parser
|
|
48
|
+
options.exit = true
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def parse_and_run(argv)
|
|
53
|
+
options = OpenStruct.new
|
|
54
|
+
rest = command_opt_parser(options).parse( argv )
|
|
55
|
+
if options.exit
|
|
56
|
+
return false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if rest.length != 1
|
|
60
|
+
puts "missing command"
|
|
61
|
+
return false
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
account = @common_args.account
|
|
65
|
+
|
|
66
|
+
case rest[0]
|
|
67
|
+
when "list"
|
|
68
|
+
Sem4r::report(account.reports, :id, :name, :status)
|
|
69
|
+
|
|
70
|
+
else
|
|
71
|
+
puts "unknow command"
|
|
72
|
+
end
|
|
73
|
+
account.adwords.p_counters
|
|
74
|
+
true
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
end
|
data/lib/sem4r/credentials.rb
CHANGED
data/lib/sem4r/extensions.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
1
2
|
module Sem4r #:nodoc:
|
|
2
3
|
module CoreExtensions #:nodoc:
|
|
3
4
|
module Hash #:nodoc:
|
|
@@ -47,16 +48,36 @@ module Sem4r #:nodoc:
|
|
|
47
48
|
end
|
|
48
49
|
|
|
49
50
|
#
|
|
50
|
-
#
|
|
51
|
+
# Sem4r
|
|
51
52
|
#
|
|
52
53
|
def assert_check_keys(*mkeys)
|
|
53
54
|
missing_keys = [mkeys].flatten - keys
|
|
54
55
|
raise(ArgumentError, "Missing key(s): #{missing_keys.join(", ")}") unless missing_keys.empty?
|
|
55
56
|
end
|
|
56
57
|
end
|
|
58
|
+
|
|
59
|
+
# Rails' ActiveSupport
|
|
60
|
+
module String #:nodoc:
|
|
61
|
+
def underscore
|
|
62
|
+
# strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $class_name))
|
|
63
|
+
self.gsub(/::/, '/').
|
|
64
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
|
65
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
|
66
|
+
tr("-", "_").
|
|
67
|
+
downcase
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def camel_case
|
|
71
|
+
self.gsub(/_([a-z])/) { $1.upcase }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
57
74
|
end
|
|
58
75
|
end
|
|
59
76
|
|
|
60
77
|
class Hash #:nodoc:
|
|
61
78
|
include Sem4r::CoreExtensions::Hash
|
|
62
79
|
end
|
|
80
|
+
|
|
81
|
+
class String
|
|
82
|
+
include Sem4r::CoreExtensions::String
|
|
83
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#
|
|
23
|
+
# -------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
module Sem4r
|
|
26
|
+
|
|
27
|
+
module GeoLocationAccountExtension
|
|
28
|
+
############################################################################
|
|
29
|
+
# Geo Location
|
|
30
|
+
|
|
31
|
+
def geo_location
|
|
32
|
+
soap_message = service.geo_location.get(@credentials, "")
|
|
33
|
+
add_counters( soap_message.counters )
|
|
34
|
+
# cost = REXML::XPath.first( soap_message.response, "//getResponse/rval/cost")
|
|
35
|
+
# cost.text.to_i
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class Account
|
|
40
|
+
include GeoLocationAccountExtension
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
@@ -28,14 +28,14 @@ module Sem4r
|
|
|
28
28
|
def initialize(connector)
|
|
29
29
|
@connector = connector
|
|
30
30
|
|
|
31
|
-
@header_namespace = "https://adwords.google.com/api/adwords/cm/
|
|
31
|
+
@header_namespace = "https://adwords.google.com/api/adwords/cm/v201008"
|
|
32
32
|
@service_namespace = @header_namespace
|
|
33
33
|
|
|
34
|
-
@sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/cm/
|
|
35
|
-
@production_service_url = "https://adwords.google.com/api/adwords/cm/
|
|
34
|
+
@sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/cm/v201008/GeoLocationService"
|
|
35
|
+
@production_service_url = "https://adwords.google.com/api/adwords/cm/v201008/GeoLocationService"
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
soap_call_v2010 :get
|
|
39
39
|
|
|
40
40
|
################
|
|
41
41
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#
|
|
23
|
+
# -------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
module Sem4r
|
|
26
|
+
|
|
27
|
+
module AccountInfoExtension
|
|
28
|
+
|
|
29
|
+
def year_unit_cost(usage_type)
|
|
30
|
+
now = Time.new
|
|
31
|
+
selector = InfoSelector.new do
|
|
32
|
+
usage_type usage_type
|
|
33
|
+
min now.strftime("%Y0101") # first January
|
|
34
|
+
max now.strftime("%Y%m%d")
|
|
35
|
+
end
|
|
36
|
+
soap_message = service.info.get(@credentials, selector.to_xml)
|
|
37
|
+
add_counters( soap_message.counters )
|
|
38
|
+
# cost = REXML::XPath.first( soap_message.response, "//getResponse/rval/cost")
|
|
39
|
+
cost = soap_message.response.at_xpath("//getResponse/rval/cost")
|
|
40
|
+
cost.text.to_i
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class Account
|
|
45
|
+
include AccountInfoExtension
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#
|
|
23
|
+
# -------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
module Sem4r
|
|
26
|
+
|
|
27
|
+
############################################################################
|
|
28
|
+
# Info Service
|
|
29
|
+
|
|
30
|
+
# FREE_USAGE_API_UNITS_PER_MONTH
|
|
31
|
+
# Retrieves the number of free API units that can be used by the developer
|
|
32
|
+
# token being used to make the call for this month.
|
|
33
|
+
# Specify only the apiUsageType parameter.
|
|
34
|
+
#
|
|
35
|
+
# TOTAL_USAGE_API_UNITS_PER_MONTH
|
|
36
|
+
# Retrieves the total number of API units for this entire month that can
|
|
37
|
+
# be used by the developer token being used to make this call. Includes
|
|
38
|
+
# both free and paid API units.
|
|
39
|
+
# Specify only the apiUsageType parameter.
|
|
40
|
+
#
|
|
41
|
+
# OPERATION_COUNT
|
|
42
|
+
# Retrieves the number of operations recorded for the developer token
|
|
43
|
+
# being used to make this call over the given date range.
|
|
44
|
+
# The given dates
|
|
45
|
+
# are inclusive; to get the operation count for a single day, supply it as
|
|
46
|
+
# both the start and end date.
|
|
47
|
+
# Specify the apiUsageType and dateRange parameters.
|
|
48
|
+
#
|
|
49
|
+
# UNIT_COUNT
|
|
50
|
+
# Retrieves the number of API units recorded for the developer token being
|
|
51
|
+
# used to make this call.
|
|
52
|
+
# o Specify the apiUsageType and dateRange parameters to retrieve
|
|
53
|
+
# the units recorded over the given date range.
|
|
54
|
+
# o Specify the apiUsageType, serviceName, methodName, operator,
|
|
55
|
+
# dateRange to retrieve the units recorded over the given date
|
|
56
|
+
# range for a specified method.
|
|
57
|
+
#
|
|
58
|
+
# UNIT_COUNT_FOR_CLIENTS
|
|
59
|
+
# Retrieves the number of API units recorded for a subset of clients over
|
|
60
|
+
# the given date range for the developer token being used to make this
|
|
61
|
+
# call.
|
|
62
|
+
# The given dates are inclusive; to get the unit count for a single
|
|
63
|
+
# day, supply it as both the start and end date.
|
|
64
|
+
# Specify the apiUsageType, dateRange and clientEmails parameters.
|
|
65
|
+
#
|
|
66
|
+
# METHOD_COST
|
|
67
|
+
# Retrieves the cost, in API units per operation, of the given method on
|
|
68
|
+
# a specific date for the developer token being used to make this call.
|
|
69
|
+
#
|
|
70
|
+
# Methods default to a cost of 1. Specify the apiUsageType, dateRange
|
|
71
|
+
# (start date and end date should be the same), serviceName, methodName,
|
|
72
|
+
# operator parameters.
|
|
73
|
+
|
|
74
|
+
class InfoSelector
|
|
75
|
+
include SoapAttributes
|
|
76
|
+
|
|
77
|
+
enum :UsageTypes, [
|
|
78
|
+
:FREE_USAGE_API_UNITS_PER_MONTH,
|
|
79
|
+
:UNIT_COUNT,
|
|
80
|
+
:TOTAL_USAGE_API_UNITS_PER_MONTH,
|
|
81
|
+
:OPERATION_COUNT,
|
|
82
|
+
:UNIT_COUNT_FOR_CLIENTS,
|
|
83
|
+
:METHOD_COST]
|
|
84
|
+
|
|
85
|
+
g_accessor :usage_type, { :values_in => :UsageTypes }
|
|
86
|
+
g_accessor :min
|
|
87
|
+
g_accessor :max
|
|
88
|
+
|
|
89
|
+
def initialize(&block)
|
|
90
|
+
if block_given?
|
|
91
|
+
block.arity < 1 ? instance_eval(&block) : block.call(self)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def to_xml
|
|
96
|
+
<<-EOFS
|
|
97
|
+
<s:selector>
|
|
98
|
+
<s:dateRange>
|
|
99
|
+
<min>#{min}</min>
|
|
100
|
+
<max>#{max}</max>
|
|
101
|
+
</s:dateRange>
|
|
102
|
+
<s:apiUsageType>#{usage_type}</s:apiUsageType>
|
|
103
|
+
</s:selector>
|
|
104
|
+
EOFS
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end
|
|
@@ -21,35 +21,20 @@
|
|
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
# -------------------------------------------------------------------
|
|
23
23
|
|
|
24
|
-
# <env:Body>
|
|
25
|
-
# <n3:get xmlns:n3="https://adwords.google.com/api/adwords/info/v200909">
|
|
26
|
-
# <n3:selector>
|
|
27
|
-
# <n3:dateRange xmlns:n4="https://adwords.google.com/api/adwords/cm/v200909">
|
|
28
|
-
# <n4:min>20090101</n4:min>
|
|
29
|
-
# <n4:max>20091030</n4:max>
|
|
30
|
-
# </n3:dateRange>
|
|
31
|
-
# <n3:apiUsageType>UNIT_COUNT</n3:apiUsageType>
|
|
32
|
-
# </n3:selector>
|
|
33
|
-
# </n3:get>
|
|
34
|
-
# </env:Body>
|
|
35
|
-
#</env:Envelope>
|
|
36
|
-
|
|
37
|
-
|
|
38
24
|
module Sem4r
|
|
39
25
|
class InfoService
|
|
40
26
|
include SoapCall
|
|
41
27
|
|
|
42
28
|
def initialize(connector)
|
|
43
29
|
@connector = connector
|
|
44
|
-
@header_namespace = "https://adwords.google.com/api/adwords/cm/
|
|
45
|
-
@service_namespace = "https://adwords.google.com/api/adwords/info/
|
|
30
|
+
@header_namespace = "https://adwords.google.com/api/adwords/cm/v201008"
|
|
31
|
+
@service_namespace = "https://adwords.google.com/api/adwords/info/v201008"
|
|
46
32
|
|
|
47
|
-
@production_service_url = "https://adwords.google.com/api/adwords/info/
|
|
48
|
-
@sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/info/
|
|
33
|
+
@production_service_url = "https://adwords.google.com/api/adwords/info/v201008/InfoService"
|
|
34
|
+
@sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/info/v201008/InfoService"
|
|
49
35
|
end
|
|
50
36
|
|
|
51
|
-
|
|
52
|
-
soap_call_v2009 :unit_cost
|
|
37
|
+
soap_call_v2010 :get, :mutate => false
|
|
53
38
|
|
|
54
39
|
def _unit_cost( usage_type )
|
|
55
40
|
<<-EOFS
|
|
@@ -65,51 +50,11 @@ module Sem4r
|
|
|
65
50
|
EOFS
|
|
66
51
|
end
|
|
67
52
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
#
|
|
75
|
-
#
|
|
76
|
-
# soap_message.instance_eval do
|
|
77
|
-
# def build_soap_message
|
|
78
|
-
# str = <<-EOFS
|
|
79
|
-
#<?xml version="1.0" encoding="utf-8" ?>
|
|
80
|
-
# <env:Envelope
|
|
81
|
-
# xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
|
82
|
-
# xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
83
|
-
# xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
|
|
84
|
-
# xmlns="https://adwords.google.com/api/adwords/cm/v200909"
|
|
85
|
-
# xmlns:s="https://adwords.google.com/api/adwords/info/v200909">
|
|
86
|
-
# <env:Header>
|
|
87
|
-
# <s:RequestHeader env:mustUnderstand="0">
|
|
88
|
-
# <authToken>#{@credentials.authentication_token}</authToken>
|
|
89
|
-
# <userAgent>adwords4r: Sample User Agent</userAgent>
|
|
90
|
-
# <developerToken>#{@credentials.developer_token}</developerToken>
|
|
91
|
-
# </s:RequestHeader>
|
|
92
|
-
# </env:Header>
|
|
93
|
-
# <env:Body >
|
|
94
|
-
# <s:get>
|
|
95
|
-
# <s:selector>
|
|
96
|
-
# <s:dateRange>
|
|
97
|
-
# <min>20090101</min>
|
|
98
|
-
# <max>20091105</max>
|
|
99
|
-
# </s:dateRange>
|
|
100
|
-
# <s:apiUsageType>UNIT_COUNT</s:apiUsageType>
|
|
101
|
-
# </s:selector>
|
|
102
|
-
# </s:get>
|
|
103
|
-
# </env:Body>
|
|
104
|
-
# </env:Envelope>
|
|
105
|
-
#EOFS
|
|
106
|
-
# str
|
|
107
|
-
# end
|
|
108
|
-
# end
|
|
109
|
-
#
|
|
110
|
-
# result_xml = soap_message.send(@sandbox_service_url)
|
|
111
|
-
# result_xml
|
|
112
|
-
# end
|
|
113
|
-
|
|
53
|
+
def _get(xml)
|
|
54
|
+
<<-EOFS
|
|
55
|
+
<s:get>#{xml}</s:get>
|
|
56
|
+
EOFS
|
|
57
|
+
end
|
|
58
|
+
|
|
114
59
|
end
|
|
115
60
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
1
2
|
# -------------------------------------------------------------------------
|
|
2
3
|
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
|
3
4
|
#
|
|
@@ -60,7 +61,8 @@ module Sem4r
|
|
|
60
61
|
|
|
61
62
|
xml = ""
|
|
62
63
|
if tag
|
|
63
|
-
xml += "<#{tag} xsi:type='#{operation_type}'>"
|
|
64
|
+
xml += "<#{tag} xsi:type='#{operation_type}' #{if @namespace then @namespace else '' end}>"
|
|
65
|
+
# xsi:type="n1:ReportDefinitionOperation" xmlns:n1="https://adwords.google.com/api/adwords/cm/v201008"
|
|
64
66
|
end
|
|
65
67
|
xml +=<<-EOS
|
|
66
68
|
<operator>#{operator}</operator>
|