video_data 0.1.0 → 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/.autotest ADDED
@@ -0,0 +1 @@
1
+ require 'autotest/growl'
data/.rspec CHANGED
@@ -1 +1,2 @@
1
1
  --color
2
+ --format documentation
data/README.markdown CHANGED
@@ -27,3 +27,40 @@ Use Rubygems to install video_data:
27
27
  video.tags # Outputs an array of active tags
28
28
  video[:date] # Hash like access to data
29
29
  video.to_s # Ouputs a human readable string of the video data
30
+ video.eye_winged? # Dynamic predicates for each tag
31
+
32
+ ## Tests
33
+
34
+ $ rake spec
35
+
36
+ ## Documentation
37
+
38
+ $ rake rdoc
39
+
40
+ ## Description of Solution
41
+ Decided from the first moment to make it a gem to make it easy to use
42
+ and install.
43
+ I decided to separate in two clases the main responsabilites to
44
+ resolve the problem:
45
+
46
+ * VideoData::Parser: Read the csv file and get the columns(attributes)
47
+ and the data. Have a convenient method to get all the videos in the
48
+ file. Handle convertion of : to _ for tags.
49
+ * VideoData::Video: From the attributes extracted in the parser and
50
+ the row data define the attributes of the video.
51
+
52
+ The gotchas are when pairing the attributes and the row data, order
53
+ is vital to associate each value. Some data is saved as is (:videos,
54
+ :date, :celebrity) while each tag is associated to a boolean value.
55
+
56
+ VideoData::Video has easy access to the data using \#name, \#date,
57
+ \#celebrity and \#tags. Bonus hash-like access is a natural
58
+ addition given that internally the data is stored in a hash.
59
+
60
+ So recaping we have VideoData::Parser that reads the file, separates
61
+ the columns and the data, then delegates the pairing of attributes and row
62
+ data to VideoData::Video, finally internally it stores the video data in a Hash.
63
+
64
+ Brownie points for adding dynamic predicates for each defined tag.
65
+
66
+ A convenient ::new in the top module to jump start the extraction.
data/Rakefile CHANGED
@@ -44,6 +44,7 @@ RDoc::Task.new do |rdoc|
44
44
 
45
45
  rdoc.rdoc_dir = 'rdoc'
46
46
  rdoc.title = "video_data #{version}"
47
+ rdoc.main = "README.rdoc"
47
48
  rdoc.rdoc_files.include('README*')
48
49
  rdoc.rdoc_files.include('lib/**/*.rb')
49
50
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.1
@@ -1,15 +1,35 @@
1
1
  module VideoData
2
2
 
3
+ # Class that handles the extraction of the attributes
4
+ # and video data from the csv file
3
5
  class Parser
6
+ # The first row of the csv file defines the attributes the videos have.
4
7
  attr_reader :attributes
5
8
 
9
+ # Extracts the data inside the csv file given in the +path+
10
+ # The attributes and data are separated here.
11
+ # * *Args* :
12
+ # - +path+ The file path to the csv file.
6
13
  def initialize(path)
7
- raise ArgumentError, "Expected a csv file" unless File.exists?(path)
14
+ raise ArgumentError, "Expected a csv file" unless File.exists?(path) && path =~ /(.*)\.csv/
8
15
  @data = File.read(path)
9
- attributes = @data.slice!(/.*?\n/).strip.split(',')
10
- @attributes = attributes.collect {|attr| attr.downcase.gsub(/:/, '_').to_sym}
16
+
17
+ raw_attributes = @data.slice!(/.*?\n/)
18
+ raise VideoData::NotAWellFormedCSV unless raw_attributes
19
+
20
+ attributes = raw_attributes.strip.split(',')
21
+ @attributes = attributes.collect do |attr|
22
+ attr.downcase.gsub(/:/, '_').to_sym
23
+ end
24
+
25
+ [:videos, :date, :celebrity].each do |attr|
26
+ raise VideoData::NotAWellFormedCSV, "#{attr} column is missing in csv file" unless @attributes.include?(attr)
27
+ end
11
28
  end
12
29
 
30
+ # For each row in the csv file a VideoData::Video is created.
31
+ # * *Returns* :
32
+ # - An array of VideoData::Video objects.
13
33
  def videos
14
34
  videos = []
15
35
  @data.lines do |line|
@@ -1,9 +1,27 @@
1
1
  module VideoData
2
+ # Class that represents the data of a video.
3
+ # Has dynamic predicates for valid tags.
4
+ # If :eye_winged is a valid tag you can
5
+ # video = VideoData.new(attributes, data)
6
+ # video.eye_winged? # Outputs *true* or *false*
2
7
  class Video
