vj-sdk 0.2.1 → 0.4.0

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 CHANGED
@@ -1,4 +1,5 @@
1
1
  log/*
2
2
  core-fixtures.yml
3
3
  pkg/*
4
- .DS_Store
4
+ .DS_Store
5
+ *.tmproj
data/README.markdown CHANGED
@@ -0,0 +1,105 @@
1
+ Videojuicer Core SDK
2
+ ====================
3
+
4
+ The Videojuicer Core SDK is a library for conveniently working with the [Videojuicer](http://videojuicer.com) Core API service.
5
+
6
+ Drop-in Rails/Merb compatibility
7
+ --------------------------------
8
+
9
+ The models in this SDK present a familiar ORM-style interface onto all the objects in the remote API. Users of ActiveRecord or DataMapper should feel right at home:
10
+
11
+ presentation = Videojuicer::Presentation.new(:title=>"Hello World")
12
+ presentation.valid? #=> true
13
+ presentation.save #=> true
14
+
15
+ Validations, creation, updates and deleting records all behave as you'd expect from these libraries.
16
+
17
+ Getting started
18
+ ===============
19
+
20
+ Getting started is easy. First off, you'll need to be a Videojuicer customer with access to a Videojuicer Seed. You'll also need to [register for a consumer key](http://api.videojuicer.com/oauth/consumers).
21
+
22
+ The Core API uses [OAuth](http://oauth.net) as a security and authorisation mechanism, and the SDK acts as an OAuth client.
23
+
24
+ To get started you will need:
25
+
26
+ * Your seed name
27
+ * Your username and password
28
+ * Your consumer key
29
+ * Your consumer secret
30
+
31
+ Authorizing the SDK to work with your account
32
+ ---------------------------------------------
33
+
34
+ require 'rubygems'
35
+ require 'videojuicer'
36
+
37
+ #
38
+ @seed_name = your_seed_name
39
+ @consumer_key = your_consumer_key
40
+ @consumer_secret = your_consumer_secret
41
+ #
42
+ # ----------------------
43
+ # OAuth Stage 1
44
+ # ----------------------
45
+ #
46
+ # Create a VJ Session
47
+ @api_session = Videojuicer::Session.new(
48
+ :seed_name=>@seed_name,
49
+ :consumer_key=>@consumer_key,
50
+ :consumer_secret=>@consumer_secret
51
+ )
52
+ # Get the OAuth Request token
53
+ @request_token = @api_session.get_request_token
54
+ # Get the authorization URL for your token
55
+ @auth_url = @api_session.authorize_url(
56
+ "oauth_token" => @request_token["oauth_token"],
57
+ "oauth_token_secret" => @request_token["oauth_token_secret"],
58
+ "oauth_callback" => a_url_where_to_which_you_want_the_user_directed_after_authorization
59
+ )
60
+ #
61
+ # ----------------------
62
+ # OAuth Stage 2
63
+ # Direct the user to the @auth_url - they will be asked for their username and password.
64
+ # ----------------------
65
+ #
66
+ # ----------------------
67
+ # OAuth Stage 3
68
+ # Exchange the Request token for an Access token
69
+ # ----------------------
70
+ #
71
+ @access_token = @api_session.exchange_request_token(
72
+ "oauth_token" => @request_token["oauth_token"],
73
+ "oauth_token_secret" => @request_token["oauth_token_secret"]
74
+ )
75
+ #
76
+ # ----------------------
77
+ # Authorization complete
78
+ # Store the access token for later use
79
+ # ----------------------
80
+
81
+ Working with the authorized access token
82
+ ----------------------------------------
83
+
84
+ @api_session = Videojuicer::Session.new(
85
+ :seed_name=>@seed_name,
86
+ :consumer_key=>@consumer_key,
87
+ :consumer_secret=>@consumer_secret,
88
+ :token=>@access_token["oauth_token"],
89
+ :token_secret=>@access_token["oauth_token_secret"]
90
+ )
91
+ # The session is now properly configured and authorized. You can just work within it like so:
92
+ @api_session.scope do
93
+ Videojuicer::User.all #=> [<Videojuicer::User ................. >]
94
+ end
95
+
96
+ You may also do one-off setup of the SDK as follows:
97
+
98
+ Videojuicer.configure!(
99
+ :seed_name=>@seed_name,
100
+ :consumer_key=>@consumer_key,
101
+ :consumer_secret=>@consumer_secret,
102
+ :token=>@access_token["oauth_token"],
103
+ :token_secret=>@access_token["oauth_token_secret"]
104
+ )
105
+ Videojuicer::User.all #=> [<Videojuicer::User ................. >]
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
+ :minor: 4
3
+ :patch: 0
2
4
  :major: 0
3
- :minor: 2
4
- :patch: 1
data/lib/videojuicer.rb CHANGED
@@ -29,11 +29,13 @@ require 'videojuicer/resource/property_registry'
29
29
  require 'videojuicer/resource/base'
30
30
  require 'videojuicer/session'
31
31
  # Frontend models
32
+ require 'videojuicer/seed'
32
33
  require 'videojuicer/user'
33
34
  require 'videojuicer/campaign'
34
35
  require 'videojuicer/campaign_policy'
35
36
  require 'videojuicer/presentation'
36
37
  require 'videojuicer/asset/audio'
38
+ require 'videojuicer/asset/document'
37
39
  require 'videojuicer/asset/flash'
38
40
  require 'videojuicer/asset/image'
39
41
  require 'videojuicer/asset/text'
@@ -31,6 +31,7 @@ module Videojuicer
31
31
 
32
32
  # - access control / workflow
33
33
  base.property :url, String, :writer => :private
34
+ base.property :http_url, String, :writer => :private
34
35
  base.property :state, String, :writer => :private
35
36
  base.property :state_changed_at, DateTime, :writer => :private
36
37
  base.property :state_changed_url, String
@@ -0,0 +1,8 @@
1
+ require File.join(File.dirname(__FILE__), "base")
2
+
3
+ module Videojuicer
4
+ module Asset
5
+ class Document < Base
6
+ end
7
+ end
8
+ end
@@ -191,7 +191,7 @@ module Videojuicer
191
191
  # with the proxy configuration to produce a set of parameters that will be accepted
192
192
  # by the OAuth provider.
193
193
  def authify_params(method, path, params)
194
- params = {
194
+ defaults = {
195
195
  :oauth_consumer_key=>consumer_key,
196
196
  :oauth_token=>token,
197
197
  :api_version=>api_version,
@@ -200,8 +200,9 @@ module Videojuicer
200
200
  :oauth_signature_method=>"HMAC-SHA1",
201
201
  :seed_name=>seed_name,
202
202
  :user_id=>user_id
203
- }.merge(params)
204
- params.delete_if {|k,v| (!v) or (v.to_s.empty?) }
203
+ }
204
+ defaults.delete_if {|k,v| (!v) or (v.to_s.empty?) }
205
+ params = defaults.merge(params)
205
206
  params[:oauth_signature] = signature(method, path, params)
206
207
  return params
207
208
  end
@@ -48,7 +48,7 @@ module Videojuicer
48
48
  end
49
49
 
50
50
  # Parse and handle response
51
- return validate_response(response)
51
+ return validate_committed_response(response)
52
52
  end
53
53
 
54
54
  # Attempts to validate this object with the remote service. Returns TRUE on success,
@@ -74,6 +74,13 @@ module Videojuicer
74
74
  def errors; @errors ||= Videojuicer::Resource::Errors.new({}); end
75
75
  def errors_on(key); errors.on(key); end
76
76
 
77
+ # Takes a *change-making* response from the API and cleans the dirty attributes if it was successful.
78
+ def validate_committed_response(response)
79
+ result = validate_response(response)
80
+ clean_dirty_attributes! if result
81
+ return result
82
+ end
83
+
77
84
  # Takes a response from the API and performs the appropriate actions.
78
85
  def validate_response(response)
79
86
  body = response.body
@@ -104,7 +111,7 @@ module Videojuicer
104
111
  def reload
105
112
  raise NoResource, "Cannot load remote attributes for new records" if new_record?
106
113
  response = proxy_for(config).get(resource_path(nil, :nested=>false))
107
- return validate_response(response)
114
+ return validate_committed_response(response)
108
115
  end
109
116
 
110
117
  # Attempts to delete this record. Will raise an exception if the record is new
@@ -134,6 +141,7 @@ module Videojuicer
134
141
  # Instantiate objects
135
142
  items = items.collect do |attrs|
136
143
  o = new; o.attributes = attrs
144
+ o.clean_dirty_attributes!
137
145
  o
138
146
  end
139
147
  return (op.is_a?(Hash))? Videojuicer::Resource::Collection.new(items, op["count"], op["offset"], op["limit"]) : items
@@ -31,10 +31,9 @@ module Videojuicer
31
31
  v = "@attributes"
32
32
  subclass.instance_variable_set(v, instance_variable_get(v))
33
33
  end
34
-
35
34
 
36
35
  def initialize(attrs={})
37
- self.attributes = default_attributes
36
+ set_default_attributes
38
37
  self.attributes = attrs
39
38
  end
40
39
 
@@ -50,14 +49,63 @@ module Videojuicer
50
49
  end
51
50
  end
52
51
 
52
+ # Sets the attributes to their default values, marking only those values with defaults as being dirty.
53
+ def set_default_attributes
54
+ self.attributes = default_attributes
55
+ self.attributes.each do |key, value|
56
+ # Scrub the attributes if there's no value
57
+ attr_clean!(key) unless value
58
+ end
59
+ end
60
+
53
61
  def default_attributes
54
62
  d = {}
55
63
  self.class.attributes.each do |key, props|
56
- d[key] = props[:default] || nil
64
+ d[key] = props[:default] || nil
57
65
  end
58
66
  return d
59
67
  end
60
68
 
69
+ # Returns the hash of currently-dirty attributes complete with values
70
+ def dirty_attributes
71
+ o = {}
72
+ @dirty_attribute_keys ||= []
73
+ @dirty_attribute_keys.each do |key|
74
+ o[key] = attr_get(key)
75
+ end
76
+ o
77
+ end
78
+
79
+ # Clears the array of dirty attribute keys
80
+ def clean_dirty_attributes!
81
+ @dirty_attribute_keys = []
82
+ end
83
+
84
+ # Returns an array of keys for attributes that are currently dirty
85
+ def dirty_attribute_keys
86
+ @dirty_attribute_keys ||= []
87
+ @dirty_attribute_keys
88
+ end
89
+
90
+ # Returns true if the specified attribute is currently dirty
91
+ def attr_dirty?(key)
92
+ @dirty_attribute_keys ||= []
93
+ @dirty_attribute_keys.include?(key.to_sym)
94
+ end
95
+
96
+ # Mark the specified attribute as dirty.
97
+ def attr_dirty!(key)
98
+ @dirty_attribute_keys ||= []
99
+ @dirty_attribute_keys << key.to_sym
100
+ @dirty_attribute_keys.uniq!
101
+ end
102
+
103
+ # Mark the specified attribute as no longer being dirty.
104
+ def attr_clean!(key)
105
+ @dirty_attribute_keys ||= []
106
+ @dirty_attribute_keys.delete_if {|k| k == key.to_sym }
107
+ end
108
+
61
109
  def attr_get(key)
62
110
  key = key.to_sym
63
111
  attributes[key]
@@ -65,6 +113,7 @@ module Videojuicer
65
113
 
66
114
  def attr_set(key, value)
67
115
  key = key.to_sym
116
+ attr_dirty!(key)
68
117
  attributes[key] = coerce_value(key, value)
69
118
  end
70
119
 
@@ -103,7 +152,7 @@ module Videojuicer
103
152
  # Returns a hash of the attributes for this object, minus the
104
153
  # private attributes that should not be included in the response.
105
154
  def returnable_attributes
106
- attrs = attributes.dup
155
+ attrs = dirty_attributes.dup
107
156
  self.class.attributes.select {|name, props| props[:writer] != :public}.each do |name, props|
108
157
  attrs.delete name
109
158
  end
@@ -0,0 +1,19 @@
1
+ module Videojuicer
2
+ class Seed
3
+ include Videojuicer::Resource
4
+ include Videojuicer::Exceptions
5
+
6
+ property :name, String
7
+ property :provider_name, String
8
+ property :provider_url, String
9
+ property :google_analytics_id, String
10
+
11
+ # Returns the currently-configured seed
12
+ def self.current
13
+ proxy = Videojuicer::OAuth::RequestProxy.new
14
+ jobj = JSON.parse(proxy.get("/seeds/current.json").body)
15
+ new(jobj)
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require File.join(File.dirname(__FILE__), "..", "helpers", "spec_helper")
2
+
3
+ describe Videojuicer::Asset::Document do
4
+
5
+ before(:all) do
6
+ @klass = Videojuicer::Asset::Document
7
+ configure_test_settings
8
+ end
9
+
10
+ describe "instantiation" do
11
+ it_should_behave_like "a configurable"
12
+ end
13
+
14
+ describe "general interface:" do
15
+ before(:all) do
16
+ @singular_name = "asset"
17
+ @plural_name = "assets/document"
18
+ end
19
+
20
+ it_should_behave_like "a RESTFUL resource model"
21
+ end
22
+
23
+ it_should_behave_like "an asset"
24
+ end
@@ -0,0 +1,311 @@
1
+ /*
2
+ Videojuicer Management Panel Core JS
3
+ This file contains the standard presentational and interactive JS for the Management Panel.
4
+
5
+ Dependencies: jQuery 1.3, jQuery Easing
6
+ */
7
+
8
+ // Document Boot
9
+ // ==============================================================================
10
+
11
+ $(document).ready(function() {
12
+
13
+ // Cosmetic - Add .has-js to the <body> so that Markup can be styled for when the user has or doesnt have JS
14
+ $("body").addClass("has-js");
15
+
16
+ // Cosmetic - Add the correct wrapper to links that require it.
17
+ $(".btn, nav > a").wrapInner("<span></span>").append("<i></i>");
18
+
19
+ // Cosmetic - Move the tooltip class to the parent element for wrapping DL items.
20
+ $(".tool-tip-container").closest("dd").addClass("has-msg");
21
+ // Cosmetic - If the fields within a DT/DD pair are in an error state, pass the error class
22
+ // around to stabilise the display.
23
+ $(".error:input").closest("dd").addClass("has-error");
24
+
25
+ // Interactivity - Allow tooltip icons to toggle the display of the element they reference.
26
+ $(".tool-tip-icon").click(function() {
27
+ $this = $(this);
28
+ t = $($this.attr("href"));
29
+
30
+ if($this.hasClass('active')) {
31
+ t.fadeOut('fast');
32
+ $this.removeClass('active');
33
+ } else {
34
+ remove_all_tooltips();
35
+ $this.addClass('active');
36
+ t.fadeIn('fast');
37
+ };
38
+ return false;
39
+ })
40
+
41
+ // Cosmetic - add wrapper elements to help boxes that don't have them.
42
+ $("div.help:not(div:has(.help-content))").wrapInner("<div class=\"help-content\"></div>");
43
+ $("div.help:not(div:has(.help-top))").prepend('<span class="help-top"><span class="help-R"></span></span>');
44
+ $("div.help:not(div:has(.help-bottom))").append('<span class="help-bottom"><span class="help-R"></span></span>');
45
+
46
+ // Interactivity - Register selection event on all select-all checkboxes. These
47
+ // checkboxes will toggle all other checkboxes within the same fieldset as themselves.
48
+ $("input.select-all").bind("change", function() {
49
+ $this = $(this);
50
+ checked = $this.is(":checked");
51
+ $("input", $this.closest("fieldset")).each(function() {
52
+ this.checked = checked;
53
+ });
54
+ });
55
+
56
+ // Interactivity - Confirmation dialogues get appended to destructive links.
57
+ $(".dangerous").click(function(event) {
58
+ code = (new String(Math.random())).substr(2,4);
59
+ msg = "This action cannot be undone. Please enter the code "+code+" to confirm your decision, or press 'Cancel' if you do not wish to continue.";
60
+ return (prompt(msg)==code);
61
+ });
62
+ $(".destructive").click(function(event) {
63
+ msg = $(this).attr("data-confirmation-msg") || "This action cannot be undone. Please confirm that you wish to continue.";
64
+ return confirm(msg);
65
+ });
66
+
67
+ // Interactivity - The markup contains nested lists that act like dropdown menus.
68
+ // This makes them work good. The interactivity causes the click on the root
69
+ // link to pop the menu open, and a click on either the button or one of the nested
70
+ // links to close it again.
71
+ $(".btn-select-parent a").bind("click", function() {
72
+ $this = $(this);
73
+ $this.closest(".btn-select-parent").toggleClass("open");
74
+ $this.closest(".btn-select-parent").toggleClass("closed");
75
+ return false;
76
+ })
77
+
78
+ // Interactivity - Make active all nav-tab arrays.
79
+ $("ul.nav-tabbed a").make_nav_tab();
80
+ $("ul.nav-tabbed a:first").activate_nav_tab();
81
+
82
+
83
+ // Interactivity - Hide All Tooltips whenever an input, textarea or select focuses
84
+ $('textarea, input, select').focus(function() {
85
+ remove_all_tooltips();
86
+ });
87
+
88
+ // Interactivity - Expandable fieldsets
89
+ $('fieldset.expandable legend a').click(function() {
90
+ $a = $(this);
91
+ $a.closest("fieldset").toggleClass("open");
92
+ $a.closest("fieldset").toggleClass("closed");
93
+ });
94
+
95
+ // Interactivity - Any link with .dismisser as the class will hide the element it
96
+ // references in the href attribute.
97
+ $("a.dismisser").click(function() {
98
+ $($(this).attr("href")).fadeOut("slow");
99
+ return false;
100
+ });
101
+
102
+ // Make necessary corrections for IE
103
+ // Buttons need inline syles applied to the span and i elements to make them appear correctly
104
+ if($.browser.msie) {
105
+ style_buttons_for_ie();
106
+
107
+ } else {
108
+ // Do Nothing!
109
+ }
110
+ });
111
+
112
+ // Tiny Extensions to jQuery (major extensions should get their own files)
113
+ // ==============================================================================
114
+
115
+ // Used on a link within a nav-tab controller bar to give it all the right interactivity.
116
+ $.fn.make_nav_tab = function(options) {
117
+ return this.each(function() { $link = $(this);
118
+ $link.click(function() {
119
+ $(this).activate_nav_tab();
120
+ return false;
121
+ })
122
+ });
123
+ }
124
+ // Used on a tab bar nav-tab to activate it and display the content it relates to.
125
+ $.fn.activate_nav_tab = function(options) {
126
+ return this.each(function() { $link = $(this); $ul = $link.closest("ul"); $li = $link.closest("li");
127
+ // Mark all containing LIs in the controller as inactive
128
+ $("li", $ul).removeClass("active");
129
+ // Mark this link's containing LI as active
130
+ $li.addClass("active");
131
+ // Hide all content blocks owned by this controller block
132
+ $(".tabbed-content[data-group="+$ul.attr("data-controls")+"]").collapse();
133
+ // Show the specific content block we're activating
134
+ $($link.attr("href")).expand();
135
+ });
136
+ }
137
+
138
+ // Animate the closing of all matched elements.
139
+ // Used to keep animation settings consistent.
140
+ $.fn.collapse = function(options) {
141
+ this.slideUp(250, 'easeOutQuad');
142
+ }
143
+ // Animate the opening of all matched elements.
144
+ // Used to keep animation settings consistent.
145
+ $.fn.expand = function(options) {
146
+ this.slideDown(250, 'easeOutQuad');
147
+ }
148
+
149
+
150
+ // Tabbed Navigation
151
+ // FOR: Switching between different tabs on the page
152
+ // ==============================================================================
153
+
154
+ function TabbedNavigation(num_tabs, tab_handle, content_handle, classname, default_tab) {
155
+
156
+ this.num_tabs = num_tabs; // -> number of tabs on page
157
+ this.tab_handle = tab_handle; // -> name of tab IDs minus number (e.g. "tab1" would be "tab")
158
+ this.content_handle = content_handle; // -> name of content box IDs minus number (e.g. "content1" would be "content")
159
+ this.classname = classname; // -> css class to be applied to open tab
160
+ this.default_tab = default_tab; // -> which tab is open by default
161
+
162
+ TabbedNavigation.prototype.hide_all_content_boxes_except = function(num, fade) {
163
+ var css = { display:'none'}
164
+ for(i = 1; i <= this.num_tabs; i++) {
165
+ $(this.content_handle + i).css(css);
166
+ }
167
+ if(!fade) {
168
+ var css = { display:'block'}
169
+ $(this.content_handle + num).css(css);
170
+ } else {
171
+ $(this.content_handle + num).fadeIn(750);
172
+ }
173
+ }
174
+
175
+ TabbedNavigation.prototype.set_current_tab_to = function(num) {
176
+ for(i = 1; i <= this.num_tabs; i++) {
177
+ $(this.tab_handle + i).removeClass(this.classname);
178
+ }
179
+ $(this.tab_handle + num).addClass(this.classname);
180
+ }
181
+
182
+ TabbedNavigation.prototype.set_tab_to = function(num) {
183
+ this.set_current_tab_to(num);
184
+ this.hide_all_content_boxes_except(num);
185
+ }
186
+
187
+ this.set_tab_to(this.default_tab);
188
+ }
189
+
190
+ // Tooltips
191
+ // FOR: Showing & Hiding the relevant tooltips when the user clicks tooltip icon
192
+
193
+ function remove_all_tooltips() {
194
+ $('.tool-tip-msg').fadeOut('fast');
195
+ $('.tool-tip-icon').removeClass('active');
196
+ };
197
+
198
+ // Expandable Fieldset
199
+ // FOR: Allowing the user to expand or contract a fieldset
200
+ function close_expandable_fieldsets() {
201
+ $('fieldset.expandable').addClass('closed');
202
+ };
203
+
204
+ function trigger_fieldset(id) {
205
+ if(id) {
206
+ var fieldset = id + '-parent'
207
+ if ($(fieldset).hasClass('closed')) {
208
+ close_expandable_fieldsets();
209
+ $(fieldset).removeClass('closed').addClass('open');
210
+ } else {
211
+ close_expandable_fieldsets();
212
+ };
213
+ };
214
+ };
215
+
216
+ // Submit forms
217
+ // FOR: Fake Submitting forms
218
+ /*
219
+ function submit_form(id, submitted_by) {
220
+ var frm = document.forms[id];
221
+
222
+ // If we passed a submitted_by array then add the elements to the form
223
+ if (submitted_by !== undefined) {
224
+
225
+ for(var key in submitted_by){
226
+ ff = document.createElement("INPUT");
227
+ ff.type = "hidden";
228
+ ff.name = key;
229
+ ff.value = submitted_by[key];
230
+ frm.appendChild(ff);
231
+ }
232
+
233
+ // Make the form revalidate so that the new values are passed
234
+ if (frm.normalize) {frm.normalize();}
235
+ }
236
+
237
+ frm.submit();
238
+ return false;
239
+ }
240
+
241
+ function reset_form(id) {
242
+ document.forms[id].reset();
243
+ return false;
244
+ }
245
+ */
246
+
247
+ // Convert Buttons
248
+ // FOR: Convert button.btn to a.btn in ie6
249
+
250
+
251
+
252
+ function highlight_links(id) {
253
+
254
+ $('tr').removeClass('highlight');
255
+ for(var i = 0; i<id.length; i++) {
256
+ //alert(id[i]);
257
+ $(id[i]).addClass('highlight');
258
+ };
259
+ };
260
+
261
+ var verbose_output = (document.location.toString().indexOf(".dev") > 0);
262
+ function trace(text) {
263
+ if (verbose_output && window.console != null) console.log(text);
264
+ }
265
+
266
+
267
+ // Style Buttons in ie
268
+ // FOR: adding inline styles to buttons to make them work in IE 6 + 7 (but not 8, ie8 is fine)
269
+
270
+ function style_buttons_for_ie() {
271
+
272
+ $('button.btn').each(function() {
273
+
274
+ // i X Positioning
275
+ var spanW = $(this).children('span').width();
276
+ var iW = $(this).children('i').width();
277
+ var XPos = spanW+iW;
278
+ var XPosNum = '-' + XPos + 'px';
279
+
280
+
281
+ // i Y Positioning
282
+ var iH = $(this).children('i').height();
283
+ var iYPos = '-' + iH + 'px'
284
+
285
+ // Button Width
286
+ var bW = spanW+iW + 'px'
287
+
288
+ if (Object.prototype.toString.call(self.JSON) === "[object JSON]"){
289
+ // IE8: Dont fix anything
290
+ }
291
+
292
+ else if (typeof document.body.style.maxHeight === "undefined") {
293
+ // ie6: Add inline styles
294
+ $(this).each(function() {
295
+ $(this).children('i').css({'position' : 'relative', 'right' : XPosNum, 'top' : iYPos});
296
+ $(this).css({'height' : iH, 'width' : bW, 'overflow' : 'hidden'});
297
+ })
298
+
299
+ } else {
300
+ // ie7 (same fix as ie6 fix)
301
+
302
+ $(this).each(function() {
303
+ $(this).children('i').css({'position' : 'relative', 'right' : XPosNum, 'top' : iYPos});
304
+ $(this).css({'height' : iH, 'width' : bW, 'overflow' : 'hidden'})
305
+ })
306
+
307
+ }
308
+
309
+ });
310
+
311
+ };
@@ -199,6 +199,19 @@ module Videojuicer
199
199
  }}
