bing_ads_ruby_sdk 0.0.0 → 1.0.0

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -1
  3. data/.rspec +3 -1
  4. data/Gemfile +0 -3
  5. data/LICENSE.txt +1 -1
  6. data/README.md +70 -9
  7. data/Rakefile +2 -0
  8. data/bin/setup +1 -3
  9. data/bing_ads_ruby_sdk.gemspec +17 -22
  10. data/changelog.md +19 -0
  11. data/lib/bing_ads_ruby_sdk.rb +32 -3
  12. data/lib/bing_ads_ruby_sdk/api.rb +81 -0
  13. data/lib/bing_ads_ruby_sdk/augmented_parser.rb +79 -0
  14. data/lib/bing_ads_ruby_sdk/configuration.rb +26 -0
  15. data/lib/bing_ads_ruby_sdk/errors/error_handler.rb +65 -0
  16. data/lib/bing_ads_ruby_sdk/errors/errors.rb +192 -0
  17. data/lib/bing_ads_ruby_sdk/header.rb +44 -0
  18. data/lib/bing_ads_ruby_sdk/http_client.rb +65 -0
  19. data/lib/bing_ads_ruby_sdk/log_message.rb +57 -0
  20. data/lib/bing_ads_ruby_sdk/oauth2/authorization_handler.rb +94 -0
  21. data/lib/bing_ads_ruby_sdk/oauth2/fs_store.rb +34 -0
  22. data/lib/bing_ads_ruby_sdk/postprocessors/cast_long_arrays.rb +35 -0
  23. data/lib/bing_ads_ruby_sdk/postprocessors/snakize.rb +35 -0
  24. data/lib/bing_ads_ruby_sdk/preprocessors/camelize.rb +45 -0
  25. data/lib/bing_ads_ruby_sdk/preprocessors/order.rb +58 -0
  26. data/lib/bing_ads_ruby_sdk/services/ad_insight.rb +10 -0
  27. data/lib/bing_ads_ruby_sdk/services/base.rb +83 -0
  28. data/lib/bing_ads_ruby_sdk/services/bulk.rb +26 -0
  29. data/lib/bing_ads_ruby_sdk/services/campaign_management.rb +116 -0
  30. data/lib/bing_ads_ruby_sdk/services/customer_billing.rb +10 -0
  31. data/lib/bing_ads_ruby_sdk/services/customer_management.rb +26 -0
  32. data/lib/bing_ads_ruby_sdk/services/reporting.rb +10 -0
  33. data/lib/bing_ads_ruby_sdk/soap_client.rb +143 -0
  34. data/lib/bing_ads_ruby_sdk/string_utils.rb +23 -0
  35. data/lib/bing_ads_ruby_sdk/version.rb +4 -1
  36. data/lib/bing_ads_ruby_sdk/wsdl/v12/production/ad_insight.xml +1 -0
  37. data/lib/bing_ads_ruby_sdk/wsdl/v12/production/bulk.xml +1 -0
  38. data/lib/bing_ads_ruby_sdk/wsdl/v12/production/campaign_management.xml +1 -0
  39. data/lib/bing_ads_ruby_sdk/wsdl/v12/production/customer_billing.xml +1 -0
  40. data/lib/bing_ads_ruby_sdk/wsdl/v12/production/customer_management.xml +1 -0
  41. data/lib/bing_ads_ruby_sdk/wsdl/v12/production/reporting.xml +1 -0
  42. data/lib/bing_ads_ruby_sdk/wsdl/v12/sandbox/ad_insight.xml +1 -0
  43. data/lib/bing_ads_ruby_sdk/wsdl/v12/sandbox/bulk.xml +1 -0
  44. data/lib/bing_ads_ruby_sdk/wsdl/v12/sandbox/campaign_management.xml +1 -0
  45. data/lib/bing_ads_ruby_sdk/wsdl/v12/sandbox/customer_billing.xml +1 -0
  46. data/lib/bing_ads_ruby_sdk/wsdl/v12/sandbox/customer_management.xml +1 -0
  47. data/lib/bing_ads_ruby_sdk/wsdl/v12/sandbox/reporting.xml +1 -0
  48. data/lib/bing_ads_ruby_sdk/wsdl/v12/test/ad_insight.xml +3065 -0
  49. data/lib/bing_ads_ruby_sdk/wsdl/v12/test/bulk.xml +1424 -0
  50. data/lib/bing_ads_ruby_sdk/wsdl/v12/test/campaign_management.xml +9949 -0
  51. data/lib/bing_ads_ruby_sdk/wsdl/v12/test/customer_billing.xml +899 -0
  52. data/lib/bing_ads_ruby_sdk/wsdl/v12/test/customer_management.xml +3966 -0
  53. data/lib/bing_ads_ruby_sdk/wsdl/v12/test/reporting.xml +3742 -0
  54. data/lib/bing_ads_ruby_sdk/wsdl/wsdl_source.txt +25 -0
  55. data/lib/bing_ads_ruby_sdk/wsdl_operation_wrapper.rb +39 -0
  56. data/tasks/bing_ads_ruby_sdk.rake +28 -0
  57. metadata +137 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 19d9468ca04839a78af34cbe1e45cbde578a7f3c
