rivendell-import 0.9 → 0.10

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rivendell-import (0.9)
4
+ rivendell-import (0.10)
5
5
  SyslogLogger (~> 2.0)
6
6
  activerecord (~> 3.2.8)
7
7
  activesupport (~> 3.2.8)
@@ -11,9 +11,10 @@ PATH
11
11
  listen (~> 1.3.1)
12
12
  mail
13
13
  rivendell-api (~> 0.0.5)
14
- rivendell-db (~> 0.2)
14
+ rivendell-db (~> 0.3)
15
15
  sinatra
16
16
  sqlite3
17
+ taglib-ruby
17
18
  trollop
18
19
  will_paginate (~> 3.0.0)
19
20
 
@@ -21,38 +22,40 @@ GEM
21
22
  remote: https://rubygems.org/
22
23
  specs:
23
24
  SyslogLogger (2.0)
24
- activemodel (3.2.17)
25
- activesupport (= 3.2.17)
25
+ activemodel (3.2.19)
26
+ activesupport (= 3.2.19)
26
27
  builder (~> 3.0.0)
27
- activerecord (3.2.17)
28
- activemodel (= 3.2.17)
29
- activesupport (= 3.2.17)
28
+ activerecord (3.2.19)
29
+ activemodel (= 3.2.19)
30
+ activesupport (= 3.2.19)
30
31
  arel (~> 3.0.2)
31
32
  tzinfo (~> 0.3.29)
32
- activesupport (3.2.17)
33
+ activesupport (3.2.19)
33
34
  i18n (~> 0.6, >= 0.6.4)
34
35
  multi_json (~> 1.0)
35
- addressable (2.3.5)
36
+ addressable (2.3.6)
36
37
  arel (3.0.3)
37
- bcrypt-ruby (3.1.2)
38
+ bcrypt (3.1.7)
39
+ bcrypt-ruby (3.1.5)
40
+ bcrypt (>= 3.1.3)
38
41
  builder (3.0.4)
39
- capistrano (2.14.2)
40
- highline
41
- net-scp (>= 1.0.0)
42
- net-sftp (>= 2.0.0)
43
- net-ssh (>= 2.0.14)
44
- net-ssh-gateway (>= 1.1.0)
45
- cucumber (1.3.10)
42
+ capistrano (3.2.1)
43
+ i18n
44
+ rake (>= 10.0.0)
45
+ sshkit (~> 1.3)
46
+ coderay (1.1.0)
47
+ colorize (0.7.3)
48
+ cucumber (1.3.17)
46
49
  builder (>= 2.1.2)
47
50
  diff-lcs (>= 1.1.3)
48
51
  gherkin (~> 2.12)
49
52
  multi_json (>= 1.7.5, < 2.0)
50
- multi_test (>= 0.0.2)
53
+ multi_test (>= 0.1.1)
51
54
  daemons (1.1.9)
52
- data_objects (0.10.13)
55
+ data_objects (0.10.14)
53
56
  addressable (~> 2.1)
54
- database_cleaner (0.8.0)
55
- diff-lcs (1.1.3)
57
+ database_cleaner (1.3.0)
58
+ diff-lcs (1.2.5)
56
59
  dm-core (1.2.1)
57
60
  addressable (~> 2.3)
58
61
  dm-do-adapter (1.2.0)
@@ -77,106 +80,114 @@ GEM
77
80
  uuidtools (~> 2.1)
78
81
  dm-validations (1.2.0)
79
82
  dm-core (~> 1.2.0)
80
- do_mysql (0.10.13)
81
- data_objects (= 0.10.13)
83
+ do_mysql (0.10.14)
84
+ data_objects (= 0.10.14)
85
+ docile (1.1.5)
82
86
  fastercsv (1.5.5)
83
- ffi (1.9.3)
87
+ ffi (1.9.5)
88
+ formatador (0.2.5)
84
89
  gherkin (2.12.2)
85
90
  multi_json (~> 1.3)
86
- guard (1.4.0)
87
- listen (>= 0.4.2)
91
+ guard (1.8.3)
92
+ formatador (>= 0.2.4)
93
+ listen (~> 1.3)
94
+ lumberjack (>= 1.0.2)
95
+ pry (>= 0.9.10)
88
96
  thor (>= 0.14.6)
89
- guard-cucumber (1.2.0)
97
+ guard-cucumber (1.4.1)
90
98
  cucumber (>= 1.2.0)
91
99
  guard (>= 1.1.0)
92
- guard-rspec (2.0.0)
93
- guard (>= 1.1)
94
- rspec (~> 2.11)
95
- highline (1.6.16)
96
- httmultiparty (0.3.14)
100
+ guard-rspec (3.1.0)
101
+ guard (>= 1.8)
102
+ rspec (~> 2.13)
103
+ httmultiparty (0.3.15)
97
104
  httparty (>= 0.7.3)
98
105
  mimemagic
99
106
  multipart-post
100
107
  httparty (0.11.0)
