bing_ads_ruby_sdk 0.0.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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