mongify 0.1.2 → 0.1.3

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/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,12 @@
1
+ == 0.1.3 / 21 Feb 2011
2
+ * Made all exception stem from MongifyError and system always raises a child of MongifyError.
3
+ * Brought in the progress bar into source
4
+ * Changed behaviour on storing BigDecimal (now converts into String)
5
+ * Added ability to convert BigDecimal to integer via an :at => 'integer, :scale => 2 settings.
6
+ * Improved Progress Bar display, now it gives you a better feel for what's going on.
7
+ * Added an index on pre_mongified_id to speedup lookup times (Making it 42 times faster on import of embedded tables)
8
+ * Fixed bug in importing of polymorphic tables where associations are nil
9
+ * Fixed bug where pre_mongified_id would be a string and not an integer (causing no updates of ref_ids)
1
10
  == 0.1.2 / 14 Feb 2011
2
11
  * More Improvements to README and RDOC
3
12
  * Added ability to :force => true on a mongodb_connection, forcing it to drop database before processing.
data/Gemfile.lock CHANGED
@@ -1,31 +1,31 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mongify (0.1.2)
4
+ mongify (0.1.3)
5
5
  activerecord (>= 3.0.3)
6
6
  activesupport (>= 3.0.3)
7
7
  bson_ext (>= 1.1.5)
8
+ highline (>= 1.6.1)
8
9
  mongo (>= 1.1.5)
9
10
  mysql2
10
11
  net-ssh (>= 2.0)
11
- progressbar (>= 0.9)
12
12
 
13
13
  GEM
14
14
  remote: http://rubygems.org/
15
15
  specs:
16
- activemodel (3.0.3)
17
- activesupport (= 3.0.3)
16
+ activemodel (3.0.4)
17
+ activesupport (= 3.0.4)
18
18
  builder (~> 2.1.2)
19
19
  i18n (~> 0.4)
20
- activerecord (3.0.3)
21
- activemodel (= 3.0.3)
22
- activesupport (= 3.0.3)
20
+ activerecord (3.0.4)
21
+ activemodel (= 3.0.4)
22
+ activesupport (= 3.0.4)
23
23
  arel (~> 2.0.2)
24
24
  tzinfo (~> 0.3.23)
25
- activesupport (3.0.3)
26
- arel (2.0.7)
27
- bson (1.2.0)
28
- bson_ext (1.2.0)
25
+ activesupport (3.0.4)
26
+ arel (2.0.8)
27
+ bson (1.2.2)
28
+ bson_ext (1.2.2)
29
29
  builder (2.1.2)
30
30
  cucumber (0.10.0)
31
31
  builder (>= 2.1.2)
@@ -36,26 +36,24 @@ GEM
36
36
  diff-lcs (1.1.2)
37
37
  gherkin (2.3.3)
38
38
  json (~> 1.4.6)
39
+ highline (1.6.1)
39
40
  i18n (0.5.0)
40
41
  json (1.4.6)
41
- mocha (0.9.10)
42
- rake
43
- mongo (1.2.0)
44
- bson (>= 1.2.0)
42
+ mocha (0.9.12)
43
+ mongo (1.2.2)
44
+ bson (>= 1.2.2)
45
45
  mysql (2.8.1)
46
46
  mysql2 (0.2.6)
47
47
  net-ssh (2.1.0)
48
- progressbar (0.9.0)
49
- rake (0.8.7)
50
48
  rcov (0.9.9)
51
- rspec (2.4.0)
52
- rspec-core (~> 2.4.0)
53
- rspec-expectations (~> 2.4.0)
54
- rspec-mocks (~> 2.4.0)
55
- rspec-core (2.4.0)
56
- rspec-expectations (2.4.0)
49
+ rspec (2.5.0)
50
+ rspec-core (~> 2.5.0)
51
+ rspec-expectations (~> 2.5.0)
52
+ rspec-mocks (~> 2.5.0)
53
+ rspec-core (2.5.1)
54
+ rspec-expectations (2.5.0)
57
55
  diff-lcs (~> 1.1.2)