101
108
  multi_json (~> 1.0)
102
109
  multi_xml (>= 0.5.2)
103
- i18n (0.6.9)
110
+ i18n (0.6.11)
104
111
  json (1.8.1)
105
112
  json_pure (1.8.1)
106
- libnotify (0.8.2)
113
+ libnotify (0.8.3)
107
114
  ffi (>= 1.0.11)
108
115
  listen (1.3.1)
109
116
  rb-fsevent (>= 0.9.3)
110
117
  rb-inotify (>= 0.9)
111
118
  rb-kqueue (>= 0.2)
112
- mail (2.5.4)
113
- mime-types (~> 1.16)
114
- treetop (~> 1.4.8)
115
- mime-types (1.25.1)
119
+ lumberjack (1.0.9)
120
+ mail (2.6.1)
121
+ mime-types (>= 1.16, < 3)
122
+ method_source (0.8.2)
123
+ mime-types (2.3)
116
124
  mimemagic (0.2.1)
117
- multi_json (1.8.2)
118
- multi_test (0.0.3)
125
+ multi_json (1.10.1)
126
+ multi_test (0.1.1)
119
127
  multi_xml (0.5.5)
120
128
  multipart-post (2.0.0)
121
- net-scp (1.1.0)
122
- net-ssh (>= 2.6.5)
123
- net-sftp (2.1.1)
124
- net-ssh (>= 2.6.5)
125
- net-ssh (2.6.6)
126
- net-ssh-gateway (1.2.0)
129
+ net-scp (1.2.1)
127
130
  net-ssh (>= 2.6.5)
131
+ net-ssh (2.9.1)
128
132
  null_logger (0.0.1)
129
- polyglot (0.3.5)
133
+ pry (0.10.1)
134
+ coderay (~> 1.1.0)
135
+ method_source (~> 0.8.1)
136
+ slop (~> 3.4)
130
137
  rack (1.5.2)
131
- rack-protection (1.5.1)
138
+ rack-protection (1.5.3)
132
139
  rack
133
- rake (0.9.2.2)
134
- rb-fsevent (0.9.3)
135
- rb-inotify (0.9.2)
140
+ rake (10.3.2)
141
+ rb-fsevent (0.9.4)
142
+ rb-inotify (0.9.5)
136
143
  ffi (>= 0.5.0)
137
- rb-kqueue (0.2.0)
144
+ rb-kqueue (0.2.3)
138
145
  ffi (>= 0.5.0)
139
- rdoc (3.12.2)
146
+ rdoc (4.1.2)
140
147
  json (~> 1.4)
141
148
  rivendell-api (0.0.5)
142
149
  activesupport
143
150
  httmultiparty
144
151
  null_logger
145
- rivendell-db (0.2)
152
+ rivendell-db (0.3)
146
153
  dm-core
147
154
  dm-mysql-adapter
148
155
  dm-serializer
149
156
  dm-types
150
157
  dm-validations
151
- rspec (2.11.0)
152
- rspec-core (~> 2.11.0)
153
- rspec-expectations (~> 2.11.0)
154
- rspec-mocks (~> 2.11.0)
155
- rspec-core (2.11.1)
156
- rspec-expectations (2.11.3)
157
- diff-lcs (~> 1.1.3)
158
- rspec-mocks (2.11.3)
159
- simplecov (0.6.4)
158
+ rspec (2.99.0)
159
+ rspec-core (~> 2.99.0)
160
+ rspec-expectations (~> 2.99.0)
161
+ rspec-mocks (~> 2.99.0)
162
+ rspec-core (2.99.2)
163
+ rspec-expectations (2.99.2)
164
+ diff-lcs (>= 1.1.3, < 2.0)
165
+ rspec-mocks (2.99.2)
166
+ simplecov (0.9.1)
167
+ docile (~> 1.1.0)
160
168
  multi_json (~> 1.0)
161
- simplecov-html (~> 0.5.3)
162
- simplecov-html (0.5.3)
169
+ simplecov-html (~> 0.8.0)
170
+ simplecov-html (0.8.0)
163
171
  simplecov-rcov (0.2.3)
164
172
  simplecov (>= 0.4.1)
165
- sinatra (1.4.4)
173
+ sinatra (1.4.5)
166
174
  rack (~> 1.4)
167
175
  rack-protection (~> 1.4)
168
176
  tilt (~> 1.3, >= 1.3.4)
177
+ slop (3.6.0)
169
178
  sqlite3 (1.3.9)
179
+ sshkit (1.5.1)
180
+ colorize
181
+ net-scp (>= 1.1.2)
182
+ net-ssh (>= 2.8.0)
170
183
  stringex (1.5.1)
171
- thor (0.16.0)
184
+ taglib-ruby (0.7.0)
185
+ thor (0.19.1)
172
186
  tilt (1.4.1)
173
- treetop (1.4.15)
174
- polyglot
175
- polyglot (>= 0.3.1)
176
187
  trollop (2.0)
