remi-rubytube 0.1.0 → 0.1.2

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/README.rdoc CHANGED
@@ -31,4 +31,19 @@ a screencast doesn't sound pleasant ... so I figured I'd automate it.
31
31
  => #<RubyTube::Screencast:0x7fcc8a831c98...>
32
32
 
33
33
  >> screencast.submit!
34
- => <WWW::Mechanize::Page...>
34
+ => "Thanks for the submission! We'll post it after a quick review!"
35
+
36
+ # If you try to submit the same screencast again:
37
+
38
+ >> screencast.submit!
39
+ => "There was a problem, most likely a wrong or duplicate URL, sorry!"
40
+
41
+ After you've called RubyTube::Screencast#submit! you can goto a URL like http://rubytu.be/ruby-basics
42
+ to see if your screencast was created. It will show up here before it is added to the home page
43
+ of the site (my guess is that the site owner approves all videos?)
44
+
45
+ == Resources
46
+
47
+ RubyTube Site:: http://rubytu.be
48
+ RDoc:: http://remi.github.com/rubytube
49
+ Code:: http://github.com/remi/rubytube
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.2
data/lib/rubytube.rb CHANGED
@@ -1,7 +1,13 @@
1
1
  $LOAD_PATH.unshift File.dirname(__FILE__)
2
2
 
3
- %w( rubygems mechanize ).each {|lib| require lib }
3
+ require 'rubygems'
4
4
 
5
+ begin
6
+ require 'mechanize'
7
+ rescue LoadError
8
+ raise "mechanize failed to load. try: sudo gem install mechanize"
9
+ end
10
+
5
11
  module RubyTube #:nodoc:
6
12
 
7
13
  # Represents a screencast on http://rubytu.be
@@ -9,27 +15,66 @@ module RubyTube #:nodoc:
9
15
  # Currently, this is just used to post screencasts to RubyTube,
10
16
  # not to pull them. Unfortunately, RubyTube doesn't appear to
11
17
  # have any kind of an API or easy way to access video information.
12
- #
13
- # The whole site is 1 page (with pagination) and there's a Feed:
14
- # http://feeds.feedburner.com/rubytube?format=xml
15
- #
16
- # There are tags, but they don't even work!
17
18
  class Screencast
18
-
19
+
20
+ # Returns the required fields/attributes (an Array of strings or symbols)
21
+ #
22
+ # #valid? will ensure that each of these attributes is not empty.
23
+ #
24
+ # The default fields: DEFAULT_REQUIRED_FIELDS
19
25
  def self.required_fields
20
- @required_fiels
26
+ @required_fields
21
27
  end
22
- @required_fiels ||= %w( name title url description duration )
23
28
 
24
- attr_accessor :name, :twitter, :title, :url, :duration, :tags, :description
29
+ DEFAULT_REQUIRED_FIELDS = %w( name title url description duration )
30
+ @required_fields ||= DEFAULT_REQUIRED_FIELDS
31
+
32
+ # Your name, eg. 'Bob'
33
+ attr_accessor :name
34
+
35
+ # Your twitter ID, eg. '@coolbob'
36
+ attr_accessor :twitter
37
+
38
+ # The title of this Screencast, eg. 'ActiveRecord Awesomness'
39
+ attr_accessor :title
40
+
41
+ # The absolute path to this Screencast. This should not be a media
42
+ # URL (eg. a path to a video) nor should it be a URL to a site that
43
+ # has many videos (eg. 'http://peepcode.com'). Instead, this should
44
+ # be a link to a page that's specific to this Screencast
45
+ attr_accessor :url
46
+
47
+ # The duration of this Screencast, format: "HH:MM:SS"
48
+ attr_accessor :duration
25
49
 
50
+ # An Array of tags associated with this screencast, eg: ['Rails', 'ActiveRecord']
51
+ attr_accessor :tags
52
+
53
+ # A short description about this Screencast
54
+ attr_accessor :description
55
+
56
+ # After calling valid?, this is set to an Array which, if the
57
+ # Screencast isn't valid, will contain messages describing
58
+ # why the Screencast isn't valid
26
59
  attr_reader :errors
27
60
 
61
+ # Initialized a new Screencast
62
+ #
63
+ # Accepts a (standard) Hash or attributes, eg.
64
+ #
65
+ # >> @screencast = Screencast.new :name => 'remi', :title => 'Awesome Screencast'
66
+ #
28
67
  def initialize options = nil
29
68
  @tags ||= []
30
69
  options.each {|k,v| self.send "#{k}=", v } if options
31
70
  end
32
71
 
72
+ # Returns a boolean indicating whether or not this Screencast is valid
73
+ #
74
+ # #submit! cannot be called if #valid? doesn't return true
75
+ #
76
+ # After calling #valid?, you can check #errors to see messages
77
+ # describing why this Screencast isn't valid
33
78
  def valid?
34
79
  @errors = []
35
80
  Screencast.required_fields.each do |field|
@@ -40,15 +85,67 @@ module RubyTube #:nodoc:
40
85
  @errors.empty?
41
86
  end
42
87
 