4
- data.tar.gz: 45a579ccf5d81cf82f9b8881f6cf1dd1bfeb4474
3
+ metadata.gz: 11c7e24cf05dfac01e506e24cb886fe6d7290ea3
4
+ data.tar.gz: 8877b5a30d082582c90777e8ced9d68d8ab2fcf9
5
5
  SHA512:
6
- metadata.gz: ed3e275860eb7c4f1f5057185be411c3c0db8a8ad14a951d435bb56dbf2301baabc7494a9753a49d97f3a8ed08d3a45a10aa9d6442dcb324c340f8f75e7fda66
7
- data.tar.gz: f0bec9ee6cf4c974a27f8c658ebf9ad2d90d3ac2c347097947c28652ebe2c91d6be2511cef68e8df8aea30b88826c3da95072c144820150a178b74a0de5635a1
6
+ metadata.gz: 3b974e4c75e62f5018b52e6b6158594c6186f5774d1b822934ed82cf94ab8cfd911c48abe8d1aa8cdfa2e987abc4b5f9842eba763036979124ea6546cd03c168
7
+ data.tar.gz: 0d5fd652d0107446ff4413ca14e4e5bcfc5872e06fee42d001b52deb79d0df474c702d479743e187fe3495458ef9b9e5ce035e0275b8aeadbcae432d9829e36f
data/.gitignore CHANGED
@@ -7,6 +7,11 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
-
10
+ /log/*
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
+ .token_*
14
+
15
+ .byebug_history
16
+ .env
17
+ custom_setup.rb
data/.rspec CHANGED
@@ -1,2 +1,4 @@
1
- --format documentation
1
+ --format progress
2
2
  --color
3
+ --exclude-pattern '**/examples/**/*_spec.rb'
4
+ --require spec_helper
data/Gemfile CHANGED
@@ -2,6 +2,3 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in bing_ads_ruby_sdk.gemspec
4
4
  gemspec
5
-
6
- # remove after/if merged
7
- gem 'lolsoap', git: 'https://github.com/effilab/lolsoap', branch: 'edge'
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017 sami
3
+ Copyright (c) 2017 Effilab
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,12 +1,8 @@
1
1
  # BingAdsRubySdk
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/bing_ads_ruby_sdk`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
6
-
7
3
  ## Installation
8
4
 
9
- Add this line to your application's Gemfile:
5
+ Add the following to your application's Gemfile:
10
6
 
11
7
  ```ruby
12
8
  gem 'bing_ads_ruby_sdk'
@@ -20,19 +16,84 @@ Or install it yourself as:
20
16
 
21
17
  $ gem install bing_ads_ruby_sdk
22
18
 