177
- tzinfo (0.3.39)
178
- uuidtools (2.1.4)
179
- will_paginate (3.0.5)
188
+ tzinfo (0.3.41)
189
+ uuidtools (2.1.5)
190
+ will_paginate (3.0.7)
180
191
 
181
192
  PLATFORMS
182
193
  ruby
data/Guardfile CHANGED
@@ -1,9 +1,6 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
3
-
4
- guard 'rspec' do
1
+ guard :rspec do
5
2
  watch(%r{^spec/.+_spec\.rb$})
6
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
4
  watch('spec/spec_helper.rb') { "spec" }
8
5
  end
9
6
 
@@ -35,7 +35,7 @@ module Rivendell::Import
35
35
  end
36
36
  end
37
37
 
38
- Listen.to(directory).change(&callback).start!
38
+ Listen.to(directory, latency: 1, wait_for_delay: 5).change(&callback).start!
39
39
  end
40
40
 
41
41
  def process(*paths)
@@ -10,7 +10,7 @@ module Rivendell::Import
10
10
 
11
11
  def attributes
12
12
  attributes = {}
13
- %w{number group clear_cuts title default_title import_options}.each do |attribute|
13
+ %w{number group clear_cuts title default_title scheduler_codes import_options}.each do |attribute|
14
14
  value = send attribute
15
15
  attributes[attribute] = value if value.present?
16
16
  end
@@ -32,13 +32,17 @@ module Rivendell::Import
32
32
 
33
33
  delegate :blank?, :to => :attributes
34
34
 
35
- attr_accessor :number, :group, :title, :default_title
35
+ attr_accessor :number, :group, :title, :default_title, :scheduler_codes
36
36
  attr_reader :task
37
37
 
38
38
  def initialize(task = nil)
39
39
  @task = task
40
40
  end
41
41
 
42
+ def scheduler_codes
43
+ @scheduler_codes ||= []
44
+ end
45
+
42
46
  def xport
43
47
  task.xport
44
48
  end
@@ -51,44 +55,97 @@ module Rivendell::Import
51
55
  end
52
56
 
53
57
  def update
54
- begin
55
- update_by_api
56
- rescue => e
57
- Rivendell::Import.logger.debug "Update by API failed : #{e}"
58
- update_by_db if Database.enabled?
58
+ updaters.any? do |updater|
59
+ updater.new(self).update
59
60
  end
60
61
  end
61
62
 
62
- def empty_title?(title)
63
- [ nil, "", "[new cart]" ].include? title
63
+ def updaters
64
+ [].tap do |updaters|
65
+ updaters << ApiUpdater if scheduler_codes.empty?
66
+ updaters << DbUpdater if Database.enabled?
67
+ end
68
+ end
69
+
70
+ class Updater
71
+
72
+ attr_accessor :cart
73
+
74
+ def initialize(cart)
75
+ @cart = cart
76
+ end
77
+ delegate :number, :title, :default_title, :scheduler_codes, :to => :cart
78
+
79
+ def empty_title?(title)
80
+ [ nil, "", "[new cart]" ].include? title
81
+ end
82
+
83
+ def title_with_default
84
+ @title_with_default ||=
85
+ if title
86
+ title
87
+ else
88
+ default_title if default_title && empty_title?(current_title)
89
+ end
90
+ end
91
+
92
+ def update
93
+ begin
94
+ update!
95
+ rescue => e
96
+ Rivendell::Import.logger.debug "#{self.class.name} failed : #{e}"
97
+ false
98
+ end
99
+ end
100
+
64
101
  end
65
102
 
66
- def update_by_api
67
- update_attributes = {}
103
+ class ApiUpdater < Updater
68
104
 
69
- if title
70
- update_attributes[:title] = title
71
- else
72
- update_attributes[:title] = default_title if default_title && empty_title?(xport.list_cart(number).title)
105
+ def update!
106
+ unless attributes.empty?
107
+ Rivendell::Import.logger.debug "Update Cart by API : #{attributes}"
108
+ xport.edit_cart number, attributes
109
+ else
110
+ true
111
+ end
73
112
  end
74
113
 
75
- unless update_attributes.empty?
76
- Rivendell::Import.logger.debug "Update Cart by API : #{update_attributes}"
77
- xport.edit_cart number, update_attributes
114
+ delegate :xport, :to => :cart
115
+
116
+ def current_title
117
+ xport.list_cart(number).title
78
118
  end
119
+
120
+ def attributes
121
+ {}.tap do |attributes|
122
+ attributes[:title] = title_with_default if title_with_default
123
+ end
124
+ end
125
+
79
126
  end
80
127
 
81
- def update_by_db
82
- Database.init
128
+ class DbUpdater < Updater
83
129
 
84
- Rivendell::Import.logger.debug "Update Cart by DB"
85
- current_cart = Rivendell::DB::Cart.get(number)
86
- if title
87
- current_cart.title = title
88
- else
89
- current_cart.title = default_title if default_title && empty_title?(current_cart.title)
130
+ def current_cart
131
+ @current_cart ||= Rivendell::DB::Cart.get(number)
90
132
  end