200
200
  end
201
201
 
202
+ class Asset::Document
203
+ include FixtureHelper
204
+ set_attribute_proc {{
205
+ :user_id => rand(100) + 1,
206
+ :licensed_at => Time.now,
207
+ :licensed_by => "foo, bar",
208
+ :licensed_under => "CC BY:NC:SA",
209
+ :published_at => Time.now,
210
+ :file => File.open(File.join(File.dirname(__FILE__), "..", "files", "document.js"))
211
+ }}
212
+ end
213
+
214
+
202
215
  class Asset::Video
203
216
  include FixtureHelper
204
217
  set_attribute_proc {{
@@ -76,6 +76,28 @@ describe Videojuicer::Resource::PropertyRegistry do
76
76
  @example_registry.attr_set :string, "987654321"
77
77
  @example_registry.attr_get(:string).should == "987654321"
78
78
  end
79
+
80
+ it "registers an attribute as being dirty when the attribute is set" do
81
+ @r = ::FooAttributeRegistry.new
82
+ @r.attr_set :string, "987654321"
83
+ @r.attr_dirty?(:string).should be_true
84
+ @r.attr_dirty?(:integer).should be_false
85
+ end
86
+
87
+ it "clears the dirty attributes when clean_dirty_attributes! is called" do
88
+ @r = ::FooAttributeRegistry.new
89
+ @r.attr_set :string, "987654321"
90
+ @r.attr_dirty?(:string).should be_true
91
+ @r.clean_dirty_attributes!
92
+ @r.attr_dirty?(:string).should be_false
93
+ end
94
+
95
+ it "provides the dirty attributes for submission as a hash" do
96
+ @r = ::FooAttributeRegistry.new
97
+ @r.integer = 0
98
+ @r.dirty_attribute_keys.should == [:string_with_default, :integer]
99
+ @r.dirty_attributes.should == {:string_with_default=>"this is the default", :integer=>0}
100
+ end
79
101
 
80
102
  it "converts attributes to a date when a string is passed into a datetime object" do
81
103
  @date_registry.date = "2009-07-01 13:14:15"
@@ -92,6 +114,8 @@ describe Videojuicer::Resource::PropertyRegistry do
92
114
  @example_private_prop_registry.returnable_attributes.should_not include(:id)
93
115
  end
94
116
  it "does not include the private attributes in the returnable attributes" do
117
+ @example_private_prop_registry.public_attr = "foo" # dirty the attributes
118
+ @example_private_prop_registry.private_attr = "bar"
95
119
  @example_private_prop_registry.returnable_attributes.should_not include(:private_attr)
96
120
  @example_private_prop_registry.returnable_attributes.should include(:public_attr)
97
121
  end
data/spec/seed_spec.rb ADDED
@@ -0,0 +1,21 @@
1
+ require File.join(File.dirname(__FILE__), "helpers", "spec_helper")
2
+
3
+ describe Videojuicer::Seed do
4
+
5
+ before(:all) do
6
+ @klass = Videojuicer::Seed
7
+ configure_test_settings
8
+ end
9
+
10
+ describe "instantiation" do
11
+ it_should_behave_like "a configurable"
12
+ end
13
+
14
+ describe "getting the current seed" do
15
+ it "should be successful" do
16
+ s = Videojuicer::Seed.current
17
+ s.name.should == Videojuicer.current_scope[:seed_name]
18
+ end
19
+ end
20
+
21
+ end
@@ -33,7 +33,10 @@ shared_examples_for "a RESTFUL resource model" do
33
33
  end
34
34
  it "gets an ID" do
35
35
  @successful.id.should be_kind_of(Integer)
36
- end
36
+ end
37
+ it "resets the dirty attributes" do
38
+ @successful.dirty_attributes.should be_empty
39
+ end
37
40
  end
38
41
  describe "unsuccessfully" do
39
42
  before(:all) do
@@ -58,6 +61,9 @@ shared_examples_for "a RESTFUL resource model" do
58
61
  it "does not get an ID" do
59
62
  @fail.id.should be_nil
60
63
  end
64
+ it "does not reset the dirty attributes" do
65
+ @fail.dirty_attributes.should_not be_empty
66
+ end
61
67
  end
62
68
  end
63
69
  end
@@ -75,6 +81,10 @@ shared_examples_for "a RESTFUL resource model" do
75
81
  attrs = attrs.reject {|k,v| !v}
76
82
  attrs.should_not be_empty
77
83
  end
84
+
85
+ it "has no dirty attributes" do
86
+ @record.dirty_attributes.should be_empty
87
+ end
78
88
  end
79
89
 
80
90
  describe "listing records" do
@@ -82,6 +92,12 @@ shared_examples_for "a RESTFUL resource model" do
82
92
  @list = @klass.all
83
93
  end
84
94
 
95
+ it "returns items with no dirty attributes" do
96
+ @list.each do |i|
97
+ i.dirty_attributes.should be_empty
98
+ end
99
+ end
100
+
85
101
  it "should return a collection object" do
86
102
  @list.should be_kind_of(Videojuicer::Resource::Collection)
87
103
  end
@@ -118,6 +134,16 @@ shared_examples_for "a RESTFUL resource model" do
118
134
  @record.reload.should be_true
119
135
  end
120
136
 
137
+ it "resets the dirty attributes when reloaded" do
138
+ r = @klass.gen
139
+ r = @klass.get(r.id)
140
+ dattr = @klass.attributes.select {|a,props| props[:class] == String || props[:class] == Integer }.map {|a| a.first }.first
141
+ r.send("#{dattr}=", 1)
142
+ r.attr_dirty?(dattr).should be_true
143
+ r.reload
144
+ r.attr_dirty?(dattr).should be_false
145
+ end
146
+
121
147
  it "saves successfully" do
122
148
  saved = @record.save
123
149
  @record.errors.should == {}
data/vj-sdk.gemspec CHANGED
@@ -5,22 +5,20 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{vj-sdk}
8
- s.version = "0.2.1"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["danski", "thejohnny", "knowtheory", "sixones", "btab"]
12
- s.date = %q{2009-10-30}
12
+ s.date = %q{2010-03-04}
13
13
  s.email = %q{dan@videojuicer.com}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
16
- "README.markdown",
17
- "README.rdoc"
16
+ "README.markdown"
18
17
  ]
19
18
  s.files = [
20
19
  ".gitignore",
21
20
  "LICENSE",
22
21
  "README.markdown",
23
- "README.rdoc",
24
22
  "Rakefile",
25
23
  "VERSION.yml",
26
24
  "lib/core_ext/cgi.rb",
@@ -31,6 +29,7 @@ Gem::Specification.new do |s|
31
29
  "lib/videojuicer.rb",
32
30
  "lib/videojuicer/asset/audio.rb",
33
31
  "lib/videojuicer/asset/base.rb",
32
+ "lib/videojuicer/asset/document.rb",
34
33
  "lib/videojuicer/asset/flash.rb",
35
34
  "lib/videojuicer/asset/image.rb",
36
35
  "lib/videojuicer/asset/text.rb",
@@ -57,11 +56,13 @@ Gem::Specification.new do |s|
57
56
  "lib/videojuicer/resource/property_registry.rb",
58
57
  "lib/videojuicer/resource/relationships/belongs_to.rb",
59
58
  "lib/videojuicer/resource/types.rb",
59
+ "lib/videojuicer/seed.rb",
60
60
  "lib/videojuicer/session.rb",
61
61
  "lib/videojuicer/shared/configurable.rb",
62
62
  "lib/videojuicer/shared/exceptions.rb",
63
63
  "lib/videojuicer/user.rb",
64
64
  "spec/assets/audio_spec.rb",
65
+ "spec/assets/document_spec.rb",
65
66
  "spec/assets/flash_spec.rb",
66
67
  "spec/assets/image_spec.rb",
67
68
  "spec/assets/text_spec.rb",
@@ -76,6 +77,7 @@ Gem::Specification.new do |s|
76
77
  "spec/criterion/time_spec.rb",
77
78
  "spec/criterion/week_day_spec.rb",
78
79
  "spec/files/audio.mp3",
80
+ "spec/files/document.js",
79
81
  "spec/files/empty_file",
80
82
  "spec/files/flash.swf",
81
83
  "spec/files/image.jpg",
@@ -92,6 +94,7 @@ Gem::Specification.new do |s|
92
94
  "spec/promos/video_spec.rb",
93
95
  "spec/property_registry_spec.rb",
94
96
  "spec/request_proxy_spec.rb",
97
+ "spec/seed_spec.rb",
95
98
  "spec/session_spec.rb",
96
99
  "spec/shared/asset_spec.rb",
97
100
  "spec/shared/configurable_spec.rb",
@@ -108,10 +111,11 @@ Gem::Specification.new do |s|
108
111
  s.homepage = %q{http://github.com/danski/vj-sdk}
109
112
  s.rdoc_options = ["--charset=UTF-8"]
110
113
  s.require_paths = ["lib"]
111
- s.rubygems_version = %q{1.3.5}
114
+ s.rubygems_version = %q{1.3.6}
112
115
  s.summary = %q{Videojuicer core-sdk}
113
116
  s.test_files = [
114
117
  "spec/assets/audio_spec.rb",
118
+ "spec/assets/document_spec.rb",
115
119
  "spec/assets/flash_spec.rb",
116
120
  "spec/assets/image_spec.rb",
117
121
  "spec/assets/text_spec.rb",
@@ -136,6 +140,7 @@ Gem::Specification.new do |s|
136
140
  "spec/promos/video_spec.rb",
137
141
  "spec/property_registry_spec.rb",
138
142
  "spec/request_proxy_spec.rb",
143
+ "spec/seed_spec.rb",
139
144
  "spec/session_spec.rb",
140
145
  "spec/shared/asset_spec.rb",
141
146
  "spec/shared/configurable_spec.rb",
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vj-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 4
8
+ - 0
9
+ version: 0.4.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - danski
@@ -13,39 +18,50 @@ autorequire:
13
18
  bindir: bin
14
19
  cert_chain: []
15
20
 
16
- date: 2009-10-30 00:00:00 +00:00
21
+ date: 2010-03-04 00:00:00 +00:00
17
22
  default_executable:
18
23
  dependencies:
19
24
  - !ruby/object:Gem::Dependency
20
25
  name: json
21
- type: :runtime
22
- version_requirement:
23
- version_requirements: !ruby/object:Gem::Requirement
26
+ prerelease: false
27
+ requirement: &id001 !ruby/object:Gem::Requirement
24
28
  requirements:
25
29
  - - ">="
26
30
  - !ruby/object:Gem::Version
31
+ segments:
32
+ - 1
33
+ - 0
27
34
  version: "1.0"
28
- version:
35
+ type: :runtime
36
+ version_requirements: *id001
29
37
  - !ruby/object:Gem::Dependency
30
38
  name: ruby-hmac
31
- type: :runtime
32
- version_requirement:
33
- version_requirements: !ruby/object:Gem::Requirement
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
34
41
  requirements:
35
42
  - - ">="
36
43
  - !ruby/object:Gem::Version
44
+ segments:
45
+ - 0
46
+ - 3
47
+ - 2
37
48
  version: 0.3.2
38
- version:
49
+ type: :runtime
50
+ version_requirements: *id002
39
51
  - !ruby/object:Gem::Dependency
40
52
  name: mash
41
- type: :runtime
42
- version_requirement:
43
- version_requirements: !ruby/object:Gem::Requirement
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
44
55
  requirements:
45
56
  - - ">="
46
57
  - !ruby/object:Gem::Version
58
+ segments:
59
+ - 0
60
+ - 0
61
+ - 3
47
62
  version: 0.0.3
48
- version:
63
+ type: :runtime
64
+ version_requirements: *id003
49
65
  description:
50
66
  email: dan@videojuicer.com
51
67
  executables: []
@@ -55,12 +71,10 @@ extensions: []
55
71
  extra_rdoc_files:
56
72
  - LICENSE
57
73
  - README.markdown
58
- - README.rdoc
59
74
  files:
60
75
  - .gitignore
61
76
  - LICENSE
62
77
  - README.markdown
63
- - README.rdoc
64
78
  - Rakefile
65
79
  - VERSION.yml
66
80
  - lib/core_ext/cgi.rb
@@ -71,6 +85,7 @@ files:
71
85
  - lib/videojuicer.rb
72
86
  - lib/videojuicer/asset/audio.rb
73
87
  - lib/videojuicer/asset/base.rb
88
+ - lib/videojuicer/asset/document.rb
74
89
  - lib/videojuicer/asset/flash.rb
75
90
  - lib/videojuicer/asset/image.rb
76
91
  - lib/videojuicer/asset/text.rb
@@ -97,11 +112,13 @@ files:
97
112
  - lib/videojuicer/resource/property_registry.rb
98
113
  - lib/videojuicer/resource/relationships/belongs_to.rb
99
114
  - lib/videojuicer/resource/types.rb
115
+ - lib/videojuicer/seed.rb
100
116
  - lib/videojuicer/session.rb
101
117
  - lib/videojuicer/shared/configurable.rb
102
118
  - lib/videojuicer/shared/exceptions.rb
103
119
  - lib/videojuicer/user.rb
104
120
  - spec/assets/audio_spec.rb
121
+ - spec/assets/document_spec.rb
105
122
  - spec/assets/flash_spec.rb
106
123
  - spec/assets/image_spec.rb
107
124
  - spec/assets/text_spec.rb
@@ -116,6 +133,7 @@ files:
116
133
  - spec/criterion/time_spec.rb
117
134
  - spec/criterion/week_day_spec.rb
118
135
  - spec/files/audio.mp3
136
+ - spec/files/document.js
119
137
  - spec/files/empty_file
120
138
  - spec/files/flash.swf
121
139
  - spec/files/image.jpg
@@ -132,6 +150,7 @@ files:
132
150
  - spec/promos/video_spec.rb
133
151
  - spec/property_registry_spec.rb
134
152
  - spec/request_proxy_spec.rb
153
+ - spec/seed_spec.rb
135
154
  - spec/session_spec.rb
136
155
  - spec/shared/asset_spec.rb
137
156
  - spec/shared/configurable_spec.rb
@@ -157,23 +176,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
176
  requirements:
158
177
  - - ">="
159
178
  - !ruby/object:Gem::Version
179
+ segments:
180
+ - 0
160
181
  version: "0"
161
- version:
162
182
  required_rubygems_version: !ruby/object:Gem::Requirement
163
183
  requirements:
164
184
  - - ">="
165
185
  - !ruby/object:Gem::Version
186
+ segments:
187
+ - 0
166
188
  version: "0"
167
- version:
168
189
  requirements: []
169
190
 
170
191
  rubyforge_project:
171
- rubygems_version: 1.3.5
192
+ rubygems_version: 1.3.6
172
193
  signing_key:
173
194
  specification_version: 3
174
195
  summary: Videojuicer core-sdk
175
196
  test_files:
176
197
  - spec/assets/audio_spec.rb
198
+ - spec/assets/document_spec.rb
177
199
  - spec/assets/flash_spec.rb
178
200
  - spec/assets/image_spec.rb
179
201
  - spec/assets/text_spec.rb
@@ -198,6 +220,7 @@ test_files:
198
220
  - spec/promos/video_spec.rb
199
221
  - spec/property_registry_spec.rb
200
222
  - spec/request_proxy_spec.rb
223
+ - spec/seed_spec.rb
201
224
  - spec/session_spec.rb
202
225
  - spec/shared/asset_spec.rb
203
226
  - spec/shared/configurable_spec.rb
data/README.rdoc DELETED
@@ -1,7 +0,0 @@
1
- = vj-sdk
2
-
3
- Description goes here.
4
-
5
- == Copyright
6
-
7
- Copyright (c) 2009 danski. See LICENSE for details.