58
- rspec-mocks (2.4.0)
56
+ rspec-mocks (2.5.0)
59
57
  sqlite3 (1.3.3)
60
58
  sqlite3-ruby (1.3.3)
61
59
  sqlite3 (>= 1.3.3)
data/README.rdoc CHANGED
@@ -177,6 +177,8 @@ Table Options are as follow:
177
177
  end # Moving records around, renaming records, changing values in row based on
178
178
  end # some values! Checkout Mongify::Database::DataRow to learn more
179
179
 
180
+ More documentation can be found at {Mongify::Database::Table}
181
+
180
182
  === Columns
181
183
 
182
184
  ==== Structure
@@ -194,7 +196,7 @@ Before we cover the options, you need to know what types of columns are supporte
194
196
  :key # Columns that are primary keys need to be marked as :key type
195
197
  :integer # Will be converted to a integer
196
198
  :float # Will be converted to a float
197
- :decimal # Will be converted to a BigDecimal
199
+ :decimal # Will be converted to a string (due to MongoDB Ruby Drivers not supporting BigDecimal, read details in Mongify::Database::Column under Decimal Storage)
198
200
  :string # Will be converted to a string
199
201
  :text # Will be converted to a string
200
202
  :datetime # Will be converted to a Time format (DateTime is not currently supported in the Mongo ruby driver)
@@ -215,6 +217,18 @@ Before we cover the options, you need to know what types of columns are supporte
215
217
  column "surname",
216
218
  :string,
217
219
  :rename_to => 'last_name' # Rename_to allows you to rename the column
220
+
221
+ <em>For decimal columns you can specify a few options:</em>
222
+ column "total", # This is a default conversion setting.
223
+ :decimal,
224
+ :as => 'string'
225
+
226
+ column "total", # You can specify to convert your decimal to integer
227
+ :decimal, # specifying scale will define how many decimal places to keep
228
+ :as => 'integer', # Example: :scale => 2 will convert 123.4567 to 12346 before saving
229
+ :scale => 2
230
+
231
+ More documentation can be found at {Mongify::Database::Column}
218
232
 
219
233
  == Notes
220
234
 
@@ -224,8 +238,12 @@ More testing will be done once the basic functionality is done
224
238
 
225
239
 
226
240
  == TODO
241
+ * Allow deeper embedding
242
+ * Test in Ruby 1.9
243
+ * Test in different databases
227
244
 
228
- * Update user on what is being processed
245
+ == Known Issues
246
+ * Can't do anything to an embedded table
229
247
 
230
248
  == Development
231
249
 
data/lib/mongify.rb CHANGED
@@ -3,8 +3,9 @@
3
3
  #
4
4
  require 'active_support/core_ext'
5
5
  require 'active_record'
6
- require 'progressbar'
6
+ require 'highline'
7
7
 
8
+ require 'mongify/progressbar'
8
9
  require 'mongify/ui'
9
10
  require 'mongify/status'
10
11
  require 'mongify/exceptions'
@@ -26,9 +26,12 @@ module Mongify
26
26
  begin
27
27
  cmd = @options.parse
28
28
  cmd.execute(self)
29
- rescue Exception => error
29
+ rescue MongifyError => error
30
30
  $stderr.puts "Error: #{error}"
31
31
  report_error
32
+ rescue Exception => error
33
+ report_error
34
+ raise error
32
35
  end
33
36
  return @status
34
37
  end
@@ -87,6 +87,8 @@ EOB
87
87
  # option parser, ensuring parse_options is only called once
88
88
  def parse_options
89
89
  @parsed = true && @parser.parse!(@argv) unless @parsed
90
+ rescue OptionParser::InvalidOption => er
91
+ raise Mongify::InvalidOption, er.message, er.backtrace
90
92
  end
91
93
  end
92
94
  end