91
- current_cart.save
133
+
134
+ def current_title
135
+ current_cart.title
136
+ end
137
+
138
+ def update!
139
+ Database.init
140
+
141
+ if title_with_default or not scheduler_codes.empty?
142
+ Rivendell::Import.logger.debug "Update Cart by DB"
143
+ current_cart.title = title_with_default
144
+ current_cart.scheduler_codes = scheduler_codes
145
+ current_cart.save
146
+ end
147
+ end
148
+
92
149
  end
93
150
 
94
151
  def cut
@@ -20,6 +20,10 @@ module Rivendell::Import
20
20
  end
21
21
  end
22
22
 
23
+ def log(message)
24
+ logger.info message if message
25
+ end
26
+
23
27
  def run(&block)
24
28
  instance_exec file, &block if block_given?
25
29
  end
@@ -31,6 +31,16 @@ module Rivendell::Import
31
31
  ::File.extname(name).gsub(/^\./,'')
32
32
  end
33
33
 
34
+ def directories
35
+ filename = path
36
+ [].tap do |directories|
37
+ while (parent = ::File.dirname(filename)) != ::File::SEPARATOR
38
+ directories << ::File.basename(parent)
39
+ filename = parent
40
+ end
41
+ end.reverse
42
+ end
43
+
34
44
  def ==(other)
35
45
  other and path == other.path
36
46
  end
@@ -65,6 +75,32 @@ module Rivendell::Import
65
75
  ::File.exists? path
66
76
  end
67
77
 
78
+ def file_ref
79
+ @file_ref ||=
80
+ if exists? and not (file_ref = TagLib::FileRef.new(path)).null?
81
+ file_ref
82
+ else
83
+ :null
84
+ end
85
+
86
+ @file_ref unless :null == @file_ref
87
+ end
88
+
89
+ def close
90
+ if @file_ref.respond_to?(:close)
91
+ @file_ref.close
92
+ @file_ref = nil
93
+ end
94
+ end
95
+
96
+ def tag
97
+ file_ref.tag if file_ref
98
+ end
99
+
100
+ def audio_properties
101
+ file_ref.audio_properties if file_ref
102
+ end
103
+
68
104
  def destroy!
69
105
  Rivendell::Import.logger.debug "Delete file #{path}"
70
106
  ::File.delete(path) if exists?
@@ -17,7 +17,11 @@ module Rivendell::Import
17
17
  end
18
18
 
19
19
  def self.ready
20
- self.pending.select(&:ready?)
20
+ pending.by_priority.select(&:ready?)
21
+ end
22
+
23
+ def self.by_priority
24
+ order(["priority desc", "created_at"])
21
25
  end
22
26
 
23
27
  RAN_STATUSES = %w{completed failed canceled}.freeze
@@ -128,6 +132,8 @@ module Rivendell::Import
128
132
  logger.error "Task failed : #{e}"
129
133
  logger.debug e.backtrace.join("\n")
130
134
  ensure
135
+ close_file
136
+
131
137
  unless ran?
132
138
  change_status! :failed
133
139
  end
@@ -22,5 +22,9 @@ module Rivendell::Import::Tasking
22
22
  self.delete_file = true
23
23
  end
24
24
 
25
+ def close_file
26
+ @file.close if @file
27
+ end
28
+
25
29
  end
26
30
  end
@@ -14,8 +14,19 @@ module Rivendell::Import
14
14
  end
15
15
 
16
16
  def create(file, &block)
17
- Rivendell::Import::Task.create({:file => file}, {}, &block).tap do |task|
18
- Rivendell::Import.logger.debug "Created task #{task.inspect}"
17
+ retry_count = 3
18
+ begin
19
+ Rivendell::Import::Task.create({:file => file}, {}, &block).tap do |task|
20
+ Rivendell::Import.logger.debug "Created task #{task.inspect}"
21
+ end
22
+ rescue Exception => e
23
+ Rivendell::Import.logger.error "Can't create Task: #{e}"
24
+ retry_count -= 1
25
+ if retry_count > 0
26
+ Rivendell::Import.logger.error "Retry in 5s"
27
+ sleep 5
28
+ retry
29
+ end
19
30
  end
20
31
  end
21
32
 
@@ -1,5 +1,5 @@
1
1
  module Rivendell
2
2
  module Import
3
- VERSION = "0.9"
3
+ VERSION = "0.10"
4
4
  end
5
5
  end
@@ -45,7 +45,7 @@
45
45
  <td><%= distance_of_time_in_words_from_now(task.updated_at) %></td>
46
46
  <td><%= truncate_filename(task.file, 60) %></td>
47
47
  <td><%= task.destination %></td>
48
- <td>default</td>
48
+ <td><%= task.priority or "default" %></td>
49
49
  </tr>
50
50
  <% end %>
51
51
  </table>
@@ -8,9 +8,9 @@ module Rivendell::Import
8
8
  end