23
- ## Usage
19
+ ## Getting Started
20
+
21
+ In order to use Bing's api you need to get your api credentials from bing. From there gem handles the oauth token generation.
22
+
23
+ By default, there is only one store in the gem to store the oauth token. It's a file system based store. You can create one yourself to store credentials in a database or wherever you desire. The store class must implement `read` and `write(data)` instance methods.
24
+
25
+ To get your token, run:
26
+ ```ruby
27
+ rake bing_token:get[my_token.json,your_dev_token,your_bing_client_id]
28
+
29
+ ```
30
+
31
+
32
+ Then to use the api:
33
+ ```ruby
34
+ store = ::BingAdsRubySdk::OAuth2::FsStore.new('my_token.json')
35
+ api = BingAdsRubySdk::Api.new(
36
+ oauth_store: store,
37
+ developer_token: 'your_dev_token',
38
+ client_id: 'your_bing_client_id'
39
+ )
40
+ api.customer_management.signup_customer(params)
41
+ filter: 'name',
42
+ top_n: 1
43
+ )
44
+
45
+ # once you have your bing customer and account ids:
46
+ api.set_customer(customer_id: customer_id, account_id: account_id )
47
+
48
+ api.campaign_management.get_campaigns_by_account_id(account_id: account_id)
49
+ ```
50
+
51
+ You'll see services like `customer_management` implement some methods, but not all the ones available in the API.
52
+
53
+ The methods implemented contain additional code to ease data manipulation but any endpoint can be reached using `call` on a service.
54
+
55
+ ```ruby
56
+ @cm.call(:find_accounts_or_customers_info, filter: 'name', top_n: 1)
57
+ # => { account_info_with_customer_data: { account_info_with_customer_data: [{ customer_id: "250364751", :
58
+
59
+ # VS method dedicated to extract data
60
+
61
+ @cm.find_accounts_or_customers_info(filter: 'name', top_n: 1)
62
+ # => [{ customer_id: "250364731" ...
24
63
 
25
- TODO: Write usage instructions here
64
+ ```
65
+
66
+
67
+ ## Configure the gem
68
+ ```ruby
69
+ BingAdsRubySdk.configure do |conf|
70
+ conf.log = true
71
+ conf.logger.level = Logger::DEBUG
72
+ conf.pretty_print_xml = true
73
+ # to filter sensitive data before logging
74
+ conf.filters = ["AuthenticationToken", "DeveloperToken"]
75
+ end
76
+ ```
26
77
 
27
78
  ## Development
28
79
 
80
+ ### Updating to a new Bing API version
81
+ Bing regularly releases new versions of the API and removes support for old versions.
82
+ When you want to support a new version of the API, here are some of the things that
83
+ need to be changed:
84
+ * Go to https://docs.microsoft.com/en-us/bingads/guides/migration-guide to see what has changed
85
+ * Set the default SDK version in lib/bing_ads_ruby_sdk/version.rb
86
+
87
+ ### Specs
29
88
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
89
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
90
+ To release a new version, update the version number in `version.rb`, and then run
91
+ `bundle exec rake release`, which will create a git tag for the version, push git
92
+ commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
93
 
33
94
  ## Contributing
34
95
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/bing_ads_ruby_sdk.
96
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Effilab/bing_ads_ruby_sdk.
36
97
 
37
98
  ## License
38
99
 
data/Rakefile CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
+ require './lib/bing_ads_ruby_sdk'
4
+ import 'tasks/bing_ads_ruby_sdk.rake'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
data/bin/setup CHANGED
@@ -3,6 +3,4 @@ set -euo pipefail
3
3
  IFS=$'\n\t'
4
4
  set -vx
5
5
 
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
6
+ bundle install
@@ -5,37 +5,32 @@ require 'bing_ads_ruby_sdk/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'bing_ads_ruby_sdk'
8
+ spec.required_ruby_version = '>= 2.0'
9
+
8
10
  spec.version = BingAdsRubySdk::VERSION
9
- spec.authors = ["Effilab", "Sami Ben-yahia"]
10
- spec.email = %w[contact@effilab-local.com]
11
+ spec.authors = %w[Effilab developers]
12
+ spec.email = %w[developers@effilab-local.com]
11
13
 
12
14
  spec.summary = 'Bing Ads Ruby SDK'
13
- spec.description = 'The Bing Ads Ruby Software Development Kit (SDK) ' \
14
- 'enhances the experience of developing Bing Ads applications with the ' \
15
- 'Ruby programming language'
16
- spec.homepage = 'https://github.com/effilab/bing_ads_ruby_sdk'
15
+ spec.description = 'Bing Ads Api Wrapper'
16
+ spec.homepage = 'https://github.com/Effilab/bing_ads_ruby_sdk'
17
17
  spec.license = 'MIT'
18
18
 
19
- if spec.respond_to?(:metadata)
20
- spec.metadata['allowed_push_host'] = "https://rubygems.org"
21
- else
22
- raise 'RubyGems 2.0 or newer is required to protect against ' \
23
- 'public gem pushes.'
24
- end
25
-
26
19
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
20
  f.match(%r{^(test|spec|features)/})
28
21
  end
29
- spec.bindir = 'exe'
30
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
22
  spec.require_paths = %w[lib]
32
23
 
