adparlor-facebook 0.5.9

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 (136) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.gitlab-ci.yml +5 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +28 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +4 -0
  8. data/Gemfile +4 -0
  9. data/Gemfile.lock +136 -0
  10. data/Guardfile +13 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +164 -0
  13. data/Rakefile +3 -0
  14. data/adparlor-facebook.gemspec +38 -0
  15. data/bin/console +18 -0
  16. data/bin/gitlab_runner_specs.sh +22 -0
  17. data/bin/setup +7 -0
  18. data/lib/adparlor/facebook/api.rb +106 -0
  19. data/lib/adparlor/facebook/config.rb +24 -0
  20. data/lib/adparlor/facebook/error.rb +13 -0
  21. data/lib/adparlor/facebook/graph_api/activity.rb +11 -0
  22. data/lib/adparlor/facebook/graph_api/ad.rb +43 -0
  23. data/lib/adparlor/facebook/graph_api/ad_account.rb +168 -0
  24. data/lib/adparlor/facebook/graph_api/ad_creative.rb +22 -0
  25. data/lib/adparlor/facebook/graph_api/ad_image.rb +87 -0
  26. data/lib/adparlor/facebook/graph_api/ad_label.rb +12 -0
  27. data/lib/adparlor/facebook/graph_api/ad_preview.rb +15 -0
  28. data/lib/adparlor/facebook/graph_api/ad_set.rb +39 -0
  29. data/lib/adparlor/facebook/graph_api/ad_targeting_search.rb +64 -0
  30. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_education_major.rb +11 -0
  31. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_education_school.rb +11 -0
  32. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocation.rb +19 -0
  33. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocation_meta.rb +16 -0
  34. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocations/ad_city.rb +13 -0
  35. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocations/ad_country.rb +13 -0
  36. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocations/ad_geo_market.rb +13 -0
  37. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocations/ad_region.rb +13 -0
  38. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocations/ad_zip_code.rb +13 -0
  39. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_interest.rb +11 -0
  40. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_interest_suggestion.rb +12 -0
  41. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_interest_validation.rb +18 -0
  42. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_locale.rb +11 -0
  43. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_radius_suggestion.rb +11 -0
  44. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_targeting_category.rb +18 -0
  45. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_work_employer.rb +11 -0
  46. data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_work_position.rb +11 -0
  47. data/lib/adparlor/facebook/graph_api/ad_video.rb +124 -0
  48. data/lib/adparlor/facebook/graph_api/ads_pixel.rb +22 -0
  49. data/lib/adparlor/facebook/graph_api/ads_pixel_stat.rb +25 -0
  50. data/lib/adparlor/facebook/graph_api/advertisable_application.rb +11 -0
  51. data/lib/adparlor/facebook/graph_api/app_event_type.rb +11 -0
  52. data/lib/adparlor/facebook/graph_api/application.rb +15 -0
  53. data/lib/adparlor/facebook/graph_api/batch_object.rb +147 -0
  54. data/lib/adparlor/facebook/graph_api/broad_targeting_category.rb +11 -0
  55. data/lib/adparlor/facebook/graph_api/business.rb +18 -0
  56. data/lib/adparlor/facebook/graph_api/campaign.rb +43 -0
  57. data/lib/adparlor/facebook/graph_api/collection_proxy.rb +36 -0
  58. data/lib/adparlor/facebook/graph_api/connection_object.rb +11 -0
  59. data/lib/adparlor/facebook/graph_api/custom_audience.rb +31 -0
  60. data/lib/adparlor/facebook/graph_api/custom_audience_tos.rb +11 -0
  61. data/lib/adparlor/facebook/graph_api/custom_audience_user.rb +85 -0
  62. data/lib/adparlor/facebook/graph_api/custom_conversion.rb +22 -0
  63. data/lib/adparlor/facebook/graph_api/delivery_estimate.rb +11 -0
  64. data/lib/adparlor/facebook/graph_api/fields/activity.rb +12 -0
  65. data/lib/adparlor/facebook/graph_api/fields/ad.rb +60 -0
  66. data/lib/adparlor/facebook/graph_api/fields/ad_account.rb +21 -0
  67. data/lib/adparlor/facebook/graph_api/fields/ad_creative.rb +23 -0
  68. data/lib/adparlor/facebook/graph_api/fields/ad_image.rb +14 -0
  69. data/lib/adparlor/facebook/graph_api/fields/ad_label.rb +11 -0
  70. data/lib/adparlor/facebook/graph_api/fields/ad_preview.rb +11 -0
  71. data/lib/adparlor/facebook/graph_api/fields/ad_set.rb +100 -0
  72. data/lib/adparlor/facebook/graph_api/fields/ad_video.rb +22 -0
  73. data/lib/adparlor/facebook/graph_api/fields/ads_pixel.rb +12 -0
  74. data/lib/adparlor/facebook/graph_api/fields/ads_pixel_stat.rb +11 -0
  75. data/lib/adparlor/facebook/graph_api/fields/advertisable_application.rb +17 -0
  76. data/lib/adparlor/facebook/graph_api/fields/app_event_type.rb +11 -0
  77. data/lib/adparlor/facebook/graph_api/fields/application.rb +31 -0
  78. data/lib/adparlor/facebook/graph_api/fields/broad_targeting_category.rb +12 -0
  79. data/lib/adparlor/facebook/graph_api/fields/business.rb +11 -0
  80. data/lib/adparlor/facebook/graph_api/fields/campaign.rb +17 -0
  81. data/lib/adparlor/facebook/graph_api/fields/connection_object.rb +16 -0
  82. data/lib/adparlor/facebook/graph_api/fields/custom_audience.rb +22 -0
  83. data/lib/adparlor/facebook/graph_api/fields/custom_audience_tos.rb +11 -0
  84. data/lib/adparlor/facebook/graph_api/fields/custom_audience_user.rb +14 -0
  85. data/lib/adparlor/facebook/graph_api/fields/custom_conversion.rb +14 -0
  86. data/lib/adparlor/facebook/graph_api/fields/delivery_estimate.rb +11 -0
  87. data/lib/adparlor/facebook/graph_api/fields/field_decorator.rb +51 -0
  88. data/lib/adparlor/facebook/graph_api/fields/insight.rb +16 -0
  89. data/lib/adparlor/facebook/graph_api/fields/instagram_account.rb +11 -0
  90. data/lib/adparlor/facebook/graph_api/fields/leadgen_form.rb +23 -0
  91. data/lib/adparlor/facebook/graph_api/fields/page.rb +121 -0
  92. data/lib/adparlor/facebook/graph_api/fields/page_and_place.rb +11 -0
  93. data/lib/adparlor/facebook/graph_api/fields/partner_category.rb +12 -0
  94. data/lib/adparlor/facebook/graph_api/fields/picture.rb +17 -0
  95. data/lib/adparlor/facebook/graph_api/fields/post.rb +17 -0
  96. data/lib/adparlor/facebook/graph_api/fields/product_audience.rb +12 -0
  97. data/lib/adparlor/facebook/graph_api/fields/product_catalog.rb +11 -0
  98. data/lib/adparlor/facebook/graph_api/fields/product_feed.rb +12 -0
  99. data/lib/adparlor/facebook/graph_api/fields/product_group.rb +11 -0
  100. data/lib/adparlor/facebook/graph_api/fields/product_item.rb +18 -0
  101. data/lib/adparlor/facebook/graph_api/fields/product_set.rb +13 -0
  102. data/lib/adparlor/facebook/graph_api/fields/reach_estimate.rb +11 -0
  103. data/lib/adparlor/facebook/graph_api/fields/reach_frequency_prediction.rb +24 -0
  104. data/lib/adparlor/facebook/graph_api/fields/targeting_sentence_line.rb +11 -0
  105. data/lib/adparlor/facebook/graph_api/fields/targeting_suggestion.rb +11 -0
  106. data/lib/adparlor/facebook/graph_api/fields/targeting_validation.rb +11 -0
  107. data/lib/adparlor/facebook/graph_api/fields/user_lead_gen_info.rb +18 -0
  108. data/lib/adparlor/facebook/graph_api/fields/video_thumbnail.rb +11 -0
  109. data/lib/adparlor/facebook/graph_api/graph_object.rb +140 -0
  110. data/lib/adparlor/facebook/graph_api/insight.rb +18 -0
  111. data/lib/adparlor/facebook/graph_api/instagram_account.rb +12 -0
  112. data/lib/adparlor/facebook/graph_api/leadgen_form.rb +10 -0
  113. data/lib/adparlor/facebook/graph_api/page.rb +27 -0
  114. data/lib/adparlor/facebook/graph_api/page_and_place.rb +11 -0
  115. data/lib/adparlor/facebook/graph_api/partner_category.rb +11 -0
  116. data/lib/adparlor/facebook/graph_api/picture.rb +15 -0
  117. data/lib/adparlor/facebook/graph_api/post.rb +17 -0
  118. data/lib/adparlor/facebook/graph_api/product_audience.rb +17 -0
  119. data/lib/adparlor/facebook/graph_api/product_catalog.rb +27 -0
  120. data/lib/adparlor/facebook/graph_api/product_feed.rb +11 -0
  121. data/lib/adparlor/facebook/graph_api/product_group.rb +11 -0
  122. data/lib/adparlor/facebook/graph_api/product_item.rb +11 -0
  123. data/lib/adparlor/facebook/graph_api/product_set.rb +26 -0
  124. data/lib/adparlor/facebook/graph_api/reach_estimate.rb +17 -0
  125. data/lib/adparlor/facebook/graph_api/reach_frequency_prediction.rb +18 -0
  126. data/lib/adparlor/facebook/graph_api/targeting_sentence_line.rb +11 -0
  127. data/lib/adparlor/facebook/graph_api/targeting_suggestion.rb +16 -0
  128. data/lib/adparlor/facebook/graph_api/targeting_validation.rb +16 -0
  129. data/lib/adparlor/facebook/graph_api/traits/methods.rb +64 -0
  130. data/lib/adparlor/facebook/graph_api/user_lead_gen_info.rb +11 -0
  131. data/lib/adparlor/facebook/graph_api/video_thumbnail.rb +11 -0
  132. data/lib/adparlor/facebook/graph_api.rb +9 -0
  133. data/lib/adparlor/facebook/version.rb +5 -0
  134. data/lib/adparlor/facebook.rb +9 -0
  135. data/solano.yml +15 -0
  136. metadata +391 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 25c8f2e2b346a62b86c650d8b2fdc1b692339416