@@ -41,12 +41,12 @@ module Mongify
41
41
 
42
42
  # Used to setup connection, Raises NotImplementedError because it needs to be setup in BaseConnection's children
43
43
  def setup_connection_adapter
44
- raise NotImplementedError
44
+ raise NotImplementedMongifyError
45
45
  end
46
46
 
47
47
  # Used to test connection, Raises NotImplementedError because it needs to be setup in BaseConnection's children
48
48
  def has_connection?
49
- raise NotImplementedError
49
+ raise NotImplementedMongifyError
50
50
  end
51
51
 
52
52
 
@@ -19,7 +19,7 @@ module Mongify
19
19
  # :key # Columns that are primary keys need to be marked as :key type
20
20
  # :integer # Will be converted to a integer
21
21
  # :float # Will be converted to a float
22
- # :decimal # Will be converted to a BigDecimal
22
+ # :decimal # Will be converted to a string *(you can change default behaviour read below)
23
23
  # :string # Will be converted to a string
24
24
  # :text # Will be converted to a string
25
25
  # :datetime # Will be converted to a Time format (DateTime is not currently supported in the Mongo ruby driver)
@@ -41,12 +41,46 @@ module Mongify
41
41
  #
42
42
  # column "post_id", :integer, :auto_detect => true # Will run auto detect and make this column a :references => 'posts', :on => 'post_id' for you
43
43
  # # More used when reading a sql database, NOT recommended for use during processing of translation
44
+ #
45
+ # <em>For decimal columns you can specify a few options:</em>
46
+ # column "total", # This is a default conversion setting.
47
+ # :decimal,
48
+ # :as => 'string'
44
49
  #
50
+ # column "total", # You can specify to convert your decimal to integer
51
+ # :decimal, # specifying scale will define how many decimal places to keep
52
+ # :as => 'integer', # Example: :scale => 2 will convert 123.4567 to 12346 in to mongodb
53
+ # :scale => 2
54
+ # ==== Decimal Storage
55
+ #
56
+ # Unfortunately MongoDB Ruby Drivers doesn't support BigDecimal, so to ensure all data is stored correctly (without losing information)
57
+ # I've chosen to store as String, however you can overwrite this functionality in one of two ways:
58
+ # <em>The reason you would want to do this, is to make this searchable via a query.</em>
59
+ #
60
+ # <b>1) You can specify :as => 'integer', :scale => 2</b>
61
+ # column "total", :decimal, :as => 'integer', :scale => 2
62
+ #
63
+ # #It would take a value of 123.456 and store it as an integer of value 12346
64
+ #
65
+ # <b>2) You can specify your own custom conversion by doing a {Mongify::Database::Table#before_save}
66
+ #
67
+ # Example:
68
+ # table "invoice" do
69
+ # column "name", :string
70
+ # column "total", :decimal
71
+ # before_save do |row|
72
+ # row.total = (BigDecimal.new(row.total) * 1000).round
73
+ # end
74
+ # end
75
+ #
76
+ # This would take 123.456789 in the total column and convert it to an interger of value 123457 (and in your app you can convert it back to a decimal)
77
+ #
78
+ # *REMEMBER* there is a limit on how big of an integer you can store in BSON/MongoDB (http://bsonspec.org/#/specification)
45
79
  class Column
46
80
  attr_reader :sql_name, :type, :options
47
81
 
48
82
  #List of available options for a column
49
- AVAILABLE_OPTIONS = ['references', 'ignore', 'rename_to']
83
+ AVAILABLE_OPTIONS = ['references', 'ignore', 'rename_to', 'as', 'scale']
50
84
 
51
85
  # Auto detects if a column is an :key column or is a reference column
52
86
  def self.auto_detect(column)
@@ -88,7 +122,7 @@ module Mongify
88
122
  return {} if ignored?
89
123
  case type
90
124
  when :key
91
- {"pre_mongified_id" => value}
125
+ {"pre_mongified_id" => value.to_i}
92
126
  else
