vj-sdk 0.2.1
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.
- 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
|