9
9
 
10
10
  def start
11
- Thread.new do
11
+ Thread.new do
12
12
  Rivendell::Import.logger.debug "Start Worker"
13
- run
13
+ run
14
14
  end
15
15
 
16
16
  self
@@ -18,16 +18,19 @@ module Rivendell::Import
18
18
 
19
19
  def run
20
20
  loop do
21
- task = import.tasks.pop
22
- if task
23
- task.run
24
- else
25
- # Rivendell::Import.logger.debug "No pending task, sleep 10s"
21
+ begin
22
+ task = import.tasks.pop
23
+ if task
24
+ task.run
25
+ else
26
+ # Rivendell::Import.logger.debug "No pending task, sleep 10s"
27
+ sleep 10
28
+ end
29
+ rescue Exception => e
30
+ Rivendell::Import.logger.error "Worker failed : #{e}"
26
31
  sleep 10
27
32
  end
28
33
  end
29
- rescue => e
30
- Rivendell::Import.logger.error "Worker failed : #{e}"
31
34
  end
32
35
 
33
36
  end
@@ -4,6 +4,7 @@ require "null_logger"
4
4
  require "active_support/core_ext/module/attribute_accessors"
5
5
  require "active_support/core_ext/module/delegation"
6
6
  require "active_support/core_ext/enumerable"
7
+ require 'taglib'
7
8
 
8
9
  require "rivendell/import/config"
9
10
 
@@ -27,13 +27,14 @@ Gem::Specification.new do |gem|
27
27
  gem.add_runtime_dependency 'mail'
28
28
  gem.add_runtime_dependency 'sqlite3'
29
29
  gem.add_runtime_dependency 'SyslogLogger', '~> 2.0'
30
+ gem.add_runtime_dependency 'taglib-ruby'
30
31
 
31
32
  gem.add_runtime_dependency 'sinatra'
32
33
  gem.add_runtime_dependency 'will_paginate', '~> 3.0.0'
33
34
 
34
35
  gem.add_runtime_dependency 'daemons'
35
36
 
36
- gem.add_runtime_dependency 'rivendell-db', '~> 0.2'
37
+ gem.add_runtime_dependency 'rivendell-db', '~> 0.3'
37
38
 
38
39
  gem.add_development_dependency "simplecov"
39
40
  gem.add_development_dependency "rspec"
Binary file
@@ -120,7 +120,7 @@ describe Rivendell::Import::Base do
120
120
  end
121
121
 
122
122
  it "should invoke Listen.to with given directory" do
123
- Listen.should_receive(:to).with(directory)
123
+ Listen.should_receive(:to).with(directory, anything)
124
124
  subject.listen directory
125
125
  end
126
126
 
@@ -188,6 +188,11 @@ describe Rivendell::Import::Cart do
188
188
  subject.attributes["cut"].should == { "days" => %{mon} }
189
189
  end
190
190
 
191
+ it "should include scheduler codes" do
192
+ subject.scheduler_codes << "dummy"
193
+ subject.attributes["scheduler_codes"].should == ["dummy"]
194
+ end
195
+
191
196
  end
192
197
 
193
198
  describe "#to_json" do
@@ -208,6 +213,60 @@ describe Rivendell::Import::Cart do
208
213
 
209
214
  end
210
215
 
216
+ describe "#updaters" do
217
+
218
+ it "should contain ApiUpdater" do
219
+ subject.updaters.should include(Rivendell::Import::Cart::ApiUpdater)
220
+ end
221
+
222
+ it "should not contain ApiUpdater if scheduler codes is defined" do
223
+ subject.scheduler_codes << "dummy"
224
+ subject.updaters.should_not include(Rivendell::Import::Cart::ApiUpdater)
225
+ end
226
+
227
+ it "should contain DbUpdater if Database is enabled" do
228
+ Rivendell::Import::Database.stub :enabled? => true
229
+ subject.updaters.should include(Rivendell::Import::Cart::DbUpdater)
230
+ end
231
+
232
+ it "should not contain DbUpdater if Database isn't enabled" do
233
+ Rivendell::Import::Database.stub :enabled? => false
234
+ subject.updaters.should_not include(Rivendell::Import::Cart::DbUpdater)
235
+ end
236
+
237
+ end
238
+
239
+ describe "#update" do
240
+
241
+ def updater(success = true)
242
+ double(:new => mock(:update => success))
243
+ end
244
+
245
+ it "should return true if an Updater is successful" do
246
+ subject.stub :updaters => [updater(false), updater(true)]
247
+ subject.update.should be_true
248
+ end
249
+
250
+ it "should return true if all Updaters are not successful" do
251
+ subject.stub :updaters => [updater(false)]
252
+ subject.update.should be_false
253
+ end
254
+
255
+ it "should return false when no Updater is available" do
256
+ subject.stub :updaters => []
257
+ subject.update.should be_false
258
+ end
259
+
260
+ end
261
+
262
+ end
263
+
264
+ describe Rivendell::Import::Cart::Updater do
265
+
266
+ let(:task) { mock }
267
+ let(:cart) { Rivendell::Import::Cart.new task }
268
+ subject { Rivendell::Import::Cart::Updater.new cart }
269
+
211
270
  describe "#empty_title?" do