93
127
  {"#{name}" => type_cast(value)}
94
128
  end
@@ -115,14 +149,20 @@ module Mongify
115
149
  def method_missing(meth, *args, &blk)
116
150
  method_name = meth.to_s.gsub("=", '')
117
151
  if AVAILABLE_OPTIONS.include?(method_name)
118
- class_eval <<-EOF
119
- def #{method_name}=(value)
120
- options['#{method_name}'] = value
121
- end
122
- def #{method_name}
123
- options['#{method_name}']
124
- end
125
- EOF
152
+ unless self.class.method_defined?(method_name.to_sym)
153
+ class_eval <<-EOF
154
+ def #{method_name}=(value)
155
+ options['#{method_name}'] = value
156
+ end
157
+ EOF
158
+ end
159
+ unless self.class.method_defined?("#{method_name}=".to_sym)
160
+ class_eval <<-EOF
161
+ def #{method_name}
162
+ options['#{method_name}']
163
+ end
164
+ EOF
165
+ end
126
166
  send(meth, *args, &blk)
127
167
  else
128
168
  super(meth, *args, &blk)
@@ -154,6 +194,34 @@ module Mongify
154
194
  !!self.ignore
155
195
  end
156
196
 
197
+ # Used when trying to figure out how to convert a decimal value
198
+ # @return [String] passed option['as'] or defaults to 'string'
199
+ def as
200
+ options['as'] ||= 'string'
201
+ end
202
+ # Sets option['as'] to either 'string' or 'integer', defults to 'string' for unknown values
203
+ # @param [String|Symbol] value, can be either 'string' or 'integer
204
+ def as=(value)
205
+ value = value.to_s.downcase
206
+ options['as'] = ['string', 'integer'].include?(value) ? value : 'string'
207
+ end
208
+ # Returns true if :as was passed as integer
209
+ def as_integer?
210
+ self.as == 'integer'
211
+ end
212
+
213
+ # Get the scale option for decimal to integer conversion
214
+ # column 'total', :decimal, :as => 'integer', :scale => 3
215
+ # @return [integer] passed option['scale'] or 0
216
+ def scale
217
+ options['scale'] ||= 0
218
+ end
219
+ # Set the scale option for decimal to integer conversion
220
+ # column 'total', :decimal, :as => 'integer', :scale => 3
221
+ # @param [Integer] number of decimal places to round off to
222
+ def scale=(value)
223
+ options['scale'] = value.to_i
224
+ end
157
225
  #######
158
226
  private
159
227
  #######
@@ -164,9 +232,15 @@ module Mongify
164
232
  case type
165
233
  when :string then value
166
234
  when :text then value
167
- when :integer then value.to_i rescue value ? 1 : 0
235
+ when :integer then value.to_i
168
236
  when :float then value.to_f
169
- when :decimal then ActiveRecord::ConnectionAdapters::Column.value_to_decimal(value)
237
+ when :decimal
238
+ value = ActiveRecord::ConnectionAdapters::Column.value_to_decimal(value)
239
+ if as_integer?
240
+ (value * (10 ** self.scale)).round.to_i
241
+ else
242
+ value.to_s
243
+ end
170
244
  when :datetime then ActiveRecord::ConnectionAdapters::Column.string_to_time(value)
171
245
  when :timestamp then ActiveRecord::ConnectionAdapters::Column.string_to_time(value)
172
246
  when :time then ActiveRecord::ConnectionAdapters::Column.string_to_dummy_time(value)
@@ -176,6 +250,7 @@ module Mongify
176
250
  else value
177
251
  end
178
252
  end
253
+
179
254
 
180
255
 
181
256
  # runs auto detect (see {Mongify::Database::Column.auto_detect})
@@ -27,6 +27,7 @@ module Mongify
27
27
  class NoSqlConnection < Mongify::Database::BaseConnection
28
28
  include Mongo