33
- spec.add_dependency 'signet', '~> 0.7'
34
- spec.add_dependency 'lolsoap', '~> 0.8'
24
+ spec.add_runtime_dependency 'signet', '~> 0.8.1'
25
+ spec.add_runtime_dependency 'excon', '>= 0.62.0'
26
+ spec.add_runtime_dependency 'lolsoap', '>=0.9.0'
35
27
 
36
- spec.add_development_dependency 'bundler', '~> 1.15'
37
- spec.add_development_dependency 'rake', '~> 12.0'
38
- spec.add_development_dependency 'yard', '~> 0.9'
39
- spec.add_development_dependency 'rspec', '~> 3.6'
40
- spec.add_development_dependency 'simplecov', '~> 0.14'
28
+ spec.add_development_dependency 'bundler'
29
+ spec.add_development_dependency 'dotenv'
30
+ spec.add_development_dependency 'rake'
31
+ spec.add_development_dependency 'yard'
32
+ spec.add_development_dependency 'rspec'
33
+ spec.add_development_dependency 'simplecov'
34
+ spec.add_development_dependency 'byebug'
35
+ spec.add_development_dependency 'awesome_print'
41
36
  end
data/changelog.md ADDED
@@ -0,0 +1,19 @@
1
+ ## V1.0.0 Release
2
+ The main reasons of the refactoring were to:
3
+
4
+ - add convenient methods returning structured data
5
+
6
+ - remove metaprogramming
7
+
8
+ - remove the dependency on an unmerged and unmaintained branch of the lolsoap gem
9
+
10
+
11
+ Alongside these key points, we now have:
12
+
13
+ - filtred logs
14
+
15
+ - split concerns
16
+
17
+ - strong specs suite
18
+
19
+ - a customizable configuration
@@ -1,5 +1,34 @@
1
- require "bing_ads_ruby_sdk/version"
1
+ # frozen_string_literal: true
2
+ require 'time'
3
+ require 'lolsoap'
4
+
5
+ require 'bing_ads_ruby_sdk/version'
6
+ require 'bing_ads_ruby_sdk/configuration'
7
+ require 'bing_ads_ruby_sdk/api'
8
+ require 'bing_ads_ruby_sdk/string_utils'
2
9
 
3
10
  module BingAdsRubySdk