8
+ # The defined attributes from the csv file the video data
9
+ # was extacted.
3
10
  attr_reader :attributes
4
11
 
12
+ # From the attributes and the row line a VideoData::Video is created
13
+ # * *Args* :
14
+ # - +attributes+ The attributes defined in the csv file. The
15
+ # order is vital to match attributes and values.
16
+ # - +data+ The row line that has all the video data in csv format
5
17
  def initialize(attributes, data)
6
18
  @attributes = attributes
19
+
20
+ @all_tags = attributes.dup
21
+ [:videos, :date, :celebrity].each do |attr|
22
+ @all_tags.delete attr
23
+ end
24
+
7
25
  video_data = data.strip.split(',')
8
26
 
9
27
  @data = {}
@@ -22,18 +40,25 @@ module VideoData
22
40
  end
23
41
  end
24
42
 
43
+ # Name of the video
25
44
  def name
26
45
  @data[:videos]
27
46
  end
28
47
 
48
+ # Date of the video
29
49
  def date
30
50
  @data[:date]
31
51
  end
32
52
 
53
+ # Celebrity of the video. Can be an empty string
33
54
  def celebrity
34
55
  @data[:celebrity]
35
56
  end
36
57
 
58
+ # The tags active for the video
59
+ # * *Returns* :
60
+ # -Returns an array of symbols. Each symbol is an active tag in
61
+ # the video
37
62
  def tags
38
63
  tags = @data.dup
39
64
  [:videos, :date, :celebrity].each do |attr|
@@ -42,20 +67,35 @@ module VideoData
42
67
  tags.select { |key,value| value }.keys
43
68
  end
44
69
 
70
+ # Hash-like access to the data
71
+ # * *Args* :
72
+ # - +attr+ The attribute to be ouput. Expects a symbol.
45
73
  def [](attr)
46
74
  @data[attr]
47
75
  end
48
76
 
77
+ # Return a human friendly output with the video data.
49
78
  def to_s
50
79
  video_tags = tags
51
80
  last_tag = video_tags.pop if video_tags.size > 1
52
81
  output_tags = video_tags.join(', ')
53
82
  output_tags += " and #{last_tag}" if last_tag
54
83
 
55
- "#{@data[:videos]} has a date of #{@data[:date]} and his " +
56
- "celebrity is #{@data[:celebrity]}, additionally this video" +
84
+ artist = celebrity.empty? ? "unknown" : celebrity
85
+
86
+ "#{name} has a date of #{date} and his " +
87
+ "celebrity is #{artist}, additionally this video" +
57
88
  " has this list of tags: #{output_tags}"
58
89
  end
90
+
91
+ # Added dynamic predicates for valid tags.
92
+ # eg if :eye_winged is a valid tag you can
93
+ # video.eye_winged? # Outputs *true* or *false*
94
+ def method_missing(m, *args) # :nodoc:
95
+ attr = m[0..-2].to_sym
96
+ return @data[attr] if m =~ /(.*)\?/ and @all_tags.include?(attr)
97
+ raise NoMethodError
98
+ end
59
99
  end
60
100
 
61
101
  end
data/lib/video_data.rb CHANGED
@@ -1,9 +1,19 @@
1
+ # The video_data gem helps in the extraction of video data from
2
+ # csv files.
1
3
  module VideoData
2
4
  class << self
5
+ # Create a new parser for the given csv file.
6
+ # * *Args* :
7
+ # - +path+ The file path to the csv file.
8
+ # * *Returns* :
9
+ # - A parser, VideoData::Parser, ready for video data extraction.
3
10
  def new(path)
4
11
  VideoData::Parser.new(path)
5
12
  end
6
13
  end
14
+
15
+ # Custom exception raised when the csv file isn't in the expect format
16
+ class NotAWellFormedCSV < StandardError; end
7
17
  end
8
18
 
9
19
  require 'video_data/video'
@@ -0,0 +1,3 @@
1
+ title, datetime, celeb, eye_winged, eye_smoked
2
+ qwenimern, 21-Abr-10, Jack,,
3
+ anqwebovn, 12-May-11,,x,x
File without changes
@@ -4,29 +4,39 @@ describe VideoData::Parser do
4
4
 
5
5
  before(:all) do
6
6
  path = File.dirname(__FILE__) + '/../data/video_data.csv'
7
+ @bad_file = File.dirname(__FILE__) + '/../data/video_data'
8
+ @bad_data = File.dirname(__FILE__) + '/../data/bad_data.csv'
7
9
  @parser = VideoData::Parser.new(path)
8
10
  end
9
11
 
10
- describe ".new" do
12
+ describe "::new" do
11
13
 