29
29
 
30
+
30
31
  #Required fields for a no sql connection
31
32
  REQUIRED_FIELDS = %w{host database}
32
33
 
@@ -114,10 +115,26 @@ module Mongify
114
115
 
115
116
  # Removes pre_mongified_id from all records in a given collection
116
117
  def remove_pre_mongified_ids(collection_name)
118
+ drop_mongified_index(collection_name)
117
119
  db[collection_name].update({}, { '$unset' => { 'pre_mongified_id' => 1} }, :multi => true)
118
120
  end
119
121
 
122
+ # Removes pre_mongified_id from collection
123
+ # @param [String] collection_name name of collection to remove the index from
124
+ # @return True if successful
125
+ # @raise MongoDBError if index isn't found
126
+ def drop_mongified_index(collection_name)
127
+ db[collection_name].drop_index('pre_mongified_id_1') if db[collection_name].index_information.keys.include?("pre_mongified_id_1")
128
+ end
129
+
130
+ # Creates a pre_mongified_id index to ensure
131
+ # speedy lookup for collections via the pre_mongified_id
132
+ def create_pre_mongified_id_index(collection_name)
133
+ db[collection_name].create_index([['pre_mongified_id', Mongo::ASCENDING]])
134
+ end
135
+
120
136
  # Asks user permission to drop the database
137
+ # @return true or false depending on user's response
121
138
  def ask_to_drop_database
122
139
  if UI.ask("Are you sure you want to drop #{database} database?")
123
140
  drop_database
@@ -1,20 +1,34 @@
1
1
  module Mongify
2
+ # Base Mongify Error
3
+ class MongifyError < RuntimeError; end
4
+
5
+ # Not Implemented Error from Mongify
6
+ class NotImplementedMongifyError < MongifyError; end
7
+
2
8
  # File Not Found Exception
3
- class FileNotFound < RuntimeError; end
9
+ class FileNotFound < MongifyError; end
4
10
  # Raise when configuration file is missing
5
11
  class ConfigurationFileNotFound < FileNotFound; end
6
12
  # Raised when Translation file is missing
7
13
  class TranslationFileNotFound < FileNotFound; end
8
14
 
9
15
  # Basic Configuration Error Exception
10
- class ConfigurationError < RuntimeError; end
16
+ class ConfigurationError < MongifyError; end
11
17
  # Raise when a sqlConnection is required but not given
12
18
  class SqlConnectionRequired < ConfigurationError; end
19
+ # Raised when a SqlConfiguration is invalid?
20
+ class SqlConnectionInvalid < ConfigurationError; end
13
21
  # Raised when a noSqlConnection is required but not given
14
22
  class NoSqlConnectionRequired < ConfigurationError; end
23
+ # Raised when a NoSqlConfiguration is invalid?
24
+ class NoSqlConnectionInvalid < ConfigurationError; end
25
+
15
26
  # Raised when a Mongify::Database::Column is expected but not given
16
27
  class DatabaseColumnExpected < ConfigurationError; end
17
-
28
+
18
29
  # Raised when application has no root folder set
19
- class RootMissing < RuntimeError; end
30
+ class RootMissing < MongifyError; end
31
+
32
+ # Raised when an invalid option is passed via CLI
33
+ class InvalidOption < MongifyError; end
20
34
  end
