zuck 0.0.4

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