12
14
  it 'should raise an error with zero arguments' do
13
- expect{ VideoData::Parser.new }.to raise_error
15
+ expect{ VideoData::Parser.new }.to raise_error ArgumentError
14
16
  end
15
17
 
16
18
  it 'should raise an error with non-existant csv file' do
17
- expect{ VideoData::Parser.new('Idontexist.csv')}.to raise_error ArgumentError
19
+ expect{ VideoData::Parser.new('Idontexist.csv') }.to raise_error ArgumentError
20
+ end
21
+
22
+ it 'should raise an error with a non csv file' do
23
+ expect{ VideoData::Parser.new(@bad_file) }.to raise_error ArgumentError
24
+ end
25
+
26
+ it 'should raise an error with bad csv file' do
27
+ expect{ VideoData::Parser.new(@bad_data) }.to raise_error VideoData::NotAWellFormedCSV
18
28
  end
19
29
 
20
30
  end
21
31
 
22
- describe ".attributes" do
32
+ describe "#attributes" do
23
33
 
24
34
  it 'should return an array of symbols' do
25
35
  @parser.attributes.should be_a Array
26
36
  @parser.attributes[0].should be_a Symbol
27
37
  end
28
38
 
29
- it "should return tags without ':' has word separator" do
39
+ it "should return tags without ':' as word separator" do
30
40
  @parser.attributes[3].should_not match(/:/)
31
41
  @parser.attributes[-1].should_not match(/:/)
32
42
  end
@@ -38,7 +48,7 @@ describe VideoData::Parser do
38
48
 
39
49
  end
40
50
 
41
- describe ".videos" do
51
+ describe "#videos" do
42
52
  it 'should return an array of VideoData::Videos' do
43
53
  @parser.videos.should be_a Array
44
54
  @parser.videos[0].should be_a VideoData::Video
@@ -7,7 +7,7 @@ describe VideoData::Video do
7
7
  :eye_winged, :eye_effect, :eye_smokey]
8
8
  end
9
9
 
10
- describe ".new" do
10
+ describe "::new" do
11
11
 
12
12
  it 'should need two parameters' do
13
13
  data = "tSP3Yqqk1Vg,12-Feb-11,Adele,,x,"
@@ -17,7 +17,7 @@ describe VideoData::Video do
17
17
 
18
18
  end
19
19
 
20
- describe ".[]" do
20
+ describe "#[]" do
21
21
 
22
22
  it 'should return value using Array:Hash-type access' do
23
23
  data = "tSP3Yqqk1Vg,12-Feb-11,Adele,,x,"
@@ -51,7 +51,7 @@ describe VideoData::Video do
51
51
 
52
52
  end
53
53
 
54
- describe ".tags" do
54
+ describe "#tags" do
55
55
 
56
56
  it "should return an array of active tags" do
57
57
  data = "tSP3Yqqk1Vg,12-Feb-11,Adele,,x,x"
@@ -65,7 +65,7 @@ describe VideoData::Video do
65
65
 
66
66
  end
67
67
 
68
- describe ".to_s" do
68
+ describe "#to_s" do
69
69
 
70
70
  it 'should return a string with all the data of the video' do
71
71
  data = "tSP3Yqqk1Vg,12-Feb-11,Adele,x,x,x"
@@ -77,7 +77,7 @@ describe VideoData::Video do
77
77
 
78
78
  end
79
79
 
80
- describe ".name" do
80
+ describe "#name" do
81
81
 
82
82
  it 'should return the name of the video' do
83
83
  data = "neYfvPKkXE,22-Aug-10,Alice Cullen,,,"
@@ -87,7 +87,7 @@ describe VideoData::Video do
87
87
 
88
88
  end
89
89
 
90
- describe ".date" do
90
+ describe "#date" do
91
91
 
92
92
  it 'should return the date of the video' do
93
93
  data = "neYfvPKkXE,22-Aug-10,Alice Cullen,,,"
@@ -97,7 +97,7 @@ describe VideoData::Video do
97
97
 
98
98
  end
99
99
 
100
- describe ".celebrity" do
100
+ describe "#celebrity" do
101
101
 
102
102
  it 'should return the celebrity of the video' do
103
103
  data = "neYfvPKkXE,22-Aug-10,Alice Cullen,,,"
@@ -107,4 +107,17 @@ describe VideoData::Video do
107
107
 
108
108
  end
109
109
 
110
+ describe "dynamic predicates for tags" do
111
+
112
+ it 'should have dynamic predicates for tags' do
113
+ data = "neYfvPKkXE,22-Aug-10,Alice Cullen,x,,"
114
+ video = VideoData::Video.new(@attributes, data)
115
+ video.eye_winged?.should raise_error
116
+ video.eye_winged?.should be_true
117
+ video.eye_smokey?.should be_false
118
+ video.eye_effect?.should be_false
119
+ end
120
+
121
+ end
122
+
110
123
  end