@@ -0,0 +1,270 @@
1
+ #
2
+ # Ruby/ProgressBar - a text progress bar library
3
+ #
4
+ # Copyright (C) 2001-2005 Satoru Takabayashi <satoru@namazu.org>
5
+ # All rights reserved.
6
+ # This is free software with ABSOLUTELY NO WARRANTY.
7
+ #
8
+ # You can redistribute it and/or modify it under the terms
9
+ # of Ruby's license.
10
+ #
11
+ # This has been modified by
12
+ # Andrew Kalek
13
+ # Anlek Consulting
14
+ # http://anlek.com
15
+
16
+ module Mongify
17
+ # Progress bar used to display results
18
+ class ProgressBar
19
+ #Progress bar version
20
+ VERSION = "0.9.1"
21
+
22
+ def initialize (title, total, out = STDERR)
23
+ @title = title
24
+ @total = total
25
+ @out = out
26
+ @terminal_width = 80
27
+ @bar_mark = "o"
28
+ @current = 0
29
+ @previous = 0
30
+ @finished_p = false
31
+ @start_time = Time.now
32
+ @previous_time = @start_time
33
+ @title_width = 35
34
+ @format = "%-#{@title_width}s %s %3d%% %s %s"
35
+ @format_arguments = [:title, :count, :percentage, :bar, :stat]
36
+ clear
37
+ show
38
+ end
39
+ attr_reader :title
40
+ attr_reader :current
41
+ attr_reader :total
42
+ attr_accessor :start_time
43
+
44
+ #######
45
+ private
46
+ #######
47
+
48
+ # Formatting for the actual bar
49
+ def fmt_bar
50
+ bar_width = do_percentage * @terminal_width / 100
51
+ sprintf("|%s%s|",
52
+ @bar_mark * bar_width,
53
+ " " * (@terminal_width - bar_width))
54
+ end
55
+
56
+ # Formatting for the percentage
57
+ def fmt_percentage
58
+ do_percentage
59
+ end
60
+
61
+ # Formatting for the stat (time left or time taken to complete)
62
+ def fmt_stat
63
+ if @finished_p then elapsed else eta end
64
+ end
65
+
66
+ # Formatting for file transfer
67
+ def fmt_stat_for_file_transfer
68
+ if @finished_p then
69
+ sprintf("%s %s %s", bytes, transfer_rate, elapsed)
70
+ else
71
+ sprintf("%s %s %s", bytes, transfer_rate, eta)
72
+ end
73
+ end
74
+
75
+ # Formatting for title
76
+ def fmt_title
77
+ @title[0,(@title_width - 1)] + ":"
78
+ end
79
+
80
+ # Formatting for count (x/y)
81
+ def fmt_count
82
+ sprintf('%15s', "(#{@current}/#{@total})")
83
+ end
84
+
85
+ # Converts bytes to kb, mb or gb
86
+ def convert_bytes (bytes)
87
+ if bytes < 1024
88
+ sprintf("%6dB", bytes)
89
+ elsif bytes < 1024 * 1000 # 1000kb
90
+ sprintf("%5.1fKB", bytes.to_f / 1024)
91
+ elsif bytes < 1024 * 1024 * 1000 # 1000mb
92
+ sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
93
+ else
94
+ sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
95
+ end
96
+ end
97
+
98
+ # Returns the transfer rate
99
+ # works only with file transfer
100
+ def transfer_rate
101
+ bytes_per_second = @current.to_f / (Time.now - @start_time)
102
+ sprintf("%s/s", convert_bytes(bytes_per_second))
103
+ end
104
+
105
+ # Gets current byte count
106
+ def bytes
107
+ convert_bytes(@current)
108
+ end
109
+
110
+ # Gets formatting for time
111
+ def format_time (t)
112
+ t = t.to_i
113
+ sec = t % 60
114
+ min = (t / 60) % 60
115
+ hour = t / 3600
116
+ sprintf("%02d:%02d:%02d", hour, min, sec);
117
+ end
118
+
119
+ # ETA stands for Estimated Time of Arrival.
120
+ def eta
121
+ if @current == 0
122
+ "ETA: --:--:--"
123
+ else
124
+ elapsed = Time.now - @start_time
125
+ eta = elapsed * @total / @current - elapsed;
126
+ sprintf("ETA: %s", format_time(eta))
127
+ end
128
+ end
129
+
130
+ # Returns elapsed time
131
+ def elapsed
132
+ elapsed = Time.now - @start_time
133
+ sprintf("Time: %s", format_time(elapsed))
134
+ end
135
+
136
+ # Returns end of line
137
+ # @return [String] "\n" or "\r"
138
+ def eol
139
+ if @finished_p then "\n" else "\r" end
140
+ end
141
+
142
+ # Calculates percentage
143
+ # @return [Number] the percentage
144
+ def do_percentage
145
+ if @total.zero?
146
+ 100
147
+ else
148
+ @current * 100 / @total
149
+ end
150
+ end
151
+
152
+ # Gets the width of the terminal window
153
+ def get_width
154
+ UI.terminal_helper.output_cols
155
+ end
156
+
157
+ # Draws the bar
158
+ def show
159
+ arguments = @format_arguments.map {|method|
160
+ method = sprintf("fmt_%s", method)
161
+ send(method)
162
+ }
163
+ line = sprintf(@format, *arguments)
164
+
165
+ width = get_width
166
+ if line.length == width - 1
167
+ @out.print(line + eol)
168
+ @out.flush
169
+ elsif line.length >= width
170
+ @terminal_width = [@terminal_width - (line.length - width + 1), 0].max
171
+ if @terminal_width == 0 then @out.print(line + eol) else show end
172
+ else # line.length < width - 1
173
+ @terminal_width += width - line.length + 1
174
+ show
175
+ end
176
+ @previous_time = Time.now
177
+ end
178
+
179
+ # Checks if it's needed, shows if it's so
180
+ def show_if_needed
181
+ if @total.zero?
182
+ cur_percentage = 100
183
+ prev_percentage = 0
184
+ else
185
+ cur_percentage = (@current * 100 / @total).to_i
186
+ prev_percentage = (@previous * 100 / @total).to_i
187
+ end
188
+
189
+ # Use "!=" instead of ">" to support negative changes
190
+ if cur_percentage != prev_percentage ||
191
+ Time.now - @previous_time >= 1 || @finished_p
192
+ show
193
+ end
194
+ end
195
+
196
+ public
197
+ # Clear's line
198
+ def clear
199
+ @out.print "\r"
200
+ @out.print(" " * (get_width - 1))
201
+ @out.print "\r"
202
+ end
203
+
204
+ # Marks finished
205
+ def finish
206
+ @current = @total
207
+ @finished_p = true
208
+ show
209
+ end
210
+
211
+ # Returns if the bar is finished
212
+ def finished?
213
+ @finished_p
214
+ end
215
+
216
+ # Sets bar to file trasfer mode
217
+ def file_transfer_mode
218
+ @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
219
+ end
220
+
221
+ # Allows format to be re/defined
222
+ def format= (format)
223
+ @format = format
224
+ end
225
+
226
+ # Allows to change the arguments of items that are shown
227
+ def format_arguments= (arguments)
228
+ @format_arguments = arguments
229
+ end
230
+
231
+ # halts drawing of bar
232
+ def halt
233
+ @finished_p = true
234
+ show
235
+ end
236
+
237
+ # Incremets bar
238
+ # @return [Integer] current bar frame
239
+ def inc (step = 1)
240
+ @current += step
241
+ @current = @total if @current > @total
242
+ show_if_needed
243
+ @previous = @current
244
+ end
245
+
246
+ # Allows you to set bar frame
247
+ # @return [Integer] current bar frame
248
+ def set (count)
249
+ if count < 0 || count > @total
250
+ raise "invalid count: #{count} (total: #{@total})"
251
+ end
252
+ @current = count
253
+ show_if_needed
254
+ @previous = @current
255
+ end
256
+
257
+ # Returns string representation of this object
258
+ def inspect
259
+ "#<ProgressBar:#{@current}/#{@total}>"
260
+ end
261
+ end
262
+
263
+ # Same as progress bar but this counts the progress backwards from 100% to 0
264
+ class ReversedProgressBar < ProgressBar
265
+ # Calculates the percentage
266
+ def do_percentage
267
+ 100 - super
268
+ end
269
+ end
270
+ end