4
- # Your code goes here...
5
- end
11
+ def self.config
12
+ @configuration ||= BingAdsRubySdk::Configuration.new
13
+ end
14
+
15
+ def self.configure
16
+ yield(config)
17
+ end
18
+
19
+ def self.log(level, *args, &block)
20
+ return unless config.log
21
+ config.logger.send(level, *args, &block)
22
+ end
23
+
24
+ def self.root_path
25
+ ROOT_PATH
26
+ end
27
+
28
+ def self.type_key
29
+ TYPE_KEY
30
+ end
31
+
32
+ TYPE_KEY = '@type'
33
+ ROOT_PATH = File.join(__dir__,'..')
34
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bing_ads_ruby_sdk/header"
4
+ require "bing_ads_ruby_sdk/soap_client"
5
+ require "bing_ads_ruby_sdk/services/base"
6
+ require "bing_ads_ruby_sdk/services/ad_insight"
7
+ require "bing_ads_ruby_sdk/services/bulk"
8
+ require "bing_ads_ruby_sdk/services/campaign_management"
9
+ require "bing_ads_ruby_sdk/services/customer_billing"
10
+ require "bing_ads_ruby_sdk/services/customer_management"
11
+ require "bing_ads_ruby_sdk/services/reporting"
12
+ require "bing_ads_ruby_sdk/oauth2/authorization_handler"
13
+ require "bing_ads_ruby_sdk/errors/errors"
14
+ require "bing_ads_ruby_sdk/errors/error_handler"
15
+
16
+ module BingAdsRubySdk
17
+ class Api
18
+ attr_reader :header
19
+
20
+ # @param version [Symbol] API version, used to choose WSDL configuration version
21
+ # @param environment [Symbol]
22
+ # @option environment [Symbol] :production Use the production WSDL configuration
23
+ # @option environment [Symbol] :sandbox Use the sandbox WSDL configuration
24
+ # @param developer_token
25
+ # @param client_id
26
+ def initialize(version: DEFAULT_SDK_VERSION,
27
+ environment: :production,
28
+ developer_token:,
29
+ client_id:,
30
+ oauth_store:)
31
+ @version = version
32
+ @environment = environment
33
+ @header = Header.new(
34
+ developer_token: developer_token,
35
+ client_id: client_id,
36
+ store: oauth_store
37
+ )
38
+ end
39
+
40
+ def ad_insight
41
+ build_service(BingAdsRubySdk::Services::AdInsight)
42
+ end
43
+
44
+ def bulk
45
+ build_service(BingAdsRubySdk::Services::Bulk)
46
+ end
47
+
48
+ def campaign_management
49
+ build_service(BingAdsRubySdk::Services::CampaignManagement)
50
+ end
51
+
52
+ def customer_billing
53
+ build_service(BingAdsRubySdk::Services::CustomerBilling)
54
+ end
55
+
56
+ def customer_management
57
+ build_service(BingAdsRubySdk::Services::CustomerManagement)
58
+ end
59
+
60
+ def reporting
61
+ build_service(BingAdsRubySdk::Services::Reporting)
62
+ end
63
+
64
+ def set_customer(account_id:, customer_id:)
65
+ header.set_customer(account_id: account_id, customer_id: customer_id)
66
+ end
67
+
68
+ private
69
+
70
+ def build_service(klass)
71
+ klass.new(
72
+ BingAdsRubySdk::SoapClient.new(
73
+ version: @version,
74
+ environment: @environment,
75
+ header: header,
76
+ service_name: klass.service
77
+ )
78
+ )
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BingAdsRubySdk
4
+ class AugmentedParser
5
+
6
+ def initialize(wsdl_file_path)
7
+ @lolsoap_parser = LolSoap::WSDLParser.parse(File.read(wsdl_file_path))
8
+ @concrete_abstract_mapping = {}
9
+ end
10
+
11
+ def call
12
+ add_subtypes_to_definitions
13
+
14
+ [lolsoap_parser, concrete_abstract_mapping]
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :lolsoap_parser, :concrete_abstract_mapping
20
+
21
+ # adds subtypes to existing definitions.
22
+ # for instance, the wsdl specifies AdExtensionAssociation are accepted for AddAdExtension
23
+ # but there is no way to specify the type we want
24
+ # the goal is to:
25
+ # - validate properly the attributes
26
+ # - ensure the attributes are properly formatted when xml is created
27
+ # - ensure we inject proper type to the xml
28
+ def add_subtypes_to_definitions
29
+ # to augment all types definitions
30
+ lolsoap_parser.types.each_value do |content|
31
+ add_subtypes(content[:elements])
32
+ end
33
+ # we have to augment operations because some Requests are abstract, for instance:
34
+ # ReportRequest which can be AccountPerformanceReportRequest etc...
35
+ lolsoap_parser.operations.each_value do |content|
36
+ content[:input][:body].each do |full_name|
37
+ add_subtypes(lolsoap_parser.elements[full_name][:type][:elements])
38
+ end
39
+ end
40
+ @grouped_subtypes = nil # we can reset this as its not needed anymore
41
+ end
42
+
43
+ def add_subtypes(content)
44
+ content.keys.each do |base|
45
+ grouped_subtypes.fetch(base, []).each do |sub_type|
46
+ elem = lolsoap_parser.elements[sub_type.id]
47
+ elem[:base_type_name] = base
48
+ content[sub_type.name] = elem
49
+ end
50
+ end
51
+ end
52
+
53
+ def grouped_subtypes
54
+ @grouped_subtypes ||= begin
55
+ grouped_types = {}
56
+ # types are defined there: https://github.com/loco2/lolsoap/blob/master/lib/lolsoap/wsdl_parser.rb#L305
57
+ lolsoap_parser.each_node('xs:complexType[not(@abstract="true")]') do |node, schema|
58
+ type = ::LolSoap::WSDLParser::Type.new(lolsoap_parser, schema, node)
59
+ if type.base_type # it has a base_type, its a subtype
60
+ base_type = extract_base_type(type.base_type)
61
+ concrete_abstract_mapping[type.name] = base_type.name
62
+ grouped_types[base_type.name] ||= []
63
+ grouped_types[base_type.name].push(type)
64
+ end
65
+ end
66
+ grouped_types
67
+ end
68
+ end
69
+
70
+ # we want the real base: sometimes there are many layers of inheritance
71
+ def extract_base_type(type)
72
+ if type.base_type
73
+ extract_base_type(type.base_type)
74
+ else
75
+ type
76
+ end
77
+ end
78
+ end
79
+ end