@@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe VideoData do
4
4
 
5
- describe ".new" do
5
+ describe "::new" do
6
6
 
7
7
  it "should return a VideoData::Parser" do
8
8
  path = File.dirname(__FILE__) + '/data/video_data.csv'
@@ -0,0 +1,72 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "video_data"
8
+ s.version = "0.2.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Hector E. Gomez Morales"]
12
+ s.date = "2011-10-10"
13
+ s.description = "This gem is not for general consumption."
14
+ s.email = "hectoregm@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.markdown",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".autotest",
22
+ ".document",
23
+ ".rspec",
24
+ "Gemfile",
25
+ "LICENSE.txt",
26
+ "README.markdown",
27
+ "README.rdoc",
28
+ "Rakefile",
29
+ "VERSION",
30
+ "lib/video_data.rb",
31
+ "lib/video_data/parser.rb",
32
+ "lib/video_data/video.rb",
33
+ "spec/data/bad_data.csv",
34
+ "spec/data/video_data",
35
+ "spec/data/video_data.csv",
36
+ "spec/spec_helper.rb",
37
+ "spec/video_data/parser_spec.rb",
38
+ "spec/video_data/video_spec.rb",
39
+ "spec/video_data_spec.rb",
40
+ "video_data.gemspec"
41
+ ]
42
+ s.homepage = "http://github.com/hectoregm/video_data"
43
+ s.licenses = ["MIT"]
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = "1.8.10"
46
+ s.summary = "Extract video information from specially formated csv files."
47
+
48
+ if s.respond_to? :specification_version then
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
53
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
54
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
55
+ s.add_development_dependency(%q<rcov>, [">= 0"])
56
+ s.add_development_dependency(%q<rdoc>, [">= 0"])
57
+ else
58
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
59
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
60
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
61
+ s.add_dependency(%q<rcov>, [">= 0"])
62
+ s.add_dependency(%q<rdoc>, [">= 0"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
66
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
67
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
68
+ s.add_dependency(%q<rcov>, [">= 0"])
69
+ s.add_dependency(%q<rdoc>, [">= 0"])
70
+ end
71
+ end
72
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: video_data
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-09 00:00:00.000000000Z
12
+ date: 2011-10-10 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70236167737440 !ruby/object:Gem::Requirement
16
+ requirement: &70243334665840 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.3.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70236167737440
24
+ version_requirements: *70243334665840
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &70236167736340 !ruby/object:Gem::Requirement
27
+ requirement: &70243334664600 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70236167736340
35
+ version_requirements: *70243334664600
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: jeweler
38
- requirement: &70236167734700 !ruby/object:Gem::Requirement
38
+ requirement: &70243334663140 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.6.4
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70236167734700
46
+ version_requirements: *70243334663140
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rcov
49
- requirement: &70236167733560 !ruby/object:Gem::Requirement
49
+ requirement: &70243334661560 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70236167733560
57
+ version_requirements: *70243334661560
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rdoc
60
- requirement: &70236167732460 !ruby/object:Gem::Requirement
60
+ requirement: &70243334659920 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70236167732460
68
+ version_requirements: *70243334659920
69
69
  description: This gem is not for general consumption.
70
70
  email: hectoregm@gmail.com
71
71
  executables: []
@@ -75,6 +75,7 @@ extra_rdoc_files:
75
75
  - README.markdown
76
76
  - README.rdoc
77
77
  files:
78
+ - .autotest
78
79
  - .document
79
80
  - .rspec
80
81
  - Gemfile
@@ -87,11 +88,13 @@ files:
87
88
  - lib/video_data/parser.rb
88
89
  - lib/video_data/video.rb
89
90
  - spec/data/bad_data.csv
91
+ - spec/data/video_data
90
92
  - spec/data/video_data.csv
91
93
  - spec/spec_helper.rb
92
94
  - spec/video_data/parser_spec.rb
93
95
  - spec/video_data/video_spec.rb
94
96
  - spec/video_data_spec.rb
97
+ - video_data.gemspec
95
98
  homepage: http://github.com/hectoregm/video_data
96
99
  licenses:
97
100
  - MIT
@@ -107,7 +110,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
110
  version: '0'
108
111
  segments:
109
112
  - 0
110
- hash: -2143925689707778406
113
+ hash: 3094673234282739575
111
114
  required_rubygems_version: !ruby/object:Gem::Requirement
112
115
  none: false
113
116
  requirements: