zuck 0.0.4

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 (52) hide show
  1. data/.rvmrc +1 -0
  2. data/.travis.yml +7 -0
  3. data/.yardopts +4 -0
  4. data/CHANGELOG.markdown +4 -0
  5. data/Gemfile +35 -0
  6. data/Gemfile.lock +110 -0
  7. data/Guardfile.dist +45 -0
  8. data/LICENSE.txt +20 -0
  9. data/README.markdown +138 -0
  10. data/Rakefile +39 -0
  11. data/VERSION +1 -0
  12. data/console +26 -0
  13. data/lib/zuck/facebook/ad_account.rb +40 -0
  14. data/lib/zuck/facebook/ad_campaign.rb +24 -0
  15. data/lib/zuck/facebook/ad_creative.rb +30 -0
  16. data/lib/zuck/facebook/ad_group.rb +39 -0
  17. data/lib/zuck/facebook/targeting_spec.rb +200 -0
  18. data/lib/zuck/fb_object/dsl.rb +110 -0
  19. data/lib/zuck/fb_object/error.rb +8 -0
  20. data/lib/zuck/fb_object/hash_delegator.rb +111 -0
  21. data/lib/zuck/fb_object/helpers.rb +57 -0
  22. data/lib/zuck/fb_object/read.rb +147 -0
  23. data/lib/zuck/fb_object/read_only.rb +0 -0
  24. data/lib/zuck/fb_object/write.rb +75 -0
  25. data/lib/zuck/fb_object.rb +53 -0
  26. data/lib/zuck/koala/koala_methods.rb +27 -0
  27. data/lib/zuck.rb +9 -0
  28. data/spec/fixtures/a_single_account.yml +75 -0
  29. data/spec/fixtures/a_single_campaign.yml +48 -0
  30. data/spec/fixtures/create_ad_campaign.yml +49 -0
  31. data/spec/fixtures/create_ad_group.yml +47 -0
  32. data/spec/fixtures/delete_ad_group.yml +50 -0
  33. data/spec/fixtures/find_a_single_campaign_and_update_it.yml +247 -0
  34. data/spec/fixtures/list_of_ad_accounts.yml +75 -0
  35. data/spec/fixtures/list_of_ad_campaigns.yml +76 -0
  36. data/spec/fixtures/list_of_ad_creatives.yml +51 -0
  37. data/spec/fixtures/list_of_ad_groups.yml +49 -0
  38. data/spec/fixtures/list_of_all_ad_creatives_of_account.yml +86 -0
  39. data/spec/fixtures/reach_for_invalid_keyword.yml +95 -0
  40. data/spec/fixtures/reach_for_valid_keywords.yml +93 -0
  41. data/spec/fixtures/reach_for_valid_keywords_male_young.yml +93 -0
  42. data/spec/lib/zuck/facebook/ad_account_spec.rb +26 -0
  43. data/spec/lib/zuck/facebook/ad_campaign_spec.rb +4 -0
  44. data/spec/lib/zuck/facebook/targeting_spec_spec.rb +174 -0
  45. data/spec/lib/zuck/fb_object/helpers_spec.rb +67 -0
  46. data/spec/lib/zuck/koala/koala_methods_spec.rb +30 -0
  47. data/spec/lib/zuck/util/hash_delegator_spec.rb +54 -0
  48. data/spec/lib/zuck_spec.rb +165 -0
  49. data/spec/spec_helper.rb +47 -0
  50. data/spec/vcr_setup.rb +15 -0
  51. data/zuck.gemspec +141 -0
  52. metadata +389 -0
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zuck::FbObject do
4
+
5
+ before(:all) do
6
+ Zuck.graph = Koala::Facebook::API.new('AAAEvJ5vzhl8BABhTSazJZB2D0B4N0l242VX22Hg9J2WZA7fptcAztfXxfAZB9mhZB6W1nl5dz5tXMlb9DJk9ibs6RqtP7PtO6a3XCiHWVwZDZD')
7
+ end
8
+
9
+ let(:graph) { Zuck.graph }
10
+ let(:account) { Zuck::AdAccount.new(graph, {id: "act_10150585630710217"}) }
11
+ let(:campaign){ Zuck::AdCampaign.new(graph, {id: "6005950787751"}, account) }
12
+ let(:group) { Zuck::AdGroup.new(graph, {id: "6004497038951"}, campaign)}
13
+ let(:creative){ Zuck::AdCreative.new(graph, {id: "1234567890123"}, group) }
14
+
15
+
16
+ describe "read only objects" do
17
+ it "can't be created" do
18
+ expect{
19
+ Zuck::AdCreative.create(:x, {}, :y)
20
+ }.to raise_error(Zuck::Error::ReadOnly)
21
+ end
22
+
23
+ it "can't be saved" do
24
+ expect{
25
+ creative.save
26
+ }.to raise_error(Zuck::Error::ReadOnly)
27
+ end
28
+
29
+ it "can't be destroyed" do
30
+ expect{
31
+ creative.destroy
32
+ }.to raise_error(Zuck::Error::ReadOnly)
33
+ end
34
+ end
35
+
36
+ describe "talking to facebook" do
37
+ context "reading" do
38
+
39
+ it "a list of ad accounts" do
40
+ VCR.use_cassette('list_of_ad_accounts') do
41
+ Zuck::AdAccount.all.should have(1).item
42
+ end
43
+ end
44
+
45
+ it "a list of ad campaigns" do
46
+ VCR.use_cassette('list_of_ad_campaigns') do
47
+ account.ad_campaigns.should have(3).items
48
+ end
49
+ end
50
+
51
+ it "a list of ad groups" do
52
+ VCR.use_cassette('list_of_ad_groups') do
53
+ campaign.ad_groups.should have(1).item
54
+ end
55
+ end
56
+
57
+ it "list of ad creatives" do
58
+ VCR.use_cassette('list_of_ad_creatives') do
59
+ group.ad_creatives.should have(1).items
60
+ end
61
+ end
62
+
63
+ it "list of all ad creatives of an account" do
64
+ g = graph
65
+ Zuck::AdAccount.should_receive(:all).and_return([account])
66
+ VCR.use_cassette('list_of_all_ad_creatives_of_account') do
67
+ Zuck::AdCreative.all(g).should have(6).items
68
+ end
69
+ end
70
+
71
+ context "an id directly" do
72
+
73
+ it "with the correct type" do
74
+ VCR.use_cassette('a_single_campaign') do
75
+ c = Zuck::AdCampaign.find(6005950787751, graph)
76
+ end
77
+ end
78
+
79
+ it "with the correct type" do
80
+ VCR.use_cassette('a_single_account') do
81
+ c = Zuck::AdAccount.find('act_10150585630710217', graph)
82
+ end
83
+ end
84
+
85
+ it "when expecting an ad group but the id belongs to a campaign" do
86
+ expected_error = <<-END_ERROR
87
+ Invalid type.
88
+
89
+ Expected data['id']="6005950787751" to be equal to one of these:
90
+ * data['account_id']="10150585630710217"
91
+ * data['group_id']=nil
92
+ * data['adgroup_id']=nil
93
+ END_ERROR
94
+ VCR.use_cassette('a_single_campaign') do
95
+ expect{
96
+ c = Zuck::AdGroup.find(6005950787751, graph)
97
+ }.to raise_error(expected_error)
98
+ end
99
+ end
100
+
101
+ it "and saving it" do
102
+ VCR.use_cassette('find_a_single_campaign_and_update_it') do
103
+ group = Zuck::AdGroup.find(6005859287551, graph)
104
+ group.name = "My old name"
105
+ group.save
106
+ group.name.should == "My old name"
107
+ group.name = "My new name"
108
+ group.save
109
+ group.name.should == "My new name"
110
+ group.reload
111
+ group.name.should == "My new name"
112
+ end
113
+ end
114
+
115
+ end
116
+ end
117
+
118
+
119
+ context "creating" do
120
+ it "an ad campaign" do
121
+ VCR.use_cassette('create_ad_campaign') do
122
+ o = {daily_budget: 1000, name: "bloody" }
123
+ campaign = Zuck::AdCampaign.create(graph, o, account)
124
+ campaign.name.should == "bloody"
125
+ end
126
+ end
127
+
128
+ it "an ad campaign via an existing ad account" do
129
+ VCR.use_cassette('create_ad_campaign') do
130
+ o = {daily_budget: 1000, name: "bloody" }
131
+ campaign = account.create_ad_campaign(o)
132
+ campaign.name.should == "bloody"
133
+ end
134
+ end
135
+
136
+ it "an ad group" do
137
+ VCR.use_cassette('create_ad_group') do
138
+ o = {bid_type: 1, max_bid: 1, name: "Rap like me", targeting: '{"countries":["US"]}',
139
+ creative: '{"type":25,"action_spec":{"action.type":"like", "post":10150420410887685}}'}
140
+ group = Zuck::AdGroup.create(graph, o, campaign)
141
+ group.name.should == "Rap like me"
142
+ end
143
+ end
144
+
145
+ it "an ad group via an existing ad campaign" do
146
+ VCR.use_cassette('create_ad_group') do
147
+ o = {bid_type: 1, max_bid: 1, name: "Rap like me", targeting: '{"countries":["US"]}',
148
+ creative: '{"type":25,"action_spec":{"action.type":"like", "post":10150420410887685}}'}
149
+ group = campaign.create_ad_group(o)
150
+ group.name.should == "Rap like me"
151
+ group.bid_type.should == 1
152
+ end
153
+ end
154
+ end
155
+
156
+ context "deleting" do
157
+ it "an ad group" do
158
+ VCR.use_cassette('delete_ad_group') do
159
+ group.destroy.should be_true
160
+ end
161
+ end
162
+ end
163
+
164
+ end
165
+ end
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ require 'bundler'
5
+ Bundler.require
6
+
7
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
8
+ ENV["RAILS_ENV"] ||= 'test'
9
+ # require File.expand_path("../../config/environment", __FILE__)
10
+ require 'webmock/rspec'
11
+ require 'vcr_setup'
12
+ #require 'capybara/poltergeist'
13
+
14
+ # Requires supporting ruby files with custom matchers and macros, etc,
15
+ # in spec/support/ and its subdirectories.
16
+ Dir[File.expand_path("../../spec/support/**/*.rb", __FILE__)].each {|f| require f}
17
+
18
+ RSpec.configure do |config|
19
+ # == Mock Framework
20
+ #
21
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
22
+ #
23
+ # config.mock_with :mocha
24
+ # config.mock_with :flexmock
25
+ # config.mock_with :rr
26
+ config.mock_with :rspec
27
+
28
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
29
+
30
+ end
31
+
32
+ module TestResponseExtensions
33
+ def json_body
34
+ JSON.parse(self.body)
35
+ end
36
+
37
+ def unauthorized?
38
+ code.to_i == 401
39
+ end
40
+ end
41
+
42
+ def expect_id_and_return(id, ret_val)
43
+ lambda { |id| id.to_s.should == id.to_s; ret_val }
44
+ end
45
+
46
+
47
+ require File.expand_path("../../lib/zuck", __FILE__)
data/spec/vcr_setup.rb ADDED
@@ -0,0 +1,15 @@
1
+ # VCR Config
2
+ require 'vcr'
3
+ FileUtils.mkdir("log") rescue nil
4
+ VCR.configure do |c|
5
+ dir = File.expand_path("../../spec/fixtures", __FILE__)
6
+ c.cassette_library_dir = dir
7
+ c.hook_into :webmock
8
+ c.ignore_localhost = true
9
+ c.default_cassette_options = {
10
+ record: :new_episodes,
11
+ match_requests_on: [:method, :body, :uri]
12
+ }
13
+ c.allow_http_connections_when_no_cassette = false
14
+ c.debug_logger = File.open(File.expand_path("../../log/vcr.log", __FILE__), "w")
15
+ end
data/zuck.gemspec ADDED
@@ -0,0 +1,141 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "zuck"
8
+ s.version = "0.0.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jannis Hermanns"]
12
+ s.date = "2013-01-03"
13
+ s.description = "This gem allows to easily access facebook's ads api in ruby. See https://developers.facebook.com/docs/reference/ads-api/"
14
+ s.email = "jannis@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".rvmrc",
21
+ ".travis.yml",
22
+ ".yardopts",
23
+ "CHANGELOG.markdown",
24
+ "Gemfile",
25
+ "Gemfile.lock",
26
+ "Guardfile.dist",
27
+ "LICENSE.txt",
28
+ "README.markdown",
29
+ "Rakefile",
30
+ "VERSION",
31
+ "console",
32
+ "lib/zuck.rb",
33
+ "lib/zuck/facebook/ad_account.rb",
34
+ "lib/zuck/facebook/ad_campaign.rb",
35
+ "lib/zuck/facebook/ad_creative.rb",
36
+ "lib/zuck/facebook/ad_group.rb",
37
+ "lib/zuck/facebook/targeting_spec.rb",
38
+ "lib/zuck/fb_object.rb",
39
+ "lib/zuck/fb_object/dsl.rb",
40
+ "lib/zuck/fb_object/error.rb",
41
+ "lib/zuck/fb_object/hash_delegator.rb",
42
+ "lib/zuck/fb_object/helpers.rb",
43
+ "lib/zuck/fb_object/read.rb",
44
+ "lib/zuck/fb_object/read_only.rb",
45
+ "lib/zuck/fb_object/write.rb",
46
+ "lib/zuck/koala/koala_methods.rb",
47
+ "spec/fixtures/a_single_account.yml",
48
+ "spec/fixtures/a_single_campaign.yml",
49
+ "spec/fixtures/create_ad_campaign.yml",
50
+ "spec/fixtures/create_ad_group.yml",
51
+ "spec/fixtures/delete_ad_group.yml",
52
+ "spec/fixtures/find_a_single_campaign_and_update_it.yml",
53
+ "spec/fixtures/list_of_ad_accounts.yml",
54
+ "spec/fixtures/list_of_ad_campaigns.yml",
55
+ "spec/fixtures/list_of_ad_creatives.yml",
56
+ "spec/fixtures/list_of_ad_groups.yml",
57
+ "spec/fixtures/list_of_all_ad_creatives_of_account.yml",
58
+ "spec/fixtures/reach_for_invalid_keyword.yml",
59
+ "spec/fixtures/reach_for_valid_keywords.yml",
60
+ "spec/fixtures/reach_for_valid_keywords_male_young.yml",
61
+ "spec/lib/zuck/facebook/ad_account_spec.rb",
62
+ "spec/lib/zuck/facebook/ad_campaign_spec.rb",
63
+ "spec/lib/zuck/facebook/targeting_spec_spec.rb",
64
+ "spec/lib/zuck/fb_object/helpers_spec.rb",
65
+ "spec/lib/zuck/koala/koala_methods_spec.rb",
66
+ "spec/lib/zuck/util/hash_delegator_spec.rb",
67
+ "spec/lib/zuck_spec.rb",
68
+ "spec/spec_helper.rb",
69
+ "spec/vcr_setup.rb",
70
+ "zuck.gemspec"
71
+ ]
72
+ s.homepage = "http://github.com/jayniz/zuck"
73
+ s.licenses = ["MIT"]
74
+ s.require_paths = ["lib"]
75
+ s.rubygems_version = "1.8.24"
76
+ s.summary = "Ruby adapter to facebook's ad api"
77
+
78
+ if s.respond_to? :specification_version then
79
+ s.specification_version = 3
80
+
81
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
82
+ s.add_runtime_dependency(%q<rvm>, [">= 0"])
83
+ s.add_runtime_dependency(%q<bundler>, [">= 0"])
84
+ s.add_runtime_dependency(%q<koala>, [">= 1.5"])
85
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
86
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
87
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
88
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
89
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
90
+ s.add_development_dependency(%q<webmock>, [">= 0"])
91
+ s.add_development_dependency(%q<rspec>, [">= 0"])
92
+ s.add_development_dependency(%q<vcr>, [">= 0"])
93
+ s.add_development_dependency(%q<guard>, [">= 0"])
94
+ s.add_development_dependency(%q<guard-rspec>, [">= 0"])
95
+ s.add_development_dependency(%q<guard-bundler>, [">= 0"])
96
+ s.add_development_dependency(%q<guard-yard>, [">= 0"])
97
+ s.add_development_dependency(%q<growl>, [">= 0"])
98
+ s.add_development_dependency(%q<redcarpet>, [">= 0"])
99
+ s.add_development_dependency(%q<rb-fsevent>, [">= 0"])
100
+ else
101
+ s.add_dependency(%q<rvm>, [">= 0"])
102
+ s.add_dependency(%q<bundler>, [">= 0"])
103
+ s.add_dependency(%q<koala>, [">= 1.5"])
104
+ s.add_dependency(%q<activesupport>, [">= 0"])
105
+ s.add_dependency(%q<shoulda>, [">= 0"])
106
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
107
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
108
+ s.add_dependency(%q<simplecov>, [">= 0"])
109
+ s.add_dependency(%q<webmock>, [">= 0"])
110
+ s.add_dependency(%q<rspec>, [">= 0"])
111
+ s.add_dependency(%q<vcr>, [">= 0"])
112
+ s.add_dependency(%q<guard>, [">= 0"])
113
+ s.add_dependency(%q<guard-rspec>, [">= 0"])
114
+ s.add_dependency(%q<guard-bundler>, [">= 0"])
115
+ s.add_dependency(%q<guard-yard>, [">= 0"])
116
+ s.add_dependency(%q<growl>, [">= 0"])
117
+ s.add_dependency(%q<redcarpet>, [">= 0"])
118
+ s.add_dependency(%q<rb-fsevent>, [">= 0"])
119
+ end
120
+ else
121
+ s.add_dependency(%q<rvm>, [">= 0"])
122
+ s.add_dependency(%q<bundler>, [">= 0"])
123
+ s.add_dependency(%q<koala>, [">= 1.5"])
124
+ s.add_dependency(%q<activesupport>, [">= 0"])
125
+ s.add_dependency(%q<shoulda>, [">= 0"])
126
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
127
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
128
+ s.add_dependency(%q<simplecov>, [">= 0"])
129
+ s.add_dependency(%q<webmock>, [">= 0"])
130
+ s.add_dependency(%q<rspec>, [">= 0"])
131
+ s.add_dependency(%q<vcr>, [">= 0"])
132
+ s.add_dependency(%q<guard>, [">= 0"])
133
+ s.add_dependency(%q<guard-rspec>, [">= 0"])
134
+ s.add_dependency(%q<guard-bundler>, [">= 0"])
135
+ s.add_dependency(%q<guard-yard>, [">= 0"])
136
+ s.add_dependency(%q<growl>, [">= 0"])
137
+ s.add_dependency(%q<redcarpet>, [">= 0"])
138
+ s.add_dependency(%q<rb-fsevent>, [">= 0"])
139
+ end
140
+ end
141
+