gnib-ads-api 0.3

Sign up to get free protection for your applications and to get access to all the features.
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,186 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module GnibAdsApi
4
+
5
+ ##
6
+ # Public : Defines the base object for all report requests.
7
+ # Do not instantiate this object. Instead, you may instantiate one
8
+ # of the following report request objects which derives from this object to request a report.
9
+ #
10
+ # Reference: http://msdn.microsoft.com/en-us/library/bing-ads-reporting-bing-ads-reportrequest.aspx
11
+ #
12
+ # Author:: jlopezn@neonline.cl
13
+ #
14
+ # === Usage
15
+ #
16
+ # request = GnibAdsApi::CampaignPerformanceReportRequest.new(
17
+ # :format => :xml,
18
+ # :language => :english,
19
+ # :report_name => "Me report",
20
+ # :aggregation => :hourly,
21
+ # :columns => [:account_name, :account_number, :time_period],
22
+ # # The filter is specified as a hash
23
+ # :filter => {
24
+ # # specifies the Bing expected String value
25
+ # :ad_distribution => "Search",
26
+ # # specifies criteria as a snake case symbol
27
+ # :device_os => :android,
28
+ # :device_type => :tablet,
29
+ # # criteria nil is similar to not specify it at all
30
+ # :status => nil },
31
+ # :scope => {
32
+ # :account_ids => [123456, 234567],
33
+ # :campaigns => [<GnibAdsApi::CampaignReportScope>] },
34
+ # # predefined date
35
+ # :time => :this_week)
36
+ #
37
+ # request2 = GnibAdsApi::CampaignPerformanceReportRequest.new(
38
+ # :format => :csv,
39
+ # :language => :french,
40
+ # :report_name => "Me report",
41
+ # :aggregation => :daily,
42
+ # :columns => [:account_name, :account_number, :time_period],
43
+ # # no filter is specified
44
+ # :scope => {
45
+ # :account_ids => [123456, 234567],
46
+ # :campaigns => [<GnibAdsApi::CampaignReportScope>] },
47
+ # # Custom date range
48
+ # :time => {
49
+ # :custom_date_range_start => {:day => 1, :month => 12, :year => 2013},
50
+ # :custom_date_range_end => {:day => 12, :month => 12, :year => 2013} }
51
+ # )
52
+ class CampaignPerformanceReportRequest < GnibAdsApi::PerformanceReportRequest
53
+
54
+ # Valid Columns for this report request
55
+ COLUMNS = GnibAdsApi::Config.instance.
56
+ reporting_constants['campaign_performance_report']['columns']
57
+
58
+ # Valid Filters for this report request
59
+ FILTERS = GnibAdsApi::Config.instance.
60
+ reporting_constants['campaign_performance_report']['filter']
61
+
62
+
63
+ # Public : Constructor. Adds a validations for the columns, filter
64
+ # and scope attributes
65
+ #
66
+ # Author:: jlopezn@neonline.cl
67
+ #
68
+ # === Parameters
69
+ # * +attributes+ - Hash with the report request attributes
70
+ #
71
+ # === Example
72
+ #
73
+ # request = GnibAdsApi::CampaignPerformanceReportRequest.new(
74
+ # :format => :xml,
75
+ # :language => :english,
76
+ # :report_name => "Me report",
77
+ # :aggregation => :hourly,
78
+ # :columns => [:account_name, :account_number, :time_period],
79
+ # # The filter is specified as a hash
80
+ # :filter => {
81
+ # # specifies the Bing expected String value
82
+ # :ad_distribution => "Search",
83
+ # # specifies criteria as a snake case symbol
84
+ # :device_os => :android,
85
+ # :device_type => :tablet,
86
+ # # criteria nil is similar to not specify it at all
87
+ # :status => nil },
88
+ # :scope => {
89
+ # :account_ids => [123456, 234567],
90
+ # :campaigns => [<GnibAdsApi::CampaignReportScope>] },
91
+ # # predefined date
92
+ # :time => :this_week)
93
+ #
94
+ # request2 = GnibAdsApi::CampaignPerformanceReportRequest.new(
95
+ # :format => :csv,
96
+ # :language => :french,
97
+ # :report_name => "Me report",
98
+ # :aggregation => :daily,
99
+ # :columns => [:account_name, :account_number, :time_period],
100
+ # # no filter is specified
101
+ # :scope => {
102
+ # :account_ids => [123456, 234567],
103
+ # :campaigns => [<GnibAdsApi::CampaignReportScope>] },
104
+ # # Custom date range
105
+ # :time => {
106
+ # :custom_date_range_start => {:day => 1, :month => 12, :year => 2013},
107
+ # :custom_date_range_end => {:day => 12, :month => 12, :year => 2013} }
108
+ # )
109
+ def initialize(attributes={})
110
+ raise Exception.new("Invalid columns") if !valid_columns(COLUMNS, attributes[:columns])
111
+ raise Exception.new("Invalid filters") if !valid_filter(FILTERS, attributes[:filter])
112
+ raise Exception.new("Invalid scope") if !valid_scope(attributes[:scope])
113
+ super(attributes)
114
+ end
115
+
116
+
117
+ # Public:: Returns the object as a Hash valid for SOAP requests
118
+ #
119
+ # Author:: jlopezn@neonline.cl
120
+ #
121
+ # === Parameters
122
+ # * +keys_case+ - case for the hashes keys: underscore or camelcase
123
+ #
124
+ # Returns:: Hash
125
+ def to_hash(keys = :underscore)
126
+ hash = super(keys)
127
+ hash[get_attribute_key('columns', keys)] =
128
+ columns_to_hash(COLUMNS, columns, keys)
129
+ hash[get_attribute_key('filter', keys)] =
130
+ filter_to_hash(FILTERS, keys)
131
+ hash[get_attribute_key('scope', keys)] = scope_to_hash(keys)
132
+ hash["@xsi:type"] = type_attribute_for_soap
133
+ return hash
134
+ end
135
+
136
+
137
+ private
138
+
139
+ # Internal:: Validates the scope attribute given in the constructor
140
+ #
141
+ # Author:: jlopezn@neonline.cl
142
+ #
143
+ # === Parameters
144
+ # * +scope+ - value for the 'scope' key in the has initializer
145
+ #
146
+ # Returns:: true if the scope specification is valid. Raises Exception otherwise
147
+ #
148
+ # Raises:: Exception if the scope is not valid
149
+ def valid_scope(scope)
150
+ raise Exception.new("Invalid scope: no account_ids key") if !scope.key?(:account_ids)
151
+ raise Exception.new("Invalid scope: no campaigns key") if !scope.key?(:campaigns)
152
+ return true
153
+ end
154
+
155
+
156
+ # Internal:: Returns the scope attribute as a hash for the SOAP request
157
+ #
158
+ # Author:: jlopezn@neonline.cl
159
+ #
160
+ # === Parameters
161
+ # * +keys_case+ - case for the hash: underscore or camelcase
162
+ #
163
+ # Returns:: Hash
164
+ def scope_to_hash(keys_case=:underscore)
165
+ return {
166
+ get_attribute_key('account_ids', keys_case) => {"ins0:long" => object_to_hash(scope[:account_ids], keys_case)},
167
+ get_attribute_key('campaigns', keys_case) =>
168
+ { "CampaignReportScope" => object_to_hash(scope[:campaigns], keys_case) }
169
+ }
170
+ end
171
+
172
+
173
+ # Internal:: Returns a string with type attribute for the ReportRequest SOAP tag
174
+ #
175
+ # Author:: jlopezn@neonline.cl
176
+ #
177
+ # Returns:: "v9:CampaignPerformanceReportRequest"
178
+ def type_attribute_for_soap
179
+ return GnibAdsApi::ClientProxy::NAMESPACE.to_s + ":" +
180
+ GnibAdsApi::Config.instance.
181
+ reporting_constants['campaign_performance_report']['type']
182
+ end
183
+
184
+ end
185
+
186
+ end
@@ -0,0 +1,65 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module GnibAdsApi::Helpers
4
+
5
+ ##
6
+ # Public : Utility module
7
+ #
8
+ # Author:: jlopezn@neonline.cl
9
+ #
10
+ module ColumnHelper
11
+
12
+ # Internal : Validates the specified columns at the ReporRequest initialization
13
+ # At the first invalid column detected this method raises Exception.
14
+ # If all column values are ok, this method returns true
15
+ # Valid columns are validated against COLUMNS constant
16
+ #
17
+ # Author:: jlopezn@neonline.cl
18
+ #
19
+ # valid_columns - Hash with the valid names and values for columns
20
+ # columns - Hash with the columns specified in the initialization
21
+ #
22
+ # Returns:: true if all columns are ok
23
+ # Raises:: Exception at the first invalid column detected
24
+ def valid_columns(valid_columns, columns)
25
+ columns.each do |col|
26
+
27
+ if col.is_a?(String)
28
+ if !valid_columns.value?(col)
29
+ raise Exception.new("Invalid column value '#{col}'")
30
+ end
31
+ elsif col.is_a?(Symbol)
32
+ if !valid_columns.key?(col.to_s)
33
+ raise Exception.new("Invalid column name '#{col}'")
34
+ end
35
+ end
36
+ end
37
+ return true
38
+ end
39
+
40
+
41
+ # Public : Return the columns attribute of the ReportRequest as a valid Hash for SOAP requests
42
+ #
43
+ # Author:: jlopezn@neonline.cl
44
+ #
45
+ # keys_case - specifies the keys_case for the hash: :underscore or :camelcase
46
+ #
47
+ # Returns:: Hash
48
+ def columns_to_hash(valid_columns, columns, keys_case=:underscore)
49
+ raise Exception.new("Invalid time value: nil") if columns.nil?
50
+
51
+ key = self.class.to_s.demodulize.gsub(/ReportRequest/, 'ReportColumn')
52
+ return { key =>
53
+ columns.map do |col|
54
+ if col.is_a?(String)
55
+ col
56
+ elsif col.is_a?(Symbol)
57
+ valid_columns[col.to_s]
58
+ end
59
+ end
60
+ }
61
+ end
62
+
63
+
64
+ end
65
+ end
@@ -0,0 +1,124 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module GnibAdsApi::Helpers
4
+
5
+ ##
6
+ # Public : Utility module for filter attribute in +ReportRequest+ derived classes
7
+ #
8
+ # Author:: jlopezn@neonline.cl
9
+ #
10
+ module FilterHelper
11
+
12
+ include GnibAdsApi::SOAPHasheable
13
+
14
+
15
+ # Valid filters values for each known criteria
16
+ FILTERS_CRITERIA = GnibAdsApi::Config.instance.
17
+ reporting_constants['filters']
18
+
19
+
20
+ # Internal : Validates the filter attribute at the ReporRequest initialization
21
+ # At the first invalid filter criteria or value detected this method raises Exception.
22
+ # If all filter criteria and values are ok, this method returns true
23
+ # Valid filter criteria are validated against FILTERS_CRITERIA constant
24
+ # Valid filter values are validated against FILTERS constant
25
+ #
26
+ # Author:: jlopezn@neonline.cl
27
+ #
28
+ # === Parameters
29
+ # valid_filters - Hash with the set of valid filter values
30
+ # filter - Hash with the filter criteria and values
31
+ #
32
+ # Returns:: true if filter is valid
33
+ #
34
+ # Raises:: Exception at the first invalid filter criteria o value
35
+ def valid_filter(valid_filters, filter)
36
+ if filter && filter.is_a?(Hash)
37
+ filter.keys.each do |filter_key|
38
+ # validates if filter criteria is recognized
39
+ raise Exception.new("Invalid filter criteria '#{filter_key.to_s}'") if !valid_filters.key?(filter_key.to_s)
40
+ # validates the filter criteria value
41
+ valid_filter_value(filter_key, filter[filter_key])
42
+ end
43
+ end
44
+ return true
45
+ end
46
+
47
+
48
+ # Internal : Validates a specific filter criteria and his value
49
+ #
50
+ # Author:: jlopezn@neonline.cl
51
+ #
52
+ # key - filter criteria to evaluate
53
+ # value - filter criteria to be evaluate
54
+ #
55
+ # Returns:: true if validation runs ok. Raise exception otherwise
56
+ #
57
+ # Raises:: Exception if filter value provided is not valid
58
+ def valid_filter_value(key, value)
59
+ return true if value.nil?
60
+ return true if solve_filter_value(key, value)
61
+ end
62
+
63
+
64
+ # Public : Returns the filter attribute as a Hash to SOAP requests
65
+ #
66
+ # Author:: jlopezn@neonline.cl
67
+ #
68
+ # filter - Hash with the filter values
69
+ #
70
+ # Returns:: Hash
71
+ def filter_to_hash(valid_filters, keys_case=:undescore)
72
+ hashed_filter = {}
73
+ filter.each do |key, value|
74
+ hashed_filter[get_attribute_key(key, keys_case)] = solve_filter_value(key, value)
75
+ end
76
+ return hashed_filter
77
+ end
78
+
79
+
80
+ # Internal:: Solves the Bing value for the given filter attribute
81
+ #
82
+ # Author:: jlopezn@neonline.cl
83
+ #
84
+ # === Parameters
85
+ # * +filter_criteria+ - String or symbol with the filter attribute to be solved
86
+ #
87
+ # === Examples
88
+ # solve_filter_value(:ad_distribution, :search)
89
+ # # => "Search"
90
+ #
91
+ # solve_filter_value(:ad_distribution, :other)
92
+ # # => Exception "Invalid filter name 'other' for 'ad_distribution' criteria"
93
+ #
94
+ # solve_filter_value(:ad_distribution, "Search")
95
+ # # => "Search"
96
+ #
97
+ # solve_filter_value(:ad_distribution, "Other")
98
+ # # => Exception "Invalid filter value 'Other' for 'ad_distribution' criteria"
99
+ #
100
+ # Returns:: String with the Bing value for the filter criteria.
101
+ #
102
+ # Raises:: Exception if the filter's criteria or value are unknown
103
+ def solve_filter_value(filter_criteria, filter_value)
104
+
105
+ filter_criteria_values = FILTERS_CRITERIA[filter_criteria.to_s]
106
+ if filter_value.is_a?(String)
107
+ if filter_criteria_values.value?(filter_value)
108
+ return filter_value
109
+ else
110
+ raise Exception.new("Invalid filter value '#{filter_value}' for '#{filter_criteria}' criteria")
111
+ end
112
+ elsif filter_value.is_a?(Symbol)
113
+ if filter_criteria_values.key?(filter_value.to_s)
114
+ return filter_criteria_values[filter_value.to_s]
115
+ else
116
+ raise Exception.new("Invalid filter name '#{filter_value}' for '#{filter_criteria}' criteria")
117
+ end
118
+ end
119
+ return nil
120
+ end
121
+
122
+
123
+ end
124
+ end
@@ -0,0 +1,51 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module GnibAdsApi::Helpers
4
+
5
+ ##
6
+ # Public : Utility module for scope attribute in +ReportRequest+ derived classes
7
+ #
8
+ # Author:: jlopezn@neonline.cl
9
+ #
10
+ module ScopeHelper
11
+
12
+ include GnibAdsApi::SOAPHasheable
13
+
14
+
15
+ # Valid filters values for each known criteria
16
+ FILTERS_CRITERIA = GnibAdsApi::Config.instance.
17
+ reporting_constants['filters']
18
+
19
+
20
+ # Internal : Validates the filter attribute at the ReporRequest initialization
21
+ # At the first invalid filter criteria or value detected this method raises Exception.
22
+ # If all filter criteria and values are ok, this method returns true
23
+ # Valid filter criteria are validated against FILTERS_CRITERIA constant
24
+ # Valid filter values are validated against FILTERS constant
25
+ #
26
+ # Author:: jlopezn@neonline.cl
27
+ #
28
+ # === Parameters
29
+ # valid_filters - Hash with the set of valid filter values
30
+ # filter - Hash with the filter criteria and values
31
+ #
32
+ # Returns:: true if filter is valid
33
+ #
34
+ # Raises:: Exception at the first invalid filter criteria o value
35
+ def valid_scope(valid_scopes, scope)
36
+ end
37
+
38
+
39
+ # Public : Returns the filter attribute as a Hash to SOAP requests
40
+ #
41
+ # Author:: jlopezn@neonline.cl
42
+ #
43
+ # filter - Hash with the filter values
44
+ #
45
+ # Returns:: Hash
46
+ def scope_to_hash(keys_case=:undescore)
47
+ end
48
+
49
+
50
+ end
51
+ end
@@ -0,0 +1,69 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module GnibAdsApi::Helpers
4
+
5
+ ##
6
+ # Public : Utility module
7
+ #
8
+ # Author:: jlopezn@neonline.cl
9
+ #
10
+ module TimeHelper
11
+
12
+ # Valid languages for reports
13
+ TIME_PERIODS = GnibAdsApi::Config.instance.
14
+ reporting_constants['time_periods']
15
+
16
+ # Public : Validates the time attribute present in some report request
17
+ #
18
+ # Author:: jlopezn@neonline.cl
19
+ #
20
+ # time - Hash with the time attribute for the report request
21
+ #
22
+ # Returns:: true if validation is ok, raises Exception otherwise
23
+ # Raises:: Exception if custom date range is bad informed, or if time periods specified is unknown
24
+ def valid_time(time)
25
+ # Custom date range
26
+ if time.is_a?(Hash)
27
+ raise Exception.new("Invalid time: missing :custom_date_range_start key") if !time.key?(:custom_date_range_start)
28
+ raise Exception.new("Invalid time: missing :custom_date_range_end key") if !time.key?(:custom_date_range_end)
29
+ # Time periods
30
+ else
31
+ return TIME_PERIODS.key?(time.to_s)
32
+ end
33
+ return true
34
+ end
35
+
36
+
37
+ # Public : Return the time attribute of the ReportRequest as a valid Hash for SOAP requests
38
+ #
39
+ # Author:: jlopezn@neonline.cl
40
+ #
41
+ # keys_case - specifies the keys_case for the hash: :underscore or :camelcase
42
+ #
43
+ # Returns:: Hash
44
+ def time_to_hash(keys_case)
45
+ raise Exception.new("Invalid time value: nil") if self.time.nil?
46
+
47
+ # Custom date range
48
+ if time.is_a?(Hash)
49
+ return {
50
+ get_attribute_key("custom_date_range_end", keys_case) => {
51
+ get_attribute_key("day", keys_case) => self.time[:custom_date_range_end][:day],
52
+ get_attribute_key("month", keys_case) => self.time[:custom_date_range_end][:month],
53
+ get_attribute_key("year", keys_case) => self.time[:custom_date_range_end][:year],
54
+
55
+ },
56
+ get_attribute_key("custom_date_range_start", keys_case) => {
57
+ get_attribute_key("day", keys_case) => self.time[:custom_date_range_start][:day],
58
+ get_attribute_key("month", keys_case) => self.time[:custom_date_range_start][:month],
59
+ get_attribute_key("year", keys_case) => self.time[:custom_date_range_start][:year],
60
+ }
61
+ }
62
+ # Time periods
63
+ else
64
+ return TIME_PERIODS[time.to_s]
65
+ end
66
+ end
67
+
68
+ end
69
+ end