212
271
 
213
272
  it "should true when title is nil" do
@@ -224,44 +283,170 @@ describe Rivendell::Import::Cart do
224
283
 
225
284
  end
226
285
 
227
- describe "update" do
286
+ describe "#update" do
228
287
 
229
- it "should invoke update_by_api" do
230
- subject.should_receive :update_by_api
231
- subject.update
288
+ it "should return false if update! raises an error" do
289
+ subject.stub(:update!).and_raise("fail")
290
+ subject.update.should be_false
232
291
  end
233
292
 
234
- context "when when update_by_api fails" do
293
+ it "should return true if update! returns true" do
294
+ subject.stub :update! => true
295
+ subject.update.should be_true
296
+ end
235
297
 
236
- before do
237
- subject.stub(:update_by_api).and_raise("#fail")
298
+ it "should return false if update! returns false" do
299
+ subject.stub :update! => false
300
+ subject.update.should be_false
301
+ end
302
+
303
+ end
304
+
305
+ describe "#title_with_default" do
306
+
307
+ context "when Cart title is defined" do
308
+
309
+ before { cart.title = "dummy" }
310
+
311
+ it "should use this Cart title" do
312
+ subject.title_with_default.should == cart.title
238
313
  end
239
314
 
240
- context "when database is enabled" do
315
+ end
241
316
 
242
- before do
243
- Rivendell::Import::Database.stub :enabled? => true
244
- end
317
+ context "when default title is defined" do
245
318
 
246
- it "should invoke update_by_db " do
247
- subject.should_receive :update_by_db
248
- subject.update
249
- end
319
+ before { cart.default_title = "dummy" }
320
+
321
+ it "should default title if current title is empty" do
322
+ subject.stub current_title: "[new cart]"
323
+ subject.title_with_default.should == cart.default_title
324
+ end
250
325
 
326
+ it "should not use default title if current title is not empty" do
327
+ subject.stub current_title: "Dummy"
328
+ subject.title_with_default.should be_nil
251
329
  end
252
330
 
253
- context "when database is disabled" do
331
+ end
332
+
333
+ end
334
+
335
+ end
336
+
337
+ describe Rivendell::Import::Cart::ApiUpdater do
338
+
339
+ let(:task) { mock }
340
+ let(:cart) { Rivendell::Import::Cart.new task }
341
+ subject { Rivendell::Import::Cart::ApiUpdater.new cart }
342
+
343
+ let(:xport) { mock }
254
344
 
255
- before do
256
- Rivendell::Import::Database.stub :enabled? => false
257
- end
345
+ before do
346
+ subject.stub xport: xport
347
+ end
348
+
349
+ describe "#current_title" do
350
+
351
+ it "should retrive the current title via the API" do
352
+ xport_cart = mock(title: "dummy")
353
+ xport.should_receive(:list_cart).with(cart.number).and_return(xport_cart)
354
+ subject.current_title.should == xport_cart.title
355
+ end
356
+
357
+ end
358
+
359
+ describe "#attributes" do
360
+
361
+ it "should use title with default" do
362
+ subject.stub title_with_default: "dummy"
363
+ subject.attributes.should == { title: subject.title_with_default }
364
+ end
365
+
366
+ it "should not contain title when title_with_default is nil" do
367
+ subject.stub title_with_default: nil
368
+ subject.attributes.should == {}
369
+ end
370
+
371
+ end
372
+
373
+ describe "#update!" do
374
+
375
+ context "when attributes is not empty" do
376
+
377
+ it "should invoke xport edit_cart with attributes" do
378
+ subject.stub attributes: { title: "dummy" }
379
+ xport.should_receive(:edit_cart).with(cart.number, subject.attributes)
380
+ subject.update!
381
+ end
382
+
383
+ end
258
384
 
259
- it "should not invoke update_by_db " do
260
- subject.should_not_receive :update_by_db
261
- subject.update
262
- end
385
+ context "when attributes is empty" do
263
386
 
387
+ it "should not invoke xport edit_cart" do
388
+ subject.stub attributes: {}
389
+ xport.should_not_receive(:edit_cart)
390
+ subject.update!.should be_true
264
391
  end
392
+
393
+ end
394
+
395
+ end
396
+
397
+ end
398
+
399
+ describe Rivendell::Import::Cart::DbUpdater do
400
+
401
+ let(:task) { mock }
402
+ let(:cart) { Rivendell::Import::Cart.new task }
403
+ subject { Rivendell::Import::Cart::DbUpdater.new cart }
404
+
405
+ let(:db_cart) { Rivendell::DB::Cart.new }
406
+
407
+ before do
408
+ Rivendell::Import::Database.stub init: true
409
+ db_cart.stub save: true
410
+ Rivendell::DB::Cart.stub get: db_cart
411
+ end
412
+
413
+ describe "#current_cart" do
414
+
415
+ it "should get cart with its number" do
416
+ Rivendell::DB::Cart.should_receive(:get).with(cart.number).and_return(db_cart)
417
+ subject.current_cart.should == db_cart
418
+ end
419
+
420
+ end
421
+
422
+ describe "#current_title" do
423
+
424
+ it "should return current_cart title" do
425
+ db_cart.stub title: "dummy"
426
+ subject.current_title.should == db_cart.title
427
+ end
428
+
429
+ end
430
+
431
+ describe "#update!" do
432
+
433
+ it "should init database" do
434
+ Rivendell::Import::Database.should_receive :init
435
+ subject.update!
436
+ end
437
+
438
+ it "should use title_with_default as Cart title" do
439
+ subject.stub title_with_default: "dummy"
440
+ subject.update!
441
+ db_cart.title.should == subject.title_with_default
442
+ end
443
+
444
+ it "should define scheduler_codes" do
445
+ subject.stub scheduler_codes: ["dummy"]
446
+ subject.update!
447
+ db_cart.scheduler_codes.should == subject.scheduler_codes
265
448
  end
449
+
266
450
  end
451
+
267
452
  end
@@ -8,7 +8,7 @@ describe Rivendell::Import::Context do
8
8
  subject { Rivendell::Import::Context.new task }
9
9
 
10
10
  describe "#notify" do
11
-
11
+
12
12
  it "should add the specified notifier to the task" do
13
13
  subject.notify 'recipient@domain', :by => :email
14
14
  subject.task.notifiers.first.to.should == 'recipient@domain'
@@ -16,4 +16,15 @@ describe Rivendell::Import::Context do
16
16
 
17
17
  end
18
18
 
19
+ describe "#log" do
20
+
21
+ let(:message) { "dummy" }
22
+
23
+ it "should log the given message with info level" do
24
+ subject.logger.should_receive(:info).with(message)
25
+ subject.log message
26
+ end
27
+
28
+ end
29
+
19
30
  end
@@ -2,10 +2,14 @@ require 'spec_helper'
2
2
 
3
3
  describe Rivendell::Import::File do
4
4
 
5
- subject { Rivendell::Import::File.new "/path/to/dummy.wav", :base_directory => "/path/to" }
5
+ subject { Rivendell::Import::File.new fixture_file("audio.ogg"), :base_directory => fixture_directory }
6
+
7
+ after do
8
+ subject.close
9
+ end
6
10
 
7
11
  describe "initialization" do
8
-
12
+
9
13
  it "should use given base_directory to compute relative name" do
10
14
  Rivendell::Import::File.new("/path/to/dummy.wav", :base_directory => "/path/to").name.should == "dummy.wav"
11
15
  end
@@ -13,7 +17,7 @@ describe Rivendell::Import::File do
13
17
  end
14
18
 
15
19
  describe "#to_s" do
16
-
20
+
17
21
  it "should use name" do
18
22
  subject.to_s.should == subject.name
19
23
  end
@@ -21,7 +25,7 @@ describe Rivendell::Import::File do
21
25
  end
22
26
 
23
27
  describe ".relative_filename" do
24
-
28
+
25
29
  it "should return '/subdirectory/file' from '/base/subdirectory/file'" do
26
30
  Rivendell::Import::File.relative_filename('/base/subdirectory/file', '/base').should == 'subdirectory/file'
27
31
  end
@@ -29,7 +33,7 @@ describe Rivendell::Import::File do
29
33
  end
30
34
 
31
35
  describe "match" do
32
-
36
+
33
37
  it "should match a given regexp" do
34
38
  subject.stub :name => "dummy"
35
39
  subject.should match(/^dum/)
@@ -43,7 +47,7 @@ describe Rivendell::Import::File do
43
47
  end
44
48
 
45
49
  describe "#basename" do
46
-
50
+
47
51
  it "should return 'dummy' for 'path/to/dummy.wav'" do
48
52
  subject.stub :name => "path/to/dummy.wav"
49
53
  subject.basename.should == "dummy"
@@ -52,7 +56,7 @@ describe Rivendell::Import::File do
52
56
  end
53
57
 
54
58
  describe "#extension" do
55
-
59
+
56
60
  it "should 'wav' for 'path/to/dummy.wav'" do
57
61
  subject.stub :name => "path/to/dummy.wav"
58
62
  subject.extension.should == "wav"
@@ -60,4 +64,38 @@ describe Rivendell::Import::File do
60
64
 
61
65
  end
62
66
 