4
+ data.tar.gz: f63e094b0eccd481167a8b6fe789271f058f9265
5
+ SHA512:
6
+ metadata.gz: 815c4f75c9d5ee83f0b728dfaeab0d0ca5d64eae605695db5b3bdfafe975db5fac2b0f2550e378b8d5583b6b5e4d52853ab325df8288dd24ff521bfbe7703559
7
+ data.tar.gz: f98aeb0de7ab5d0c6ff3bd5abe01822fd639ddf476d52935d914378c41df5b729ccdd803889a31bc6ec72e1f9854898dfb56ec63fe7b3e95b6819dd40d386497
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ .DS_Store
10
+ .byebug_history
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,5 @@
1
+ specs_master:
2
+ only:
3
+ - master
4
+ script:
5
+ - ./bin/gitlab_runner_specs.sh
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,28 @@
1
+ AllCops:
2
+ Exclude:
3
+ - '*.gemspec'
4
+ - 'spec/vcr/**/*'
5
+
6
+ Documentation:
7
+ Enabled: false
8
+
9
+ Metrics/AbcSize:
10
+ Enabled: false
11
+
12
+ Metrics/ClassLength:
13
+ Max: 125
14
+
15
+ Metrics/LineLength:
16
+ Enabled: false
17
+
18
+ Metrics/MethodLength:
19
+ Enabled: false
20
+
21
+ Style/NumericLiterals:
22
+ Enabled: false
23
+
24
+ Style/RegexpLiteral:
25
+ Enabled: false
26
+
27
+ Style/SignalException:
28
+ Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.2
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in adparlor-facebook.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,136 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ adparlor-facebook (0.5.9)
5
+ faraday
6
+ faraday_middleware
7
+ httpclient
8
+ mime-types
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ addressable (2.6.0)
14
+ public_suffix (>= 2.0.2, < 4.0)
15
+ ast (2.4.0)
16
+ byebug (11.0.1)
17
+ coderay (1.1.2)
18
+ crack (0.4.3)
19
+ safe_yaml (~> 1.0.0)
20
+ diff-lcs (1.3)
21
+ docile (1.3.1)
22
+ faraday (0.15.4)
23
+ multipart-post (>= 1.2, < 3)
24
+ faraday_middleware (0.13.1)
25
+ faraday (>= 0.7.4, < 1.0)
26
+ ffi (1.10.0)
27
+ formatador (0.2.5)
28
+ guard (2.15.0)
29
+ formatador (>= 0.2.4)
30
+ listen (>= 2.7, < 4.0)
31
+ lumberjack (>= 1.0.12, < 2.0)
32
+ nenv (~> 0.1)
33
+ notiffany (~> 0.0)
34
+ pry (>= 0.9.12)
35
+ shellany (~> 0.0)
36
+ thor (>= 0.18.1)
37
+ guard-bundler (2.2.1)
38
+ bundler (>= 1.3.0, < 3)
39
+ guard (~> 2.2)
40
+ guard-compat (~> 1.1)
41
+ guard-compat (1.2.1)
42
+ guard-rspec (4.7.3)
43
+ guard (~> 2.1)
44
+ guard-compat (~> 1.1)
45
+ rspec (>= 2.99.0, < 4.0)
46
+ guard-rubocop (1.3.0)
47
+ guard (~> 2.0)
48
+ rubocop (~> 0.20)
49
+ hashdiff (0.3.9)
50
+ httpclient (2.8.3)
51
+ jaro_winkler (1.5.2)
52
+ json (2.2.0)
53
+ listen (3.1.5)
54
+ rb-fsevent (~> 0.9, >= 0.9.4)
55
+ rb-inotify (~> 0.9, >= 0.9.7)
56
+ ruby_dep (~> 1.2)
57
+ lumberjack (1.0.13)
58
+ method_source (0.9.2)
59
+ mime-types (3.2.2)
60
+ mime-types-data (~> 3.2015)
61
+ mime-types-data (3.2019.0331)
62
+ multipart-post (2.1.1)
63
+ nenv (0.3.0)
64
+ notiffany (0.1.1)
65
+ nenv (~> 0.1)
66
+ shellany (~> 0.0)
67
+ parallel (1.17.0)
68
+ parser (2.6.3.0)
69
+ ast (~> 2.4.0)
70
+ pry (0.12.2)
71
+ coderay (~> 1.1.0)
72
+ method_source (~> 0.9.0)
73
+ public_suffix (3.0.3)
74
+ rainbow (3.0.0)
75
+ rake (10.5.0)
76
+ rb-fsevent (0.10.3)
77
+ rb-inotify (0.10.0)
78
+ ffi (~> 1.0)
79
+ rspec (3.8.0)
80
+ rspec-core (~> 3.8.0)
81
+ rspec-expectations (~> 3.8.0)
82
+ rspec-mocks (~> 3.8.0)
83
+ rspec-core (3.8.0)
84
+ rspec-support (~> 3.8.0)
85
+ rspec-expectations (3.8.3)
86
+ diff-lcs (>= 1.2.0, < 2.0)
87
+ rspec-support (~> 3.8.0)
88
+ rspec-mocks (3.8.0)
89
+ diff-lcs (>= 1.2.0, < 2.0)
90
+ rspec-support (~> 3.8.0)
91
+ rspec-rerun (1.1.0)
92
+ rspec (~> 3.0)
93
+ rspec-support (3.8.0)
94
+ rubocop (0.69.0)
95
+ jaro_winkler (~> 1.5.1)
96
+ parallel (~> 1.10)
97
+ parser (>= 2.6)
98
+ rainbow (>= 2.2.2, < 4.0)
99
+ ruby-progressbar (~> 1.7)
100
+ unicode-display_width (>= 1.4.0, < 1.7)
101
+ ruby-progressbar (1.10.0)
102
+ ruby_dep (1.5.0)
103
+ safe_yaml (1.0.5)
104
+ shellany (0.0.1)
105
+ simplecov (0.16.1)
106
+ docile (~> 1.1)
107
+ json (>= 1.8, < 3)
108
+ simplecov-html (~> 0.10.0)
109
+ simplecov-html (0.10.2)
110
+ thor (0.20.3)
111
+ unicode-display_width (1.6.0)
112
+ vcr (4.0.0)
113
+ webmock (3.5.1)
114
+ addressable (>= 2.3.6)
115
+ crack (>= 0.3.2)
116
+ hashdiff
117
+
118
+ PLATFORMS
119
+ ruby
120
+
121
+ DEPENDENCIES
122
+ adparlor-facebook!
123
+ bundler (~> 1.10)
124
+ byebug
125
+ guard
126
+ guard-bundler
127
+ guard-rspec
128
+ guard-rubocop
129
+ rake (~> 10.0)
130
+ rspec-rerun
131
+ simplecov
132
+ vcr
133
+ webmock
134
+
135
+ BUNDLED WITH
136
+ 1.16.2
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rubocop, all_on_start: false do
5
+ watch(%r{.+\.rb$})
6
+ watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
7
+ end
8
+
9
+ guard :rspec, cmd: 'bundle exec rspec' do
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
12
+ watch('spec/spec_helper.rb') { 'spec' }
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Kel Stopper
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,164 @@
1
+ ### [![build status](https://gitlab.ak-networks.com/ci/projects/8/status.png?ref=master)](https://gitlab.ak-networks.com/ci/projects/8?ref=master) Master (GitLab CI)
2
+
3
+ ###[![](https://ci.solanolabs.com:443/AdParlor//badges/branches/master?badge_token=b5e0dec703fe9ae000ae346dceb0b7ddd53c91db)](https://ci.solanolabs.com:443/AdParlor/facebook_ruby_ads_sdk/suites/509306) Master (Solano CI)
4
+
5
+ # Adparlor::Facebook
6
+
7
+ The adparlor-facebook gem is a ruby library for interacting with the Facebook ads API. Supporting both REST and batch requests.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'adparlor-facebook', git: 'https://gitlab.ak-networks.com/adparlor/facebook_ruby_ads_sdk.git'
15
+ ```
16
+
17
+ or locally for development
18
+
19
+ ```bash
20
+ bundle config local.adparlor-facebook ~/Projects/facebook_ruby_ads_sdk
21
+ ```
22
+
23
+ ```ruby
24
+ gem 'adparlor-facebook', branch: 'master'
25
+ ```
26
+
27
+ And then execute:
28
+
29
+ $ bundle
30
+
31
+ <!-- Or install it yourself as:) -->
32
+
33
+ <!-- $ gem install adparlor-facebook) -->
34
+
35
+ ## Usage
36
+
37
+ ### Graph API
38
+
39
+ Once an access token is obtained [https://developers.facebook.com/docs/facebook-login/access-tokens](https://developers.facebook.com/docs/facebook-login/access-tokens) you can begin
40
+ making requests to the GraphApi.
41
+
42
+ ```ruby
43
+ #Get an ad account by the id
44
+ account = Adparlor::Facebook::GraphApi::AdAccount.get(account_id, access_token: 'access_token')
45
+ account.name #-> 'the account name'
46
+ account.account_status #-> 'the account status'
47
+
48
+ #Get an ad creative by the id
49
+ creative = Adparlor::Facebook::GraphApi::AdCreative.get(creative_id, access_token: 'access_token')
50
+ creative.id #-> '11111111111111111'
51
+
52
+ #The Get method also takes the fields option like the graph api by default only returning the minimal fields
53
+ creative = Adparlor::Facebook::GraphApi::AdCreative.get(creative_id, access_token: 'access_token', fields: %w(body image_hash image_url ...))
54
+ #OR
55
+ creative = Adparlor::Facebook::GraphApi::AdCreative.get(creative_id, access_token: 'access_token', fields: Adparlor::Facebook::GraphApi::AdCreative.fields(:all))
56
+ creative.id #-> '11111111111111111'
57
+ creative.name #-> 'the creatives name'
58
+ creative.thumbnail_url #-> 'https://facebook.com/image...'
59
+
60
+ #You can also get objects by their edges as referred to in the Facebook documentation
61
+ #which returns a memoized array of object types.
62
+ account = Adparlor::Facebook::GraphApi::AdAccount.get(account_id, access_token: 'access_token')
63
+ account.adcreatives.all #-> [Adparlor::Facebook::GraphApi::AdCreative<...>, Adparlor::Facebook::GraphApi::AdCreative<...>, Adparlor::Facebook::GraphApi::AdCreative<...>, ...]
64
+ account.adimages.all #-> [Adparlor::Facebook::GraphApi::AdImage<...>, Adparlor::Facebook::GraphApi::AdImage<...>, Adparlor::Facebook::GraphApi::AdImage<...>, ...]
65
+ account.campaigns.all #-> [Adparlor::Facebook::GraphApi::Campaign<...>, Adparlor::Facebook::GraphApi::Campaign<...>, Adparlor::Facebook::GraphApi::Campaign<...>, ...]
66
+
67
+ #The all method also takes the fields option like the graph api by default only returning the minimal fields
68
+ account.adcreatives.all.first #-> Adparlor::Facebook::GraphApi::AdCreative<@id => '1111111111111111'>
69
+ account.adcreatives.all(Adparlor::Facebook::GraphApi::AdCreative.fields(:all))).first #-> Adparlor::Facebook::GraphApi::AdCreative<@id='1111111111111111', @body='...', @image_hash='...'>
70
+
71
+ #The edges also implement create and delete options
72
+ account.adimages.delete(hash: '6aec0dd976393abfad84e8f2511960a8') #-> response.body = {"success" => true}
73
+
74
+ account.adimages.create(source: 'http://www.example.com/url/to/image.png')
75
+ #OR
76
+ account.adimages.create(source: '/path/to/image.png') #-> response.body = :images => { :url => 'https://facebook.com/image/localtion.png', :hash => 'd0f7567af280e1f6760457ff4df782d8' }
77
+ ```
78
+
79
+ ### Batch requests
80
+
81
+ If making large numbers of requests at the same time or requests that depend on each other the batch object can be used.
82
+ ```ruby
83
+ #The batch api requires an access token in the case some of the requests use different tokens
84
+ #or one is not supplied for fallback purposes.
85
+ account = Adparlor::Facebook::GraphApi::AdAccount.get(account_id, access_token: 'access_token')
86
+ response = account.batch do |batch|
87
+ batch.get account.id, AdImage, fields: [:id, :name, :hash] # uses the parent objects token
88
+ batch.get account.id, Campaign, access_token: account.access_token # uses the parent objects token but it is supplied
89
+ batch.get account2.id, AdImage, access_token: account2.access_token, fields: [:id, :name, :height]
90
+ end
91
+ response #-> [[AdImage, AdImage, ...],[Campaign, Campaign, ...],[AdImage, AdImage, ...]]
92
+
93
+ #The object can also be created without an account if the requests are all different accounts or non account level objects
94
+ #This will use the access token of the first object to be the top level access token
95
+ response = Adparlor::Facebook::GraphObject.new.batch do |batch|
96
+ batch.get nil, AdCreative, id: '6666666666666', access_token: 'access_token'
97
+ batch.get nil, AdCreative, id: '7777777777777', access_token: 'access_token'
98
+ end
99
+
100
+ #Posting follows the same style request, files should be accompanied by the source key.
101
+ response = account.batch do |batch|
102
+ batch.post account.id, AdImage, source: 'http://www.example.com/url/for/image.png' # uses the parent objects token
103
+ batch.post account2.id, AdImage, source: 'http://www.example.com/url/for/othe-image.png', access_token: account2.access_token # uses its own token
104
+ end
105
+ response #-> [AdImage, AdImage]
106
+
107
+ #Deleting follows the same style request
108
+ response = account.batch do |batch|
109
+ batch.delete account.id, AdImage, hash: 'bee06e2e03f9b5a32419855e2c7a4225'
110
+ batch.delete account.id, AdImage, hash: 'd8ebd0caddecb512ec3b782ae9498e13'
111
+ end
112
+
113
+ #You can mix up requests
114
+ response = account.batch do |batch|
115
+ batch.post account.id, AdImage, source: 'http://www.example.com/url/for/image.png'
116
+ batch.post account2.id, AdImage, source: 'http://www.example.com/url/for/othe-image.png', access_token: account2.access_token
117
+ batch.get account.id, AdImage, fields: [:id, :name, :hash]
118
+ batch.get account.id, Campaign
119
+ end
120
+ response #-> [AdImage, AdImage, [AdImage, AdImage, ...],[Campaign, Campaign, ...]]
121
+
122
+ #You can post requests that are dependent on other requests
123
+ #In this case the post that another post is dependent on will supply a name to the options parameter
124
+ #which is then referred to in dependents posts appropriate column.
125
+ #in this case the campaign post gets the name 'create_campaign' the following request refers to it
126
+ #using the JSONPath expression format required by the batch api '{result=create_campaign:$.id}'
127
+ # for more information visit: https://developers.facebook.com/docs/marketing-api/batch-requests/v2.5
128
+ response = account.batch do |batch|
129
+ batch.post account.id, Campaign,
130
+ { name: 'A Test Campaign', objective: 'LOCAL_AWARENESS', status: 'PAUSED' },
131
+ name: 'create_campaign'
132
+ batch.post account.id, AdSet,
133
+ name: 'A Test AdSet', daily_budget: 135, start_time: '00:05:00',
134
+ campaign_id: '{result=create_campaign:$.id}', bid_amount: 150,
135
+ billing_event: 'IMPRESSIONS', optimization_goal: 'REACH',
136
+ targeting: {
137
+ geo_locations: { cities: [{ key: '2418956', radius: 12, distance_unit: 'mile' }] },
138
+ page_types: %w(desktopfeed mobilefeed)
139
+ }, status: 'PAUSED',
140
+ promoted_object: { page_id: your_page_id }
141
+ end
142
+ response #-> [null, AdSet]
143
+ ```
144
+
145
+ ## Development
146
+
147
+ 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.
148
+
149
+ <!-- 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). -->
150
+
151
+ <!-- ## Contributing -->
152
+
153
+ <!-- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/adparlor-facebook. -->
154
+
155
+ ## License
156
+
157
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
158
+
159
+ ## TODO
160
+
161
+ * Create requests should probably return an instance of the object instead of the Faraday body
162
+ * ?Delete requests should return true if deleted or error message?
163
+ * Continue to add endpoints
164
+ * More configurable tests for testing live instead of the vcr cassettes.
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec-rerun/tasks'
3
+ task default: 'rspec-rerun:spec'
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'adparlor/facebook/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'adparlor-facebook'
8
+ spec.version = Adparlor::Facebook::VERSION
9
+ spec.authors = ['Kel Stopper', 'Lukas Beaton']
10
+ spec.email = ['kstopper@adparlor.com', 'lbeaton@adparlor.com']
11
+
12
+ spec.summary = 'A ruby implementation of the facebook sdk'
13
+ spec.description = 'The adparlor-facebook gem is a ruby library for interacting with the Facebook ads API. Supporting both REST and batch requests.'
14
+ spec.homepage = 'http://adparlor.com'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.10'
23
+ spec.add_development_dependency 'guard'
24
+ spec.add_development_dependency 'guard-bundler'
25
+ spec.add_development_dependency 'guard-rspec'
26
+ spec.add_development_dependency 'guard-rubocop'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rspec-rerun'
29
+ spec.add_development_dependency 'simplecov'
30
+ spec.add_development_dependency 'vcr'
31
+ spec.add_development_dependency 'webmock'
32
+ spec.add_development_dependency 'byebug'
33
+
34
+ spec.add_dependency 'faraday'
35
+ spec.add_dependency 'faraday_middleware'
36
+ spec.add_dependency 'httpclient'
37
+ spec.add_dependency 'mime-types'
38
+ end
data/bin/console ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'adparlor/facebook'
5
+
6
+ Adparlor::Facebook.configure do |config|
7
+ config.api_version = 'v2.5'
8
+ end
9
+
10
+ # You can add fixtures and/or initialization code here to make experimenting
11
+ # with your gem easier. You can also use a different console, if you like.
12
+
13
+ # (If you use this, don't forget to add pry to your Gemfile!)
14
+ # require "pry"
15
+ # Pry.start
16
+
17
+ require 'irb'
18
+ IRB.start
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+
3
+ printf "\n\nRUNNER SCRIPT: Running as `whoami`"
4
+ printf "\n\nRUNNER SCRIPT: Running in directory `pwd`"
5
+
6
+ printf "\n\nRUNNER SCRIPT: Environment Variables..."
7
+ printf "\n\n`printenv`"
8
+
9
+ printf "\n\nRUNNER SCRIPT: Installing Gems...\n"
10
+ source ~/.bash_profile
11
+ rbenv local 2.0.0-p353
12
+ bin/setup
13
+ errcode=$?
14
+
15
+ if [ "$errcode" != 0 ]
16
+ then
17
+ printf "\n\nRUNNER SCRIPT: Gem installation failed!"
18
+ exit $errcode
19
+ fi
20
+
21
+ printf "\n\nRUNNER SCRIPT: Running specs...\n"
22
+ VCR_RECORD=all bundle exec rake rspec-rerun:spec
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,106 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+
4
+ module Adparlor
5
+ module Facebook
6
+ module MultipleRequestParamsEncoder
7
+ def self.encode(query_hash)
8
+ ids_path(query_hash.delete(:ids), query_hash.delete(:fields), query_hash.delete(:access_token))
9
+ end
10
+
11
+ def self.ids_path(ids, fields, access_token)
12
+ "ids=[#{ids.join(',')}]&fields=#{fields}&access_token=#{access_token}"
13
+ end
14
+ end
15
+
16
+ module Api
17
+ def base_uri
18
+ Adparlor::Facebook.configuration.base_uri
19
+ end
20
+
21
+ def proxy_api_key
22
+ Adparlor::Facebook.configuration.proxy_api_key
23
+ end
24
+
25
+ def conn
26
+ Faraday.default_adapter = :httpclient
27
+ @conn ||= Faraday.new do |faraday|
28
+ faraday.request :multipart
29
+ faraday.request :retry, max: 3, exceptions: [Exception]
30
+ faraday.request :url_encoded
31
+ faraday.response :json
32
+ faraday.adapter Faraday.default_adapter
33
+ faraday.headers['x-api-key'] = proxy_api_key unless proxy_api_key.nil?
34
+ end
35
+ end
36
+
37
+ def conn_multi
38
+ @conn_multi ||= Faraday.new(
39
+ full_url('', {}), request: { params_encoder: Adparlor::Facebook::MultipleRequestParamsEncoder }
40
+ ) do |faraday|
41
+ faraday.request :retry, max: 3, exceptions: [Exception]
42
+ faraday.response :json
43
+ faraday.adapter Faraday.default_adapter
44
+ faraday.headers['x-api-key'] = proxy_api_key unless proxy_api_key.nil?
45
+ end
46
+ end
47
+
48
+ def get(path, options = {})
49
+ options[:fields] = self.class.fields(*options[:fields]) if options[:fields] && options[:fields].is_a?(Array)
50
+ raise FbError.new('required parameter access_token missing', 500) unless options[:access_token] || path.include?('access_token')
51
+ if path.to_s.empty? && options.key?(:ids)
52
+ conn_multi.get '', options
53
+ else
54
+ conn.get full_url(path, options), options
55
+ end
56
+ rescue Faraday::ParsingError
57
+ # FB has returned some data that we can't parse into JSON
58
+ raise FbError.new("Unable to make request.", 500)
59
+ end
60
+
61
+ def post(path, options = {}, method = 'CREATE')
62
+ self.class.validate_post_fields(*instance_variables.map { |k| k.to_s.delete('@') }, method) if self.class.respond_to?(:validate_post_fields)
63
+ raise FbError.new('required parameter access_token missing', 500) unless options[:access_token] || path.include?('access_token')
64
+ body = instance_variables.each_with_object({}) { |var, hash| hash[var.to_s.sub(/@/, '').to_sym] = instance_variable_get(var) }
65
+ content_type_header = options.delete(:content_type_header)
66
+ content_type_header ||= body[:source].respond_to?(:content_type) || !@files.nil? ? 'multipart/form-data' : 'application/json'
67
+ body.delete(:files)
68
+ body[:bytes] = Base64.encode64(open(body.delete(:source).io, &:read)) if body.key?(:source)
69
+ conn.post full_url(path, options) do |request|
70
+ request.headers['Content-Type'] = content_type_header
71
+ request.params = options
72
+ request.body = content_type_header == 'multipart/form-data' ? (@files || {}).merge(body) : body.to_json
73
+ end
74
+ rescue Faraday::ParsingError
75
+ # FB has returned some data that we can't parse into JSON
76
+ raise FbError.new("Unable to make request.", 500)
77
+ end
78
+
79
+ def delete(path, options = {})
80
+ raise FbError.new('required parameter access_token missing', 500) unless options[:access_token] || path.include?('access_token')
81
+ conn.delete full_url(path, options) do |request|
82
+ request.headers['Content-Type'] = 'application/json'
83
+ request.params = options
84
+ request.body = instance_variables.each_with_object({}) { |var, hash| hash[var.to_s.sub(/@/, '').to_sym] = instance_variable_get(var) }.to_json
85
+ end
86
+ rescue Faraday::ParsingError
87
+ # FB has returned some data that we can't parse into JSON
88
+ raise FbError.new("Unable to make request.", 500)
89
+ end
90
+
91
+ private
92
+
93
+ def api_version(options)
94
+ "/#{options.delete(:api_version) || Adparlor::Facebook.configuration.api_version}/"
95
+ end
96
+
97
+ def full_url(path, options)
98
+ if URI.parse(path).scheme
99
+ path
100
+ else
101
+ URI.join(base_uri, api_version(options), path.gsub(%r{\A/}, ''))
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,24 @@
1
+ module Adparlor
2
+ module Facebook
3
+ class << self
4
+ attr_accessor :configuration
5
+
6
+ def configure
7
+ self.configuration ||= Configuration.new
8
+ yield configuration
9
+ end
10
+ end
11
+
12
+ class Configuration
13
+ attr_accessor :api_version
14
+ attr_accessor :base_uri
15
+ attr_accessor :proxy_api_key
16
+
17
+ def initialize
18
+ @api_version = 'v2.5'
19
+ @base_uri = 'https://graph.facebook.com'
20
+ @proxy_api_key = nil
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ module Adparlor
2
+ module Facebook
3
+ class Error < StandardError
4
+ attr_reader :error_code
5
+
6
+ def initialize(message, error_code = nil, error_attributes = {})
7
+ @error_code = error_code
8
+ error_attributes.each { |key, value| instance_variable_set("@#{key}".to_sym, value) }
9
+ super message
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Adparlor
2
+ module Facebook
3
+ module GraphApi
4
+ class Activity < GraphObject
5
+ include Fields::Activity
6
+ include Traits::Methods
7
+ field_attrs FIELDS
8
+ end
9
+ end
10
+ end
11
+ end