88
+ # Submits this screencast to http://rubytu.be
89
+ #
90
+ # This is the same as going to http://rubytu.be and clicking 'Suggest Video'
91
+ # and filling out all of the fields
92
+ #
93
+ # If you want to preview all of the fields that will be filled out *before*
94
+ # calling #submit!, see #_fields
95
+ #
96
+ # Returns false if the screencast is not valid?, otherwise it returns a
97
+ # String (taken from the HTML response we get when we submit the form),
98
+ # describing whether or not the submission/suggestion was successful.
99
+ def submit!
100
+ raise "You cannot submit! an invalid Screencast" unless valid?
101
+
102
+ # the reason we're using instance variables is for caching (@agent) and
103
+ # so you can easily grab the values of these variables if you need them for debugging
104
+ @agent ||= WWW::Mechanize.new {|a| a.user_agent_alias = 'Linux Mozilla' }
105
+ @page = @agent.get 'http://rubytu.be/'
106
+ @submit_form = @page.forms.find {|form| form.action == '/content' }
107
+ @submit_form.set_fields _fields
108
+ @response = @agent.submit @submit_form
109
+
110
+ if @response.at('div.success')
111
+ @response.at('div.success').text.strip
112
+
113
+ elsif @response.at('div.error')
114
+ @response.at('div.error').text.strip
115
+
116
+ else
117
+ "No success or error message detected? see #_last_response to help with debugging."
118
+
119
+ end
120
+ end
121
+
122
+ # methods below here should likely be private! but we're keeping them public
123
+ # and giving them underscore prefixes to indicate that these are private methods
124
+
125
+ # [private]
126
+ #
127
+ # Returns the raw value to be used for the twitter field in the form we submit
128
+ #
129
+ # The user should use the #twitter attribute
43
130
  def _twitter_value
44
- (twitter.to_s.strip.empty?) ? '@' : twitter
131
+ val = (twitter.to_s.strip.empty?) ? '@' : twitter
132
+ val = "@#{val}" unless val.start_with?('@')
133
+ val
45
134
  end
46
135
 
136
+ # [private]
137
+ #
138
+ # Returns the raw value to be used for the tags field in the form we submit
139
+ #
140
+ # The user should use the #tags attribute
47
141
  def _tags_value
48
142
  tags.join(',')
49
143
  end
50
144
 
51
- def fields
145
+ # [private]
146
+ #
147
+ # Returns the raw values to be used for all of the fields in the form we submit
148
+ def _fields
52
149
  {
53
150
  'content[submitted_by]' => name,
54
151
  'content[submitted_by_twitter]' => _twitter_value,
@@ -60,16 +157,21 @@ module RubyTube #:nodoc:
60
157
  }
61
158
  end
62
159
 
63
- def submit!
64
- return unless valid?
65
-
66
- # the reason we're using instance variables is for caching (@agent) and
67
- # so you can easily grab the values of these variables if you need them for debugging
68
- @agent ||= WWW::Mechanize.new {|a| a.user_agent_alias = 'Linux Mozilla' }
69
- @page = @agent.get 'http://rubytu.be/'
70
- @submit_form = @page.forms.find {|form| form.action == '/content' }
71
- @submit_form.set_fields fields
72
- @agent.submit @submit_form
160
+ # [private]
161
+ #
162
+ # Returns the raw response of the last #submit! call
163
+ #
164
+ # This is a WWW::Mechanize::Page object
165
+ #
166
+ # To get the raw HTML of the response:
167
+ #
168
+ # >> @screencast.last_response.content
169
+ #
170
+ # If #submit! hasn't been called on this screencast, this will be nil
171
+ #
172
+ # This is really just for debugging!
173
+ def _last_response
174
+ @response
73
175
  end
74
176
 
75
177
  end
@@ -13,6 +13,7 @@ describe RubyTube::Screencast do
13
13
  RubyTube::Screencast.gen( :twitter => '@remitaylor' ).twitter.should == '@remitaylor'
14
14
 
15
15
  # check the private field that's actually used for form submission
16
+ RubyTube::Screencast.gen( :twitter => 'remitaylor' )._twitter_value.should == '@remitaylor'
16
17
  RubyTube::Screencast.gen( :twitter => '@remitaylor' )._twitter_value.should == '@remitaylor'
17
18
  RubyTube::Screencast.gen( :twitter => nil )._twitter_value.should == '@'
18
19
  RubyTube::Screencast.gen( :twitter => '' )._twitter_value.should == '@'
@@ -61,13 +62,13 @@ describe RubyTube::Screencast do
61
62
  :url => 'http://remi.org/some-screencast', :tags => %w( ruby rack ),
62
63
  :duration => '00:02:45'
63
64
  screencast.should be_valid
64
- screencast.fields['content[submitted_by]'].should == screencast.name
65
- screencast.fields['content[submitted_by_twitter]'].should == screencast._twitter_value
66
- screencast.fields['content[title]'].should == screencast.title
67
- screencast.fields['content[url]'].should == screencast.url
68
- screencast.fields['content[tag_list]'].should == screencast._tags_value
69
- screencast.fields['content[duration]'].should == screencast.duration
70
- screencast.fields['content[about]'].should == screencast.description
65
+ screencast._fields['content[submitted_by]'].should == screencast.name
66
+ screencast._fields['content[submitted_by_twitter]'].should == screencast._twitter_value
67
+ screencast._fields['content[title]'].should == screencast.title
68
+ screencast._fields['content[url]'].should == screencast.url
69
+ screencast._fields['content[tag_list]'].should == screencast._tags_value
70
+ screencast._fields['content[duration]'].should == screencast.duration
71
+ screencast._fields['content[about]'].should == screencast.description
71
72
  end
72
73
 
73
74
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remi-rubytube
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - remi