67
+ describe "#directories" do
68
+
69
+ it "should return 'path' and 'to' for 'path/to/dummy.wav'" do
70
+ subject.stub :path => "/path/to/dummy.wav"
71
+ subject.directories.should == %w{path to}
72
+ end
73
+
74
+ end
75
+
76
+ describe "#tag" do
77
+
78
+ it "should return tags contained by file metadata" do
79
+ subject.tag.title.should == "Audio Test Content"
80
+ end
81
+
82
+ end
83
+
84
+ describe "#audio_properties" do
85
+
86
+ it "should file audio properties" do
87
+ subject.audio_properties.length.should == 60
88
+ end
89
+
90
+ end
91
+
92
+ describe "#close" do
93
+
94
+ it "should close TaLib file_ref" do
95
+ subject.file_ref.should_receive :close
96
+ subject.close
97
+ end
98
+
99
+ end
100
+
63
101
  end
@@ -108,6 +108,11 @@ describe Rivendell::Import::Task do
108
108
  subject.status.should be_completed
109
109
  end
110
110
 
111
+ it "should close the used file" do
112
+ subject.file.should_receive :close
113
+ subject.run
114
+ end
115
+
111
116
  it "should change the status to failed if an error is raised" do
112
117
  subject.cart.stub(:create).and_raise("dummy")
113
118
  subject.run
@@ -364,4 +369,25 @@ describe Rivendell::Import::Task do
364
369
 
365
370
  end
366
371
 
372
+ describe "#ready" do
373
+
374
+ def task(attributes = {})
375
+ attributes = { :file => file }.merge(attributes)
376
+ Rivendell::Import::Task.create attributes
377
+ end
378
+
379
+ it "should return Task order by priority" do
380
+ lower_priority_task = task priority: 1, created_at: 5.minutes.ago
381
+ higher_priority_task = task priority: 2
382
+ Rivendell::Import::Task.ready.should == [ higher_priority_task, lower_priority_task ]
383
+ end
384
+
385
+ it "should return Task order by creation date" do
386
+ new_task = task
387
+ old_task = task created_at: 5.minutes.ago
388
+ Rivendell::Import::Task.ready.should == [ old_task, new_task ]
389
+ end
390
+
391
+ end
392
+
367
393
  end
@@ -1,3 +1,7 @@
1
+ def fixture_directory
2
+ File.expand_path "../../fixtures", __FILE__
3
+ end
4
+
1
5
  def fixture_file(name)
2
- File.expand_path "../../fixtures/#{name}", __FILE__
6
+ File.join fixture_directory, name
3
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rivendell-import
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.9'
4
+ version: '0.10'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-06-11 00:00:00.000000000 Z
12
+ date: 2014-10-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: listen
@@ -171,6 +171,22 @@ dependencies:
171
171
  - - ~>
172
172
  - !ruby/object:Gem::Version
173
173
  version: '2.0'
174
+ - !ruby/object:Gem::Dependency
175
+ name: taglib-ruby
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ type: :runtime
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
174
190
  - !ruby/object:Gem::Dependency
175
191
  name: sinatra
176
192
  requirement: !ruby/object:Gem::Requirement
@@ -226,7 +242,7 @@ dependencies:
226
242
  requirements:
227
243
  - - ~>
228
244
  - !ruby/object:Gem::Version
229
- version: '0.2'
245
+ version: '0.3'
230
246
  type: :runtime
231
247
  prerelease: false
232
248
  version_requirements: !ruby/object:Gem::Requirement
@@ -234,7 +250,7 @@ dependencies:
234
250
  requirements:
235
251
  - - ~>
236
252
  - !ruby/object:Gem::Version
237
- version: '0.2'
253
+ version: '0.3'
238
254
  - !ruby/object:Gem::Dependency
239
255
  name: simplecov
240
256
  requirement: !ruby/object:Gem::Requirement
@@ -441,6 +457,7 @@ files:
441
457
  - lib/rivendell/import/worker.rb
442
458
  - log/.gitkeep
443
459
  - rivendell-import.gemspec
460
+ - spec/fixtures/audio.ogg
444
461
  - spec/fixtures/mail-body.erb
445
462
  - spec/rivendell/import/base_spec.rb
446
463
  - spec/rivendell/import/cart_finder_spec.rb
@@ -482,7 +499,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
482
499
  version: '0'
483
500
  segments:
484
501
  - 0
485
- hash: 1053952433249090038
502
+ hash: 3604849735216139138
486
503
  required_rubygems_version: !ruby/object:Gem::Requirement
487
504
  none: false
488
505
  requirements:
@@ -491,7 +508,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
491
508
  version: '0'
492
509
  segments:
493
510
  - 0
494
- hash: 1053952433249090038
511
+ hash: 3604849735216139138
495
512
  requirements: []
496
513
  rubyforge_project:
497
514
  rubygems_version: 1.8.23
@@ -504,6 +521,7 @@ test_files:
504
521
  - features/step_definitions/import_steps.rb
505
522
  - features/support/env.rb
506
523
  - features/support/mock_xport.rb
524
+ - spec/fixtures/audio.ogg
507
525
  - spec/fixtures/mail-body.erb
508
526
  - spec/rivendell/import/base_spec.rb
509
527
  - spec/rivendell/import/cart_finder_spec.rb