francois-ad_gear_client 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1 @@
1
+ lib/**/*.rb
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ pkg
5
+ doc
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2009 François Beausoleil
2
+ Copyright (c) 2009 Bloom Digital Platforms
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = ad_gear_client
2
+
3
+ This gem is Ruby 1.8.6, Ruby 1.8.7, Ruby 1.9 and JRuby 1.3 compatible.
4
+
5
+ AdGear::Client is a client for accessing AdGear's RESTian web service.
6
+
7
+ AdGear is a product of Bloom Digital Platforms, a Montreal-based company founded in 2008. Through the AdGear family of products Bloom provides advertising management solutions to publishers, ad networks and platform developers looking to monetize their audiences.
8
+
9
+ == Dependencies
10
+
11
+ AdGear::Client works best with the ActiveResource branch made by François Beausoleil, at http://github.com/francois/rails. This branch of ActiveResource supports Digest authentication. AdGear::Client will work wihout that branch, but without Digest authentication.
12
+
13
+ == Copyright
14
+
15
+ Copyright (c) 2009 François Beausoleil.
16
+ Copyright (c) 2009 Bloom Digital Platforms
17
+ See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,117 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = "ad_gear_client"
10
+ gem.summary = %Q{A Ruby client for accessing AdGear http://bloomdigital.com/}
11
+ gem.email = "francois@teksol.info"
12
+ gem.homepage = "http://github.com/francois/ad_gear_client"
13
+ gem.authors = ["François Beausoleil"]
14
+ gem.rubyforge_project = "ad_gear_client"
15
+
16
+ gem.add_development_dependency "lsegal-yard", ">= 0.2.3"
17
+ gem.add_development_dependency "mocha", ">= 0.9.5"
18
+
19
+ gem.add_dependency "activeresource", "> 2.0"
20
+ gem.add_dependency "francois-rest-client", "~> 1"
21
+ end
22
+
23
+ Jeweler::RubyforgeTasks.new
24
+ rescue LoadError
25
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
26
+ end
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.libs << "vendor/activesupport/lib" if File.directory?("vendor/activesupport/lib")
32
+ test.libs << "vendor/activemodel/lib" if File.directory?("vendor/activemodel/lib")
33
+ test.libs << "vendor/activeresource/lib" if File.directory?("vendor/activeresource/lib")
34
+
35
+ test.pattern = 'test/**/*_test.rb'
36
+ test.verbose = true
37
+ end
38
+
39
+ begin
40
+ require 'rcov/rcovtask'
41
+ Rcov::RcovTask.new do |test|
42
+ test.libs << 'test'
43
+ test.pattern = 'test/**/*_test.rb'
44
+ test.verbose = true
45
+ end
46
+ rescue LoadError
47
+ task :rcov do
48
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
49
+ end
50
+ end
51
+
52
+
53
+ task :default => :test
54
+
55
+ module AdGear
56
+ if File.exist?("VERSION")
57
+ Version = File.read("VERSION")
58
+ else
59
+ Version = ""
60
+ end
61
+ end
62
+
63
+ begin
64
+ require "yard"
65
+ YARD::Rake::YardocTask.new(:doc) do |t|
66
+ t.options = ["--title", "AdGear::Client #{AdGear::Version}", "--readme", "README.rdoc"]
67
+ end
68
+
69
+ namespace :doc do
70
+ desc "Blow away all generated documentation"
71
+ task :clean do
72
+ rm_rf "doc"
73
+ end
74
+ end
75
+
76
+ task :doc => "doc:clean"
77
+ rescue LoadError
78
+ STDERR.puts "YARD is not available. In order to generate the best possible documentation, install YARD: sudo gem install yard"
79
+
80
+ require 'rake/rdoctask'
81
+ Rake::RDocTask.new(:doc) do |rdoc|
82
+ rdoc.rdoc_dir = "doc"
83
+ rdoc.title = "AdGear::Client #{AdGear::Version}"
84
+
85
+ rdoc.rdoc_files.include('README*')
86
+ rdoc.rdoc_files.include('lib/**/*.rb')
87
+ end
88
+ end
89
+
90
+ desc "Runs tests under all supported multiruby versions"
91
+ task :multi do
92
+ tests = FileList["test/**/*_test.rb"].map do |file|
93
+ 'require "%s"' % file
94
+ end.join("; ")
95
+ sh %{ multiruby -w -Ilib:test -e 'require "rubygems"; require "test/unit"; #{tests}' }
96
+ end
97
+
98
+ namespace :test do
99
+ desc "Do a live test against http://adgear.local/"
100
+ task :live do
101
+ base_url = ENV["BASE_URL"] || "http://adgear.local/api/services"
102
+ $:.unshift "lib"
103
+ require "ad_gear"
104
+
105
+ begin
106
+ client = AdGear::Client.new("francois", "94457f97dd3aa153c05257104e59a90f41a8110184cdefc8e52e4e295e48a782", :base_url => base_url, :logger => Logger.new(STDOUT))
107
+ p client.sites
108
+ rescue
109
+ puts $!
110
+ puts $!.backtrace
111
+ end
112
+ end
113
+ end
114
+
115
+ task :shell do
116
+ sh "irb -Ilib:vendor/activeresource/lib:vendor/activemodel/lib:vendor/activesupport/lib -rad_gear"
117
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,96 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{ad_gear_client}
5
+ s.version = "0.1.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Fran\303\247ois Beausoleil"]
9
+ s.date = %q{2009-08-12}
10
+ s.email = %q{francois@teksol.info}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".document",
17
+ ".gitignore",
18
+ "LICENSE",
19
+ "README.rdoc",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "ad_gear_client.gemspec",
23
+ "examples/.gitignore",
24
+ "examples/ad_gear.yml.sample",
25
+ "examples/prelude.rb",
26
+ "examples/read_write_site.rb",
27
+ "examples/upload_file_to_ad_unit.rb",
28
+ "lib/ad_gear.rb",
29
+ "lib/ad_gear/ad_spot.rb",
30
+ "lib/ad_gear/ad_unit.rb",
31
+ "lib/ad_gear/ad_unit_click.rb",
32
+ "lib/ad_gear/ad_unit_file.rb",
33
+ "lib/ad_gear/ad_unit_interaction.rb",
34
+ "lib/ad_gear/ad_unit_variable.rb",
35
+ "lib/ad_gear/base.rb",
36
+ "lib/ad_gear/campaign.rb",
37
+ "lib/ad_gear/click.rb",
38
+ "lib/ad_gear/config.rb",
39
+ "lib/ad_gear/file.rb",
40
+ "lib/ad_gear/format.rb",
41
+ "lib/ad_gear/has_many_array.rb",
42
+ "lib/ad_gear/interaction.rb",
43
+ "lib/ad_gear/site.rb",
44
+ "lib/ad_gear/template.rb",
45
+ "lib/ad_gear/upload.rb",
46
+ "lib/ad_gear/variable.rb",
47
+ "lib/ad_gear/xml_format.rb",
48
+ "lib/core_ext.rb",
49
+ "test/ad_gear/ad_spot_test.rb",
50
+ "test/ad_gear/config_test.rb",
51
+ "test/ad_gear/site_test.rb",
52
+ "test/ad_gear/upload_test.rb",
53
+ "test/ad_gear_test.rb",
54
+ "test/fixtures/access-denied-no-auth.txt",
55
+ "test/test_helper.rb"
56
+ ]
57
+ s.homepage = %q{http://github.com/francois/ad_gear_client}
58
+ s.rdoc_options = ["--charset=UTF-8"]
59
+ s.require_paths = ["lib"]
60
+ s.rubyforge_project = %q{ad_gear_client}
61
+ s.rubygems_version = %q{1.3.5}
62
+ s.summary = %q{A Ruby client for accessing AdGear http://bloomdigital.com/}
63
+ s.test_files = [
64
+ "test/ad_gear/ad_spot_test.rb",
65
+ "test/ad_gear/config_test.rb",
66
+ "test/ad_gear/site_test.rb",
67
+ "test/ad_gear/upload_test.rb",
68
+ "test/ad_gear_test.rb",
69
+ "test/test_helper.rb",
70
+ "examples/prelude.rb",
71
+ "examples/read_write_site.rb",
72
+ "examples/upload_file_to_ad_unit.rb"
73
+ ]
74
+
75
+ if s.respond_to? :specification_version then
76
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
77
+ s.specification_version = 3
78
+
79
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
80
+ s.add_development_dependency(%q<lsegal-yard>, [">= 0.2.3"])
81
+ s.add_development_dependency(%q<mocha>, [">= 0.9.5"])
82
+ s.add_runtime_dependency(%q<activeresource>, ["> 2.0"])
83
+ s.add_runtime_dependency(%q<francois-rest-client>, ["~> 1"])
84
+ else
85
+ s.add_dependency(%q<lsegal-yard>, [">= 0.2.3"])
86
+ s.add_dependency(%q<mocha>, [">= 0.9.5"])
87
+ s.add_dependency(%q<activeresource>, ["> 2.0"])
88
+ s.add_dependency(%q<francois-rest-client>, ["~> 1"])
89
+ end
90
+ else
91
+ s.add_dependency(%q<lsegal-yard>, [">= 0.2.3"])
92
+ s.add_dependency(%q<mocha>, [">= 0.9.5"])
93
+ s.add_dependency(%q<activeresource>, ["> 2.0"])
94
+ s.add_dependency(%q<francois-rest-client>, ["~> 1"])
95
+ end
96
+ end
@@ -0,0 +1 @@
1
+ ad_gear.yml
@@ -0,0 +1,8 @@
1
+ ---
2
+ development:
3
+ site: http://adgear.local/api
4
+ user: francois
5
+ password: 94457f97dd3aa153c05257104e59a90f41a8110184cdefc8e52e4e295e48a782
6
+ use_basic_authentication: false
7
+ use_digest_authentication: true
8
+ logger: STDERR
@@ -0,0 +1,18 @@
1
+ $:.unshift "../lib"
2
+ %w(activesupport activemodel activeresource rest-client).each do |lib|
3
+ $:.unshift "../vendor/#{lib}/lib" if File.directory?("../vendor/#{lib}/lib")
4
+ end
5
+
6
+ require "ad_gear"
7
+ require "pp"
8
+
9
+ begin
10
+ require "ruby-debug"
11
+ rescue LoadError
12
+ # Ignored under 1.9, JRuby
13
+ end
14
+
15
+ require "test/unit/assertions"
16
+ include Test::Unit::Assertions
17
+
18
+ AdGear.config = AdGear::Config.new("ad_gear.yml", "development")
@@ -0,0 +1,32 @@
1
+ require "prelude"
2
+
3
+ p AdGear::Site.find(:all)
4
+
5
+ formats = AdGear::Format.find(:all)
6
+ site = AdGear::Site.new(:name => "XLsuite", :url => "http://xlsuite.com/", :ad_spots => [{:format_id => formats.first.id, :name => "sidebar top"}])
7
+ site.ad_spots << AdGear::AdSpot.new(:format_id => formats.first.id, :name => "homepage banner")
8
+
9
+ begin
10
+ p site.new?
11
+ p site.save
12
+ p site.new?
13
+ p "Saved"
14
+
15
+ p site.embed_code
16
+ p site.ad_spots
17
+
18
+ p site.ad_spots.class
19
+
20
+ site.ad_spots << AdGear::AdSpot.new(:format_id => formats.first.id, :name => "homepage vertical")
21
+ site.ad_spots.detect {|as| as.name == "homepage banner"}.name = "home page banner"
22
+ assert_equal 3, site.ad_spots.length, site.to_xml
23
+
24
+ puts site.to_xml
25
+ site.save
26
+
27
+ p "After PUT"
28
+ assert_equal 3, site.ad_spots.length, site.to_xml
29
+ rescue ActiveResource::BadRequest => e
30
+ p ActiveResource::Formats[:xml].decode(e.response.body)
31
+ p "Could not save"
32
+ end
@@ -0,0 +1,40 @@
1
+ require "prelude"
2
+
3
+ begin
4
+ gem "francois-rest-client", ">= 1.1.5"
5
+ rescue RuntimeError => e
6
+ p e
7
+ end
8
+
9
+ require "restclient"
10
+ p RestClient.version
11
+ RestClient.log = "stdout"
12
+
13
+ upload = AdGear::Upload.new(:filename => File.dirname(__FILE__) + "/ad_gear.yml")
14
+ if upload.save then
15
+ p "uploaded successfully"
16
+ p upload.id
17
+ else
18
+ p upload.errors
19
+ exit 1
20
+ end
21
+
22
+ templates = AdGear::Template.find(:all)
23
+ template = templates.detect {|template| template.name == "Javascript"}
24
+ formats = AdGear::Format.find(:all)
25
+ campaigns = AdGear::Campaign.find(:all)
26
+
27
+ # Use Javascript, but forget to put the payload
28
+ ad_unit = AdGear::AdUnit.new(:campaign => campaigns.first, :name => "BMW M5", :format => formats.first, :template => template.name)
29
+ ad_unit.ad_unit_files << AdGear::AdUnitFile.new(:name => "image", :upload => upload)
30
+ ad_unit.ad_unit_interactions << AdGear::AdUnitInteraction.new(:name => "something")
31
+ ad_unit.ad_unit_clicks << AdGear::AdUnitClick.new(:name => "clickTAG", :url => "http://somewhere.com/")
32
+ puts "================="*8
33
+ puts ad_unit.to_xml
34
+ puts "================="*8
35
+ assert_raise ActiveResource::BadRequest do
36
+ ad_unit.save
37
+ end
38
+
39
+ ad_unit.ad_unit_variables << AdGear::AdUnitVariable.new(:name => "payload", :value => "// whatever")
40
+ assert ad_unit.save, "What? Now I'm providing the system-required variable, why am I still erroring out?\n" + ad_unit.errors.to_yaml
@@ -0,0 +1,6 @@
1
+ module AdGear
2
+ class AdSpot < AdGear::Base
3
+ ignorable_attributes :embed_code
4
+ belongs_to :format
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module AdGear
2
+ class AdUnit < AdGear::Base
3
+ has_many :ad_unit_files, :ad_unit_clicks, :ad_unit_interactions, :ad_unit_variables
4
+ belongs_to :campaign, :format
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ module AdGear
2
+ class AdUnitClick < AdGear::Base
3
+ end
4
+ end
@@ -0,0 +1,5 @@
1
+ module AdGear
2
+ class AdUnitFile < AdGear::Base
3
+ belongs_to :upload
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module AdGear
2
+ class AdUnitInteraction < AdGear::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module AdGear
2
+ class AdUnitVariable < AdGear::Base
3
+ end
4
+ end
@@ -0,0 +1,144 @@
1
+ module AdGear
2
+ class Base < ActiveResource::Base
3
+ def initialize(params={})
4
+ params = params.inject(Hash.new) do |memo, (name, value)|
5
+ name = name.to_s
6
+ if self.class.belongs_to_associations.include?(name) then
7
+ name = self.class.belongs_to_attribute_name_for(name)
8
+ value = self.class.unpack_belongs_to_association(value)
9
+ end
10
+
11
+ memo[name] = value
12
+ memo
13
+ end
14
+ super(params)
15
+ end
16
+
17
+ # Declares a relationship where we store the ID, but accept and/or return the full object.
18
+ #
19
+ # @example
20
+ # class AdGear::AdSpot < AdGear::Base
21
+ # belongs_to :format
22
+ # end
23
+ #
24
+ # AdGear::AdSpot.new(:format => Format.find(1)).attributes
25
+ # #=> {"format_id" => 1}
26
+ def self.belongs_to(*attributes)
27
+ attributes.flatten.compact.each do |attribute|
28
+ attribute_name = attribute.to_s
29
+ belongs_to_associations << attribute_name
30
+
31
+ belongs_to_attribute_writer_for(attribute_name)
32
+ belongs_to_attribute_reader_for(attribute_name)
33
+ end
34
+ end
35
+
36
+ def self.belongs_to_associations #:nodoc:
37
+ @belongs_to_associations ||= []
38
+ end
39
+
40
+ # Defines a managed sub-collection. Elements managed through a #has_many are
41
+ # ready for use by AttributeFu or ActiveRecord's 2.3 nested_attributes.
42
+ #
43
+ # @example
44
+ # class AdGear::AdUnit < AdGear::Base
45
+ # has_many :ad_unit_files, :ad_unit_clicks
46
+ # has_many :ad_unit_interactions, :ad_unit_variables
47
+ # end
48
+ #
49
+ # AdGear::AdUnit.new(:ad_unit_files => [AdUnitFile.new(...)]).to_xml
50
+ # <ad-unit>
51
+ # <ad-unit-file-attributes>
52
+ # <new>
53
+ # <n0>
54
+ # ...
55
+ # </n0>
56
+ # </new>
57
+ # <!-- If there were "old" records, they'd be here
58
+ # </ad-unit-file-attributes>
59
+ # </ad-unit>
60
+ def self.has_many(*collections)
61
+ collections.flatten.compact.each do |collection|
62
+ collection_name = collection.to_s
63
+
64
+ # Remember what collections we are managing, for use in #to_xml
65
+ has_many_collections << collection_name
66
+
67
+ # Define a getter for the collection that transforms a plain Array into
68
+ # a HasManyArray which knows about new and old records
69
+ define_method(collection_name) do
70
+ arr = @attributes[collection_name]
71
+ return arr if arr.kind_of?(AdGear::HasManyArray)
72
+ @attributes[collection_name] = AdGear::HasManyArray.new(collection_name.to_sym, arr)
73
+ end
74
+ end
75
+ end
76
+
77
+ def self.has_many_collections #:nodoc:
78
+ @has_many_collections ||= []
79
+ end
80
+
81
+ # Defines a list of attributes that should be ignored and not sent back to the server.
82
+ #
83
+ # @example
84
+ # class AdGear::Site < AdGear::Base
85
+ # ignorable_attributes :embed_code
86
+ # end
87
+ #
88
+ # AdGear::Site.find(13).to_xml
89
+ # <site>
90
+ # ...
91
+ # <!-- no embed-code element -->
92
+ # </site>
93
+ def self.ignorable_attributes(*attributes)
94
+ @ignorable_attributes ||= []
95
+ @ignorable_attributes += attributes.flatten.compact.map {|name| name.to_s}
96
+ @ignorable_attributes
97
+ end
98
+
99
+ def to_xml(options={})
100
+ self.class.has_many_collections.each do |name|
101
+ send(name) # convert the @attributes value into a HasManyArray
102
+ end
103
+
104
+ hash = if self.class.ignorable_attributes.empty?
105
+ @attributes
106
+ else
107
+ returning(@attributes.dup) do |hash|
108
+ self.class.ignorable_attributes.each do |attr_name|
109
+ hash.delete(attr_name)
110
+ end
111
+ end
112
+ end
113
+ hash.to_xml({:root => self.class.element_name}.merge(options))
114
+ end
115
+
116
+ # Delegates to #to_xml, as this is the simplest thing that could possibly work
117
+ def encode(options={}) #:nodoc:
118
+ self.to_xml
119
+ end
120
+
121
+ private
122
+
123
+ def self.belongs_to_attribute_writer_for(attribute_name) #:nodoc:
124
+ define_method("#{attribute_name}=") do |value|
125
+ @attributes[self.class.belongs_to_attribute_name_for(attribute_name)] = self.class.unpack_belongs_to_association(value)
126
+ end
127
+ end
128
+
129
+ def self.belongs_to_attribute_reader_for(attribute_name) #:nodoc:
130
+ define_method(attribute_name) do
131
+ id = @attributes[belongs_to_attribute_name_for(attribute_name)]
132
+ id.blank? ? nil : AdGear.const_get(attribute_name.classify).find(id)
133
+ end
134
+ end
135
+
136
+ def self.belongs_to_attribute_name_for(association_name)
137
+ "#{association_name}_id"
138
+ end
139
+
140
+ def self.unpack_belongs_to_association(value)
141
+ value ? value.id : nil
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,4 @@
1
+ module AdGear
2
+ class Campaign < AdGear::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module AdGear
2
+ class Click < AdGear::Base
3
+ end
4
+ end