vj-sdk 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/LICENSE +20 -0
- data/README.markdown +0 -0
- data/README.rdoc +7 -0
- data/Rakefile +70 -0
- data/VERSION.yml +4 -0
- data/lib/core_ext/cgi.rb +12 -0
- data/lib/core_ext/hash.rb +52 -0
- data/lib/core_ext/object.rb +15 -0
- data/lib/core_ext/string.rb +11 -0
- data/lib/sdk_connection_harness.rb +101 -0
- data/lib/videojuicer/asset/audio.rb +13 -0
- data/lib/videojuicer/asset/base.rb +80 -0
- data/lib/videojuicer/asset/flash.rb +8 -0
- data/lib/videojuicer/asset/image.rb +10 -0
- data/lib/videojuicer/asset/text.rb +8 -0
- data/lib/videojuicer/asset/video.rb +22 -0
- data/lib/videojuicer/campaign.rb +19 -0
- data/lib/videojuicer/campaign_policy.rb +116 -0
- data/lib/videojuicer/criterion/base.rb +56 -0
- data/lib/videojuicer/criterion/date_range.rb +15 -0
- data/lib/videojuicer/criterion/geolocation.rb +18 -0
- data/lib/videojuicer/criterion/request.rb +15 -0
- data/lib/videojuicer/criterion/time.rb +15 -0
- data/lib/videojuicer/criterion/week_day.rb +20 -0
- data/lib/videojuicer/oauth/multipart_helper.rb +96 -0
- data/lib/videojuicer/oauth/proxy_factory.rb +18 -0
- data/lib/videojuicer/oauth/request_proxy.rb +280 -0
- data/lib/videojuicer/presentation.rb +38 -0
- data/lib/videojuicer/preset.rb +29 -0
- data/lib/videojuicer/promo/base.rb +72 -0
- data/lib/videojuicer/resource/base.rb +175 -0
- data/lib/videojuicer/resource/collection.rb +36 -0
- data/lib/videojuicer/resource/embeddable.rb +30 -0
- data/lib/videojuicer/resource/errors.rb +17 -0
- data/lib/videojuicer/resource/inferrable.rb +141 -0
- data/lib/videojuicer/resource/property_registry.rb +145 -0
- data/lib/videojuicer/resource/relationships/belongs_to.rb +39 -0
- data/lib/videojuicer/resource/types.rb +28 -0
- data/lib/videojuicer/session.rb +74 -0
- data/lib/videojuicer/shared/configurable.rb +103 -0
- data/lib/videojuicer/shared/exceptions.rb +32 -0
- data/lib/videojuicer/user.rb +43 -0
- data/lib/videojuicer.rb +110 -0
- data/spec/assets/audio_spec.rb +25 -0
- data/spec/assets/flash_spec.rb +24 -0
- data/spec/assets/image_spec.rb +25 -0
- data/spec/assets/text_spec.rb +24 -0
- data/spec/assets/video_spec.rb +25 -0
- data/spec/belongs_to_spec.rb +45 -0
- data/spec/campaign_policy_spec.rb +41 -0
- data/spec/campaign_spec.rb +25 -0
- data/spec/collection_spec.rb +31 -0
- data/spec/criterion/date_range_spec.rb +24 -0
- data/spec/criterion/geolocation_spec.rb +23 -0
- data/spec/criterion/request_spec.rb +23 -0
- data/spec/criterion/time_spec.rb +23 -0
- data/spec/criterion/week_day_spec.rb +23 -0
- data/spec/files/audio.mp3 +0 -0
- data/spec/files/empty_file +0 -0
- data/spec/files/flash.swf +0 -0
- data/spec/files/image.jpg +0 -0
- data/spec/files/text.txt +1 -0
- data/spec/files/video.mov +0 -0
- data/spec/helpers/be_equal_to.rb +26 -0
- data/spec/helpers/spec_fixtures.rb +227 -0
- data/spec/helpers/spec_helper.rb +53 -0
- data/spec/presentation_spec.rb +25 -0
- data/spec/preset_spec.rb +30 -0
- data/spec/promos/audio_spec.rb +23 -0
- data/spec/promos/image_spec.rb +24 -0
- data/spec/promos/text_spec.rb +23 -0
- data/spec/promos/video_spec.rb +23 -0
- data/spec/property_registry_spec.rb +130 -0
- data/spec/request_proxy_spec.rb +90 -0
- data/spec/session_spec.rb +98 -0
- data/spec/shared/asset_spec.rb +39 -0
- data/spec/shared/configurable_spec.rb +75 -0
- data/spec/shared/dependent_spec.rb +40 -0
- data/spec/shared/embeddable_spec.rb +34 -0
- data/spec/shared/model_spec.rb +74 -0
- data/spec/shared/resource_spec.rb +140 -0
- data/spec/spec.opts +3 -0
- data/spec/user_spec.rb +42 -0
- data/spec/videojuicer_spec.rb +122 -0
- data/tasks/vj-core.rb +72 -0
- data/vj-sdk.gemspec +168 -0
- metadata +209 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 danski
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
File without changes
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'merb-core'
|
3
|
+
require 'rake'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = "vj-sdk"
|
9
|
+
gem.summary = "Videojuicer core-sdk"
|
10
|
+
gem.email = "dan@videojuicer.com"
|
11
|
+
gem.homepage = "http://github.com/danski/vj-sdk"
|
12
|
+
gem.authors = ["danski", "thejohnny", "knowtheory", "sixones", "btab"]
|
13
|
+
|
14
|
+
# Declare dependencies
|
15
|
+
gem.add_dependency "json", ">= 1.0"
|
16
|
+
gem.add_dependency "ruby-hmac", ">= 0.3.2"
|
17
|
+
gem.add_dependency "mash", ">= 0.0.3"
|
18
|
+
end
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'spec/rake/spectask'
|
24
|
+
Spec::Rake::SpecTask.new do |t|
|
25
|
+
t.spec_opts = ['--options', 'spec/spec.opts']
|
26
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
27
|
+
end
|
28
|
+
|
29
|
+
namespace :spec do
|
30
|
+
task :sdk do
|
31
|
+
require 'tasks/vj-core'
|
32
|
+
Rake::Task["videojuicer:core:setup"].invoke
|
33
|
+
Rake::Task["spec"].execute
|
34
|
+
Rake::Task["videojuicer:core:cleanup"].invoke
|
35
|
+
end
|
36
|
+
end
|
37
|
+
task :default => :"spec:sdk"
|
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
|
+
require 'rake/rdoctask'
|
53
|
+
Rake::RDocTask.new do |rdoc|
|
54
|
+
if File.exist?('VERSION.yml')
|
55
|
+
config = YAML.load(File.read('VERSION.yml'))
|
56
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
57
|
+
else
|
58
|
+
version = ""
|
59
|
+
end
|
60
|
+
|
61
|
+
rdoc.rdoc_dir = 'rdoc'
|
62
|
+
rdoc.title = "vj-sdk #{version}"
|
63
|
+
rdoc.rdoc_files.include('README*')
|
64
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "provide a console like merb -i or script/console"
|
68
|
+
task :console do
|
69
|
+
exec "irb -r irb/completion -r lib/videojuicer.rb -r lib/sdk_connection_harness.rb"
|
70
|
+
end
|
data/VERSION.yml
ADDED
data/lib/core_ext/cgi.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
# Returns a new hash just like this one, but with all the string keys expressed as symbols.
|
4
|
+
# Also applies to hashes within self.
|
5
|
+
# Based on an implementation within Rails 2.x, thanks Rails!
|
6
|
+
def deep_symbolize
|
7
|
+
target = dup
|
8
|
+
target.inject({}) do |memo, (key, value)|
|
9
|
+
value = value.deep_symbolize if value.is_a?(Hash)
|
10
|
+
memo[(key.to_sym rescue key) || key] = value
|
11
|
+
memo
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns a new hash just like this one, but with all the symbol keys expressed as strings.
|
16
|
+
# Also applies to hashes within self.
|
17
|
+
# Based on an implementation within Rails 2.x, thanks Rails!
|
18
|
+
def deep_stringify
|
19
|
+
target = dup
|
20
|
+
target.inject({}) do |memo, (key, value)|
|
21
|
+
value = value.deep_stringify if value.is_a?(Hash)
|
22
|
+
memo[(key.to_s rescue key) || key] = value
|
23
|
+
memo
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Merges self with another hash, recursively.
|
28
|
+
#
|
29
|
+
# This code was lovingly stolen from some random gem:
|
30
|
+
# http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
|
31
|
+
#
|
32
|
+
# Thanks to whoever made it.
|
33
|
+
def deep_merge(hash)
|
34
|
+
target = dup
|
35
|
+
|
36
|
+
hash.keys.each do |key|
|
37
|
+
if hash[key].is_a? Hash and self[key].is_a? Hash
|
38
|
+
target[key] = target[key].deep_merge(hash[key])
|
39
|
+
next
|
40
|
+
end
|
41
|
+
target[key] = hash[key]
|
42
|
+
end
|
43
|
+
target
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_xml
|
47
|
+
inject("") do |memo, (key, value)|
|
48
|
+
memo << "<#{key}>#{(value.respond_to?(:to_xml))? value.to_xml : value}</#{key}>"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Object
|
2
|
+
|
3
|
+
# Cribbed from DataMapper's Extlib library.
|
4
|
+
def full_const_get(name)
|
5
|
+
list = name.split("::")
|
6
|
+
list.shift if list.first.blank?
|
7
|
+
obj = self
|
8
|
+
list.each do |x|
|
9
|
+
# This is required because const_get tries to look for constants in the
|
10
|
+
# ancestor chain, but we only want constants that are HERE
|
11
|
+
obj = obj.const_defined?(x) ? obj.const_get(x) : obj.const_missing(x)
|
12
|
+
end
|
13
|
+
obj
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
begin
|
2
|
+
require 'extlib'
|
3
|
+
rescue LoadError
|
4
|
+
require 'mash'
|
5
|
+
end
|
6
|
+
require 'yaml'
|
7
|
+
class SDKConnectionHarness
|
8
|
+
class << self
|
9
|
+
|
10
|
+
attr_accessor :server_pid
|
11
|
+
attr_accessor :fixtures
|
12
|
+
|
13
|
+
def core_directory
|
14
|
+
File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "vj-core"))
|
15
|
+
end
|
16
|
+
|
17
|
+
def start!
|
18
|
+
stop! if running?
|
19
|
+
puts "Starting vj-core from #{core_directory}\n"
|
20
|
+
Thread.new do
|
21
|
+
cur_dir = Dir.pwd
|
22
|
+
Dir.chdir(core_directory) do
|
23
|
+
`./bin/merb -d #{app_server} -p #{port} -e test --log ./log/sdk-development.log`
|
24
|
+
end
|
25
|
+
Dir.chdir(cur_dir)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def stop!
|
30
|
+
Thread.new do
|
31
|
+
`killall -9 "merb : worker (port #{port})"`
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def running?
|
36
|
+
uri = URI.parse("http://localhost:#{port}/")
|
37
|
+
req = Net::HTTP::Get.new(uri.path)
|
38
|
+
|
39
|
+
begin
|
40
|
+
resp = Net::HTTP.start(uri.host, uri.port) do |http|
|
41
|
+
http.request(req)
|
42
|
+
end
|
43
|
+
return true
|
44
|
+
rescue Exception => e
|
45
|
+
# Connection refused means the daemon isn't running
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def load_fixtures
|
51
|
+
Dir.chdir(core_directory) do
|
52
|
+
out = `./bin/rake videojuicer:sdk:setup MERB_ENV=test`
|
53
|
+
out = out.match(/!!!([^!]+)!!!/m)
|
54
|
+
self.fixtures = out[1]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def write_fixtures
|
59
|
+
f = File.open(File.join(File.dirname(__FILE__), "..", "core-fixtures.yml"), "w+")
|
60
|
+
f.rewind
|
61
|
+
f.write(self.fixtures)
|
62
|
+
f.close
|
63
|
+
end
|
64
|
+
|
65
|
+
def app_server
|
66
|
+
begin
|
67
|
+
require 'thin'
|
68
|
+
adapter = 'thin'
|
69
|
+
rescue LoadError
|
70
|
+
adapter = 'mongrel'
|
71
|
+
end
|
72
|
+
return "--adapter #{adapter}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def port
|
76
|
+
6666
|
77
|
+
end
|
78
|
+
|
79
|
+
def connect(overrides={})
|
80
|
+
fixtures = Mash.new(YAML.load(load_fixtures)).merge(overrides)
|
81
|
+
configure_test_settings(fixtures)
|
82
|
+
Videojuicer.enter_scope :seed_name => fixtures[:seed][:name],
|
83
|
+
:consumer_key=>fixtures["write-master"][:consumer][:consumer_key],
|
84
|
+
:consumer_secret=>fixtures["write-master"][:consumer][:consumer_secret],
|
85
|
+
:token=>fixtures["write-master"][:authorized_token][:oauth_token],
|
86
|
+
:token_secret=>fixtures["write-master"][:authorized_token][:oauth_token_secret]
|
87
|
+
end
|
88
|
+
|
89
|
+
def configure_test_settings(overrides={})
|
90
|
+
Videojuicer.configure!({
|
91
|
+
:consumer_key => nil,
|
92
|
+
:consumer_secret => nil,
|
93
|
+
:api_version => 1,
|
94
|
+
:protocol => "http",
|
95
|
+
:host => "localhost",
|
96
|
+
:port => port
|
97
|
+
}.merge(overrides))
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "base")
|
2
|
+
|
3
|
+
module Videojuicer
|
4
|
+
module Asset
|
5
|
+
class Audio < Base
|
6
|
+
property :bit_rate, Integer, :writer => :private # bits per second
|
7
|
+
property :channels, Integer, :writer => :private
|
8
|
+
property :duration, Integer, :writer => :private # milliseconds
|
9
|
+
property :format, String, :writer => :private
|
10
|
+
property :sample_rate, Integer, :writer => :private # hertz
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Videojuicer
|
2
|
+
module Asset
|
3
|
+
class Base
|
4
|
+
|
5
|
+
def self.inherited(base)
|
6
|
+
base.send(:include, Videojuicer::Resource)
|
7
|
+
base.send(:extend, Videojuicer::Asset::Base::ClassMethods)
|
8
|
+
base.send(:include, Videojuicer::Asset::Base::InstanceMethods)
|
9
|
+
|
10
|
+
# - heritage
|
11
|
+
base.property :derived_internally, Videojuicer::Resource::Types::Boolean, :writer => :private
|
12
|
+
base.property :original_asset_id, Integer, :writer => :private
|
13
|
+
base.property :original_asset_type, String, :writer => :private
|
14
|
+
base.property :preset_id, Integer, :writer => :private
|
15
|
+
base.property :user_id, Integer, :writer => :private
|
16
|
+
|
17
|
+
# - transformation
|
18
|
+
base.property :source_space_window, String, :writer => :private
|
19
|
+
base.property :source_time_window, String, :writer => :private
|
20
|
+
|
21
|
+
# - generic file handling
|
22
|
+
base.property :file, File
|
23
|
+
base.property :file_name, String
|
24
|
+
base.property :file_size, Integer, :writer => :private # bytes
|
25
|
+
|
26
|
+
# - common metadata
|
27
|
+
base.property :licensed_at, Date
|
28
|
+
base.property :licensed_by, String
|
29
|
+
base.property :licensed_under, String
|
30
|
+
base.property :published_at, Date
|
31
|
+
|
32
|
+
# - access control / workflow
|
33
|
+
base.property :url, String, :writer => :private
|
34
|
+
base.property :state, String, :writer => :private
|
35
|
+
base.property :state_changed_at, DateTime, :writer => :private
|
36
|
+
base.property :state_changed_url, String
|
37
|
+
base.property :created_at, DateTime
|
38
|
+
base.property :updated_at, DateTime
|
39
|
+
end
|
40
|
+
|
41
|
+
module ClassMethods
|
42
|
+
def singular_name
|
43
|
+
"asset"
|
44
|
+
end
|
45
|
+
|
46
|
+
def base_path(options={})
|
47
|
+
"/assets/#{self.to_s.downcase.split("::").last}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module InstanceMethods
|
52
|
+
def derive(preset)
|
53
|
+
response = proxy_for(config).post(resource_path, :preset_id => preset.id)
|
54
|
+
self.class.new(JSON.parse(response.body))
|
55
|
+
end
|
56
|
+
|
57
|
+
def file
|
58
|
+
raise "use the value of #{self.class}#url to download a copy of the asset"
|
59
|
+
end
|
60
|
+
|
61
|
+
def returnable_attributes
|
62
|
+
attrs = super
|
63
|
+
attrs.delete(:file) unless new_record?
|
64
|
+
attrs
|
65
|
+
end
|
66
|
+
|
67
|
+
def set_derived(from_asset, preset)
|
68
|
+
params = {
|
69
|
+
:original_asset_type => from_asset.class.to_s.split("::").last,
|
70
|
+
:original_asset_id => from_asset.id,
|
71
|
+
:preset_id => preset.id
|
72
|
+
}
|
73
|
+
response = proxy_for(config).post(resource_path(:set_derived), params)
|
74
|
+
self.attributes = JSON.parse(response.body)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "base")
|
2
|
+
|
3
|
+
module Videojuicer
|
4
|
+
module Asset
|
5
|
+
class Video < Base
|
6
|
+
property :bit_rate, Integer, :writer => :private # bits per second
|
7
|
+
property :duration, Integer, :writer => :private # milliseconds
|
8
|
+
|
9
|
+
property :audio_bit_rate, Integer, :writer => :private # bits per second
|
10
|
+
property :audio_channels, Integer, :writer => :private
|
11
|
+
property :audio_format, String, :writer => :private
|
12
|
+
property :audio_sample_rate, Integer, :writer => :private # hertz
|
13
|
+
|
14
|
+
property :video_bit_rate, Integer, :writer => :private # bits per second
|
15
|
+
property :video_format, String, :writer => :private
|
16
|
+
property :video_frame_rate, Float, :writer => :private # frames per second
|
17
|
+
|
18
|
+
property :width, Integer, :writer => :private # pixels
|
19
|
+
property :height, Integer, :writer => :private # pixels
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Videojuicer
|
2
|
+
class Campaign
|
3
|
+
include Videojuicer::Resource
|
4
|
+
include Videojuicer::Exceptions
|
5
|
+
|
6
|
+
property :name, String
|
7
|
+
property :user_id, Integer
|
8
|
+
property :created_at, DateTime
|
9
|
+
property :updated_at, DateTime
|
10
|
+
belongs_to :user, :class=>Videojuicer::User
|
11
|
+
|
12
|
+
attr_accessor :campaign_policies
|
13
|
+
def campaign_policies=(arg)
|
14
|
+
# Loop over and make objects or something
|
15
|
+
@campaign_policies=(arg)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Videojuicer
|
2
|
+
class Campaign
|
3
|
+
class CampaignPolicy
|
4
|
+
include Videojuicer::Resource
|
5
|
+
|
6
|
+
# Resource should note that this is a class within a class
|
7
|
+
# Should treat parent class as parent resource
|
8
|
+
|
9
|
+
property :presentation_id, Integer
|
10
|
+
property :campaign_id, Integer
|
11
|
+
property :created_at, DateTime
|
12
|
+
property :updated_at, DateTime
|
13
|
+
|
14
|
+
belongs_to :campaign
|
15
|
+
|
16
|
+
attr_accessor :criteria
|
17
|
+
def criteria=(object_hash)
|
18
|
+
# TODO instantiate criteria in a useful object of some sort
|
19
|
+
|
20
|
+
# Fail unless arg is an array
|
21
|
+
# Loop over array do |mem|
|
22
|
+
# if mem is a hash
|
23
|
+
# instantiate as a criterion
|
24
|
+
|
25
|
+
|
26
|
+
# if criterion object already on this policy
|
27
|
+
# leave be
|
28
|
+
# else
|
29
|
+
# add_criteria(mem)
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
|
33
|
+
# what you want to be able to do is:
|
34
|
+
# policy.criteria.include?(some_criterion)
|
35
|
+
@criteria = {}
|
36
|
+
object_hash.map do |type_sym, criteria|
|
37
|
+
@criteria[type_sym.to_sym] =
|
38
|
+
criteria.map do |criterion|
|
39
|
+
Videojuicer::Criterion.model_map[type_sym.to_sym].new(criterion) #rescue raise("No criteria class found for #{type_sym} in #{Videojuicer::Criterion.model_map.inspect}")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def criteria
|
45
|
+
@criteria.values.flatten
|
46
|
+
end
|
47
|
+
|
48
|
+
%w(date_criteria geolocation_criteria request_criteria time_criteria week_day_criteria).each do |key|
|
49
|
+
class_eval <<-DEF
|
50
|
+
def #{key}
|
51
|
+
@criteria[:#{key}]
|
52
|
+
end
|
53
|
+
DEF
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def add_criteria(*criteria)
|
58
|
+
responses = criteria.map do |criterion|
|
59
|
+
proxy_for(config).post("#{path_for_dependents}#{criterion.class.base_path}", {:criterion => criterion.attributes})
|
60
|
+
end
|
61
|
+
self.reload
|
62
|
+
responses
|
63
|
+
end
|
64
|
+
|
65
|
+
def remove_criteria(*criteria)
|
66
|
+
responses = criteria.map do |criterion|
|
67
|
+
proxy_for(config).delete("#{path_for_dependents}#{criterion.class.base_path}", {:criterion => criterion.attributes})
|
68
|
+
end
|
69
|
+
self.reload
|
70
|
+
responses
|
71
|
+
end
|
72
|
+
|
73
|
+
def promos=(object_hash={})
|
74
|
+
@promos = {}
|
75
|
+
object_hash.map do |type_sym, promos|
|
76
|
+
@promos[type_sym.to_sym] =
|
77
|
+
promos.map do |promo|
|
78
|
+
Videojuicer::Promo.model_map[type_sym.to_sym].new(promo)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def promos
|
84
|
+
@promos.values.flatten
|
85
|
+
end
|
86
|
+
|
87
|
+
%w(audio images texts videos).each do |key|
|
88
|
+
class_eval <<-DEF
|
89
|
+
def #{key}
|
90
|
+
@promos[:#{key}]
|
91
|
+
end
|
92
|
+
DEF
|
93
|
+
end
|
94
|
+
|
95
|
+
def add_promo(*promos)
|
96
|
+
responses = promos.map do |promo|
|
97
|
+
proxy_for(config).post("#{path_for_dependents}#{promo.class.base_path}", {:promo => promo.attributes})
|
98
|
+
end
|
99
|
+
self.reload
|
100
|
+
responses
|
101
|
+
end
|
102
|
+
|
103
|
+
def remove_promo(*promos)
|
104
|
+
responses = promos.map do |promo|
|
105
|
+
proxy_for(config).delete("#{path_for_dependents}#{promo.class.base_path}", {:promo => promo.attributes})
|
106
|
+
end
|
107
|
+
self.reload
|
108
|
+
responses
|
109
|
+
end
|
110
|
+
|
111
|
+
def path_for_dependents
|
112
|
+
self.class.compile_route(self.class.nesting_route,{:campaign_policy_id => self.id, :campaign_id => self.campaign_id})
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Videojuicer
|
2
|
+
module Criterion
|
3
|
+
def self.model_map
|
4
|
+
{ :date_criteria => Videojuicer::Criterion::DateRange,
|
5
|
+
:geolocation_criteria => Videojuicer::Criterion::Geolocation,
|
6
|
+
:request_criteria => Videojuicer::Criterion::Request,
|
7
|
+
:time_criteria => Videojuicer::Criterion::Time,
|
8
|
+
:week_day_criteria => Videojuicer::Criterion::WeekDay
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
class Base
|
13
|
+
def self.inherited(base)
|
14
|
+
base.send(:include, Videojuicer::Resource)
|
15
|
+
base.send(:extend, Videojuicer::Criterion::Base::ClassMethods)
|
16
|
+
base.send(:include, Videojuicer::Criterion::Base::InstanceMethods)
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
def singular_name
|
21
|
+
"criterion"
|
22
|
+
end
|
23
|
+
|
24
|
+
def base_path(options={})
|
25
|
+
"/criteria/#{self.to_s.split("::").last.snake_case}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def get(*args); raise NoMethodError; end
|
29
|
+
def all(*args); raise NoMethodError; end
|
30
|
+
def first(*args); raise NoMethodError; end
|
31
|
+
end
|
32
|
+
|
33
|
+
module InstanceMethods
|
34
|
+
def save(*args); raise NoMethodError; end
|
35
|
+
def destroy(*args); raise NoMethodError; end
|
36
|
+
def ==(other); self.attributes == other.attributes; end
|
37
|
+
def eql?(other); self.attributes.eql?(other.attributes) end
|
38
|
+
def matcher_attributes; end
|
39
|
+
|
40
|
+
def matcher_attributes
|
41
|
+
result = {}
|
42
|
+
self.matcher_keys.each do |key|
|
43
|
+
result[key] = self.send(key)
|
44
|
+
end
|
45
|
+
return result
|
46
|
+
end
|
47
|
+
|
48
|
+
def matcher_keys
|
49
|
+
raise NoMethodError, "Matcher Attributes needs to be implemented for #{self.class}";
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "base")
|
2
|
+
|
3
|
+
module Videojuicer
|
4
|
+
module Criterion
|
5
|
+
class Geolocation < Base
|
6
|
+
|
7
|
+
property :country, String
|
8
|
+
property :region, String
|
9
|
+
property :city, String
|
10
|
+
property :exclude, Boolean
|
11
|
+
|
12
|
+
def matcher_keys
|
13
|
+
[:country, :region, :city, :exclude]
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|