video_data 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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: