redisk 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -20,4 +20,5 @@ pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
22
  dump.rdb
23
- redis-test.pid
23
+ redis-test.pid
24
+ tmp
data/HISTORY ADDED
@@ -0,0 +1,14 @@
1
+ === 0.2.0 [2009-12-22]
2
+
3
+ * Almost complete support for both line and byte operations on Redisk::IO
4
+ * New special extensions to the base IO class:
5
+ * .from_file and .to_file for writing/reading to disk
6
+ * .unlink for deleting contents
7
+ * .all lists the IO's created by Redisk::IO
8
+ * New examples folder
9
+
10
+ === 0.1.0
11
+
12
+ * Initial Release.
13
+ * Basic support for line operations in Redisk::IO
14
+ * Redisk::Logger
data/README.rdoc CHANGED
@@ -41,6 +41,24 @@ By default, Redisk uses the Redis on localhost:6379, but you can change that by
41
41
 
42
42
  Redisk.redis = 'myhost:myport'
43
43
 
44
+ Check out the small but growing list of examples in examples/
45
+
46
+ == INSTALL (NOW!)
47
+
48
+ Proudly tested and working on Ruby 1.8.6, 1.8.7, and 1.9.1
49
+
50
+ Gems are on gemcutter:
51
+
52
+ gem install redisk
53
+
54
+ Dependencies:
55
+
56
+ redis running somewhere
57
+
58
+ gems:
59
+ redis
60
+ redis-namespace
61
+
44
62
  == Note on Patches/Pull Requests
45
63
 
46
64
  * Fork the project.
data/examples/rails.rb ADDED
@@ -0,0 +1,4 @@
1
+ # You could put this in a Rails environment
2
+
3
+ # Set the logger to log to redis and truncate it at 10,000 lines
4
+ config.logger = Redisk::Logger.new("#{Rails.env}.log", :truncate => 10 * 1000)
data/examples/yajl.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'yajl'
3
+ require 'redisk'
4
+
5
+ hash = {'something' => 'for nothing', 'and_the_rest' => 'for free', 'i' => {'want' => {'my' => 'mtv'}}}
6
+
7
+ io_name = 'test.json'
8
+ Redisk::IO.unlink(io_name)
9
+
10
+ puts 'The hash:'
11
+ puts hash.inspect
12
+
13
+ puts 'write the hash as json to redis'
14
+ io = Redisk::IO.new(io_name)
15
+ Yajl::Encoder.encode(hash, io)
16
+
17
+ puts 'read it back out'
18
+ io.rewind
19
+ puts io.read.inspect
20
+
21
+ io.rewind
22
+
23
+ puts 'parse it back to ruby'
24
+ puts Yajl::Parser.parse(io).inspect
data/lib/redisk/io.rb CHANGED
@@ -6,16 +6,24 @@ module Redisk
6
6
 
7
7
  class NotImplementedError < RuntimeError; end
8
8
  class EOFError < ::EOFError; end
9
+ class IOError < ::IOError; end
9
10
 
10
11
  attr_reader :name, :mode, :_
11
12
 
12
- def initialize(name, mode = 'rw')
13
- @name = name
14
- @mode = mode # we're going to just ignore this for now
15
- @buffer = nil
16
- @sync = false
17
- @size = 0
18
- @lineno = 0
13
+ def initialize(name, mode = 'r')
14
+ @name = name
15
+ @mode = mode # we're going to just ignore this for now
16
+ @read_open = true
17
+ @write_open = true
18
+ @write_buffer = nil
19
+ @read_buffer = nil
20
+ @sync = false
21
+ @pos = 0
22
+ @lineno = 0
23
+ @size = stat.size > 0 ? stat.size : true_size
24
+ # add io to the list of ios
25
+ redis.sadd dir, name
26
+ rewind
19
27
  end
20
28
  alias :for_fd :initialize
21
29
 
@@ -26,7 +34,19 @@ module Redisk
26
34
  def list_key
27
35
  self.class.list_key(name)
28
36
  end
37
+
38
+ def self.all
39
+ redis.smembers dir
40
+ end
29
41
 
42
+ def self.dir
43
+ "__ios__"
44
+ end
45
+
46
+ def dir
47
+ self.class.dir
48
+ end
49
+
30
50
  # Executes the block for every line in the named I/O port, where lines are
31
51
  # separated by sep_string.
32
52
  #
@@ -38,8 +58,9 @@ module Redisk
38
58
  # GOT This is line three
39
59
  # GOT And so on...
40
60
  def self.foreach(name, &block)
41
- readlines(name).each(&block)
42
- nil
61
+ io = new(name)
62
+ io.each_line(&block)
63
+ io.close
43
64
  end
44
65
 
45
66
  # With no associated block, open is a synonym for IO::new. If the optional
@@ -48,7 +69,9 @@ module Redisk
48
69
  # instance, IO::open returns the value of the block.
49
70
  def self.open(name, mode = 'r')
50
71
  io = new(name, mode)
51
- block_given? ? yield(io) : io
72
+ returned = block_given? ? yield(io) : io
73
+ io.close
74
+ returned
52
75
  end
53
76
 
54
77
  # IO.pipe → array
@@ -92,12 +115,21 @@ module Redisk
92
115
  # IO.read("testfile", 20) #=> "This is line one\nThi"
93
116
  # IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
94
117
  def self.read(name, length = nil, offset = nil)
118
+ io = new(name)
119
+ io.seek(offset) if offset
120
+ returned = io.read(length)
121
+ io.close
122
+ returned
123
+ end
124
+
125
+ # Works similarly to IO.read, but operates on lines instead of bytes
126
+ def self.read_lines(name, length = nil, offset = nil)
95
127
  start_i = offset || 0
96
128
  end_i = length ? start_i + (length - 1) : -1
97
129
  values = redis.lrange(list_key(name), start_i, end_i)
98
- values.join("\n")
130
+ values.join
99
131
  end
100
-
132
+
101
133
  # Reads the entire file specified by name as individual lines, and returns
102
134
  # those lines in an array. Lines are separated by sep_string.
103
135
  #
@@ -125,6 +157,31 @@ module Redisk
125
157
  raise NotImplementedError, ".sysopen is not implemented"
126
158
  end
127
159
 
160
+ # Removes all references to the io at name
161
+ def self.unlink(name)
162
+ redis.keys("#{name}:*").each do |key|
163
+ redis.del key.gsub('redisk:','')
164
+ end
165
+ redis.srem dir, name
166
+ nil
167
+ end
168
+
169
+ # Reads the contents of file into the IO.
170
+ # If file is not a File its taken as a path and passed to File.open
171
+ def self.from_file(name, file)
172
+ io = new(name)
173
+ io.from_file(file)
174
+ io
175
+ end
176
+
177
+ # Writes the contents of IO into file.
178
+ # If file is not a File its taken as a path and passed to File.open
179
+ def self.to_file(name, file)
180
+ io = new(name)
181
+ io.to_file(file)
182
+ io
183
+ end
184
+
128
185
  # String Output—Writes obj to ios. obj will be converted to a string using
129
186
  # to_s.
130
187
  #
@@ -133,10 +190,10 @@ module Redisk
133
190
  #
134
191
  # Hello world!
135
192
  def <<(text)
136
- @buffer ||= ''
137
- @buffer << text
193
+ @write_buffer ||= ''
194
+ @write_buffer << text
138
195
  flush if sync
139
- @buffer
196
+ @write_buffer
140
197
  end
141
198
 
142
199
  # ios.binmode => ios
@@ -154,7 +211,9 @@ module Redisk
154
211
  #
155
212
  # If ios is opened by IO.popen, close sets $?.
156
213
  def close
157
-
214
+ flush
215
+ close_read
216
+ close_write
158
217
  end
159
218
 
160
219
  # ios.close_read => nil
@@ -170,7 +229,8 @@ module Redisk
170
229
  # prog.rb:3:in `readlines': not opened for reading (IOError)
171
230
  # from prog.rb:3
172
231
  def close_read
173
-
232
+ @read_open = false
233
+ nil
174
234
  end
175
235
 
176
236
  # ios.close_write => nil
@@ -187,7 +247,8 @@ module Redisk
187
247
  # from prog.rb:3:in `print'
188
248
  # from prog.rb:3
189
249
  def close_write
190
-
250
+ @write_open = false
251
+ nil
191
252
  end
192
253
 
193
254
  # ios.closed? => true or false
@@ -202,8 +263,8 @@ module Redisk
202
263
  # f.closed? #=> false
203
264
  # f.close_read #=> nil
204
265
  # f.closed? #=> true
205
- def closed
206
-
266
+ def closed?
267
+ !(@write_open || @read_open)
207
268
  end
208
269
 
209
270
  # ios.each(sep_string=$/) {|line| block } => ios
@@ -238,7 +299,11 @@ module Redisk
238
299
  # f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
239
300
  # checksum #=> 12
240
301
  def each_byte
241
-
302
+ rewind
303
+ while !eof?
304
+ yield getc
305
+ end
306
+ self
242
307
  end
243
308
 
244
309
  # ios.eof => true or false
@@ -266,7 +331,7 @@ module Redisk
266
331
  # Note that IO#eof? reads data to a input buffer. So IO#sysread doesn‘t
267
332
  # work with IO#eof?.
268
333
  def eof
269
- lineno >= length
334
+ lineno >= length || pos >= size
270
335
  end
271
336
  alias :eof? :eof
272
337
 
@@ -302,13 +367,13 @@ module Redisk
302
367
  #
303
368
  # no newline
304
369
  def flush
305
- if @buffer
306
- redis.rpush list_key, @buffer
307
- @size += @buffer.length
370
+ if @write_buffer && @write_buffer != ''
371
+ redis.rpush list_key, @write_buffer
372
+ @size += @write_buffer.length
308
373
  stat.write_attribute(:size, @size)
309
374
  stat.write_attribute(:mtime, Time.now)
310
375
  end
311
- @buffer = nil
376
+ @write_buffer = nil
312
377
  end
313
378
 
314
379
  # ios.fsync => 0 or nil
@@ -318,6 +383,31 @@ module Redisk
318
383
  # from Ruby‘s buffers, but doesn‘t not guarantee that the underlying
319
384
  # operating system actually writes it to disk.
320
385
  def fsync
386
+ false
387
+ end
388
+
389
+ # Reads the contents of file into the IO.
390
+ # If file is not a File its taken as a path and passed to File.open
391
+ # Returns the IO
392
+ def from_file(file)
393
+ file = File.open(file, 'r') if !file.is_a?(File)
394
+ file.each_line do |l|
395
+ write l
396
+ end
397
+ file.close
398
+ self
399
+ end
400
+
401
+ # Writes the contents of IO into file.
402
+ # If file is not a File its taken as a path and passed to File.open
403
+ # Returns the IO
404
+ def to_file(file)
405
+ file = File.open(file, 'w') if !file.is_a?(File)
406
+ each_line do |l|
407
+ file.write l
408
+ end
409
+ file.close
410
+ self
321
411
  end
322
412
 
323
413
  # ios.getc => fixnum or nil
@@ -328,6 +418,7 @@ module Redisk
328
418
  # f.getc #=> 84
329
419
  # f.getc #=> 104
330
420
  def getc
421
+ read(1).to_s.ord
331
422
  end
332
423
 
333
424
  # ios.gets(sep_string=$/) => string or nil
@@ -342,11 +433,14 @@ module Redisk
342
433
  # File.new("testfile").gets #=> "This is line one\n"
343
434
  # $_ #=> "This is line one\n"
344
435
  def gets
436
+ check_stream_open!(:read)
345
437
  flush
438
+ return nil if eof?
346
439
  val = redis.lrange(list_key, lineno, lineno + 1)
347
440
  if val = val.first
348
441
  self.lineno += 1
349
442
  $_ = @_ = val
443
+ @pos += val.length
350
444
  val
351
445
  end
352
446
  end
@@ -387,6 +481,10 @@ module Redisk
387
481
  @size
388
482
  end
389
483
 
484
+ def true_size
485
+ readlines.join.length
486
+ end
487
+
390
488
  # ios.lineno => integer
391
489
  # Returns the current line number in ios. The stream must be opened for
392
490
  # reading. lineno counts the number of times gets is called, rather than
@@ -416,7 +514,15 @@ module Redisk
416
514
  # f.gets #=> "This is line two\n"
417
515
  # $. # lineno of last read #=> 1001
418
516
  def lineno=(num)
419
- @lineno = num
517
+ @lineno = num.to_i
518
+ end
519
+
520
+ def open?(stream = nil)
521
+ if stream
522
+ instance_variable_get("@#{stream}_open")
523
+ else
524
+ @write_open && @read_open
525
+ end
420
526
  end
421
527
 
422
528
  # ios.pid => fixnum
@@ -434,7 +540,7 @@ module Redisk
434
540
  # In child, pid is 26209
435
541
  # In parent, child pid is 26209
436
542
  def pid
437
-
543
+ Process.pid
438
544
  end
439
545
 
440
546
  # ios.pos => integer
@@ -446,7 +552,7 @@ module Redisk
446
552
  # f.gets #=> "This is line one\n"
447
553
  # f.pos #=> 17
448
554
  def pos
449
-
555
+ @pos
450
556
  end
451
557
  alias :tell :pos
452
558
 
@@ -457,7 +563,13 @@ module Redisk
457
563
  # f.pos = 17
458
564
  # f.gets #=> "This is line two\n"
459
565
  def pos=(num)
460
-
566
+ current_pos = @pos
567
+ if num < current_pos
568
+ @pos = 0
569
+ else
570
+ num -= current_pos
571
+ end
572
+ read(num)
461
573
  end
462
574
 
463
575
  # ios.print() => nil
@@ -497,7 +609,7 @@ module Redisk
497
609
  #
498
610
  # AA
499
611
  def putc(obj)
500
-
612
+ self << obj.is_a?(Fixnum) ? obj : obj.to_s[0]
501
613
  end
502
614
 
503
615
  # ios.puts(obj, ...) => nil
@@ -516,8 +628,11 @@ module Redisk
516
628
  # test
517
629
  def puts(*args)
518
630
  args.empty? ?
519
- write('') :
520
- args.each {|a| write(a) }
631
+ write("\n") :
632
+ args.each {|a|
633
+ a += "\n" if a !~ /\n$/
634
+ write(a)
635
+ }
521
636
  nil
522
637
  end
523
638
 
@@ -532,8 +647,30 @@ module Redisk
532
647
  #
533
648
  # f = File.new("testfile")
534
649
  # f.read(16) #=> "This is line one"
535
- def read
536
-
650
+ def read(length = nil, buffer = nil)
651
+ check_stream_open!(:read)
652
+ if eof
653
+ length ? nil : ""
654
+ else
655
+ if length
656
+ @read_buffer ||= ""
657
+ fetched = false
658
+ while @read_buffer.length < length && !eof?
659
+ @read_buffer << gets.to_s
660
+ fetched = true
661
+ end
662
+ result = @read_buffer[0...length]
663
+ @read_buffer = @read_buffer[length..-1] || ""
664
+ if fetched
665
+ @pos -= @read_buffer.length
666
+ else
667
+ @pos += result.length
668
+ end
669
+ else
670
+ result = readlines.join
671
+ end
672
+ buffer ? buffer.replace(buffer + result) : result
673
+ end
537
674
  end
538
675
 
539
676
  # ios.read_nonblock(maxlen) => string
@@ -566,7 +703,14 @@ module Redisk
566
703
  # read data is obtainable via its data method.
567
704
  #
568
705
  def readbytes(n)
569
-
706
+ result = read(n)
707
+ if result && result.length < n
708
+ raise TruncatedDataError, result
709
+ elsif result.nil?
710
+ raise EOFError, "You have reached the end of the IO stream"
711
+ else
712
+ result
713
+ end
570
714
  end
571
715
 
572
716
  # ios.readchar => fixnum
@@ -595,6 +739,7 @@ module Redisk
595
739
  # f = File.new("testfile")
596
740
  # f.readlines[0] #=> "This is line one\n"
597
741
  def readlines
742
+ check_stream_open!(:read)
598
743
  self.class.readlines(name)
599
744
  end
600
745
 
@@ -678,6 +823,7 @@ module Redisk
678
823
  # f.readline #=> "This is line one\n"
679
824
  def rewind
680
825
  self.lineno = 0
826
+ self.pos = 0
681
827
  end
682
828
 
683
829
  # scanf(str,&b)
@@ -727,6 +873,19 @@ module Redisk
727
873
  # f.seek(-13, IO::SEEK_END) #=> 0
728
874
  # f.readline #=> "And so on...\n"
729
875
  def seek(offset, whence = SEEK_SET)
876
+ case whence
877
+ when SEEK_SET
878
+ self.pos = offset
879
+ when SEEK_END
880
+ self.pos = size + offset
881
+ when SEEK_CUR
882
+ self.pos += offset
883
+ end
884
+ 0
885
+ end
886
+
887
+ # works just like seek, but seeks by lineno instead of pos
888
+ def seek_lines(offset, whence = SEEK_SET)
730
889
  case whence
731
890
  when SEEK_SET
732
891
  self.lineno = offset
@@ -815,6 +974,7 @@ module Redisk
815
974
  else
816
975
  redis.ltrim list_key, -size, -1
817
976
  end
977
+ stat.write_attribute(:size, @size = true_size)
818
978
  length
819
979
  end
820
980
 
@@ -829,10 +989,20 @@ module Redisk
829
989
  # c = f.getc #=> 84
830
990
  # f.ungetc(c) #=> nil
831
991
  # f.getc #=> 84
832
- def ungetc(int)
833
-
992
+ def ungetc(integer)
993
+ check_stream_open!(:write)
994
+ char = ("" << integer)
995
+ self << char
996
+ nil
834
997
  end
835
998
 
999
+ # Removes all references to the IO and closes it for reading and writing
1000
+ def unlink
1001
+ close
1002
+ self.class.unlink(name)
1003
+ end
1004
+ alias :delete :unlink
1005
+
836
1006
  # ios.write(string) => integer
837
1007
  # Writes the given string to ios. The stream must be opened for writing.
838
1008
  # If the argument is not a string, it will be converted to a string using
@@ -845,8 +1015,9 @@ module Redisk
845
1015
  # This is a test
846
1016
  # That was 15 bytes of data
847
1017
  def write(string)
1018
+ check_stream_open!(:write)
848
1019
  string = string.to_s
849
- @buffer = string
1020
+ self << string
850
1021
  flush
851
1022
  string.length
852
1023
  end
@@ -863,5 +1034,10 @@ module Redisk
863
1034
  def write_nonblock(string)
864
1035
  end
865
1036
 
1037
+ private
1038
+ def check_stream_open!(stream = :read)
1039
+ raise(IOError, "#{self} is not open for #{stream}ing") unless open?(stream)
1040
+ end
1041
+
866
1042
  end
867
1043
  end
data/lib/redisk.rb CHANGED
@@ -6,7 +6,7 @@ require 'redisk/io'
6
6
  require 'redisk/logger'
7
7
 
8
8
  module Redisk
9
- VERSION = '0.1.0'
9
+ VERSION = '0.2.0'
10
10
 
11
11
  extend self
12
12
 
@@ -33,5 +33,22 @@ module Redisk
33
33
  self.redis
34
34
  end
35
35
 
36
+ def io(*args)
37
+ Redisk::IO.new(*args)
38
+ end
39
+
40
+ def logger(*args)
41
+ Redisk::Logger.new(*args)
42
+ end
43
+
36
44
  end
37
45
 
46
+ class String
47
+
48
+ if !method_defined?(:ord)
49
+ def ord
50
+ self[0]
51
+ end
52
+ end
53
+
54
+ end
data/redisk.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{redisk}
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Aaron Quint"]
12
- s.date = %q{2009-12-17}
12
+ s.date = %q{2009-12-22}
13
13
  s.description = %q{Redisk includes Redisk::IO which is ~ Ruby's stdlib IO. It can be used with stdlib's Logger to log directly to redis}
14
14
  s.email = %q{aaron@quirkey.com}
15
15
  s.extra_rdoc_files = [
@@ -19,9 +19,12 @@ Gem::Specification.new do |s|
19
19
  s.files = [
20
20
  ".document",
21
21
  ".gitignore",
22
+ "HISTORY",
22
23
  "LICENSE",
23
24
  "README.rdoc",
24
25
  "Rakefile",
26
+ "examples/rails.rb",
27
+ "examples/yajl.rb",
25
28
  "lib/redisk.rb",
26
29
  "lib/redisk/helper.rb",
27
30
  "lib/redisk/io.rb",
@@ -45,7 +48,9 @@ Gem::Specification.new do |s|
45
48
  "spec/redisk_io_spec.rb",
46
49
  "spec/redisk_logger_spec.rb",
47
50
  "spec/redisk_stat_spec.rb",
48
- "spec/spec_helper.rb"
51
+ "spec/spec_helper.rb",
52
+ "examples/rails.rb",
53
+ "examples/yajl.rb"
49
54
  ]
50
55
 
51
56
  if s.respond_to? :specification_version then
@@ -2,6 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe Redisk::IO do
4
4
  before do
5
+ FileUtils.mkdir_p('tmp')
5
6
  # load a file into an IO object
6
7
  @io_name = 'rails.log'
7
8
  @key = Redisk::IO.list_key(@io_name)
@@ -14,7 +15,9 @@ describe Redisk::IO do
14
15
  end
15
16
 
16
17
  after do
17
- Redisk.redis.del @key
18
+ Redisk.redis.keys(@key.gsub(':_list', '*')).each do |key|
19
+ Redisk.redis.del key.gsub('redisk:', '')
20
+ end
18
21
  end
19
22
 
20
23
  describe 'new' do
@@ -29,6 +32,15 @@ describe Redisk::IO do
29
32
  it 'stores the name of the key' do
30
33
  @io.name.should == @io_name
31
34
  end
35
+
36
+ it 'should be open' do
37
+ @io.closed?.should == false
38
+ end
39
+
40
+ it 'should add to the list of ios' do
41
+ Redisk::IO.all.should include(@io_name)
42
+ end
43
+
32
44
  end
33
45
 
34
46
  describe 'foreach' do
@@ -45,6 +57,45 @@ describe Redisk::IO do
45
57
 
46
58
  end
47
59
 
60
+ describe 'from_file' do
61
+ before(:each) do
62
+ Redisk::IO.unlink('dump_test.log')
63
+ File.open('tmp/dump_test.log', 'w+') {|f| f << "This is a file" }
64
+ end
65
+
66
+ it 'should write into io at name from file' do
67
+ @io = Redisk::IO.from_file('dump_test.log', 'tmp/dump_test.log')
68
+ @io.rewind
69
+ @io.gets.should == "This is a file"
70
+ end
71
+
72
+ it 'should write into io at name from File' do
73
+ @io = Redisk::IO.from_file('dump_test.log', File.new('tmp/dump_test.log'))
74
+ @io.rewind
75
+ @io.gets.should == "This is a file"
76
+ end
77
+
78
+ end
79
+
80
+ describe 'to_file' do
81
+ before(:each) do
82
+ Redisk::IO.unlink('dump_test.log')
83
+ File.unlink('tmp/dump_test.log')
84
+ Redisk::IO.open('dump_test.log') {|io| io << 'This is an IO' }
85
+ end
86
+
87
+ it 'should write into file from io' do
88
+ Redisk::IO.to_file('dump_test.log', 'tmp/dump_test.log')
89
+ File.read('tmp/dump_test.log').should == 'This is an IO'
90
+ end
91
+
92
+ it 'should write into File from io' do
93
+ Redisk::IO.to_file('dump_test.log', File.open('tmp/dump_test.log', 'w'))
94
+ File.read('tmp/dump_test.log').should == 'This is an IO'
95
+ end
96
+
97
+ end
98
+
48
99
  describe 'open' do
49
100
 
50
101
  it 'should return an IO object if no block is given' do
@@ -68,15 +119,32 @@ describe Redisk::IO do
68
119
  describe 'read' do
69
120
 
70
121
  it 'should return the entire contents without arguments' do
71
- Redisk::IO.read(@io_name).should == @file_as_array.join("\n")
122
+ Redisk::IO.read(@io_name).should == @file_as_array.join("")
123
+ end
124
+
125
+ it 'should return the first [length] bytes' do
126
+ Redisk::IO.read(@io_name, 2).should == @file_as_array[0][0..1]
127
+ end
128
+
129
+ it 'should return [length] contents starting at [offset]' do
130
+ Redisk::IO.read(@io_name, 2, 2).should == @file_as_array[0][2..3]
131
+ end
132
+
133
+ end
134
+
135
+
136
+ describe 'read_lines' do
137
+
138
+ it 'should return the entire contents without arguments' do
139
+ Redisk::IO.read_lines(@io_name).should == @file_as_array.join("")
72
140
  end
73
141
 
74
142
  it 'should return the first [length] contents' do
75
- Redisk::IO.read(@io_name, 2).should == @file_as_array[0..1].join("\n")
143
+ Redisk::IO.read_lines(@io_name, 2).should == @file_as_array[0..1].join("")
76
144
  end
77
145
 
78
146
  it 'should return [length] contents starting at [offset]' do
79
- Redisk::IO.read(@io_name, 2, 2).should == @file_as_array[2..3].join("\n")
147
+ Redisk::IO.read_lines(@io_name, 2, 2).should == @file_as_array[2..3].join("")
80
148
  end
81
149
 
82
150
  end
@@ -99,7 +167,7 @@ describe Redisk::IO do
99
167
  it 'should append a line to the io' do
100
168
  @io << 'whu'
101
169
  @io.lineno = 100
102
- @io.gets.should == 'whu'
170
+ @io.gets.should == "whu"
103
171
  end
104
172
 
105
173
  it 'should return the text' do
@@ -109,10 +177,56 @@ describe Redisk::IO do
109
177
  it 'should be able to chain' do
110
178
  @io << 'whu ' << 'zuh'
111
179
  @io.lineno = 100
112
- @io.gets.should == 'whu zuh'
180
+ @io.gets.should == "whu zuh"
113
181
  end
114
182
 
115
183
  end
184
+
185
+ describe '#close_read' do
186
+
187
+ it 'should close the io for reading' do
188
+ @io.close_read
189
+ lambda {
190
+ @io.gets
191
+ }.should raise_error(IOError)
192
+ end
193
+
194
+ end
195
+
196
+ describe '#close_write' do
197
+ it 'should close the io for writing' do
198
+ @io.close_write
199
+ lambda {
200
+ @io.puts
201
+ }.should raise_error(IOError)
202
+ end
203
+
204
+ end
205
+
206
+ describe '#close' do
207
+
208
+ it 'should close for reading and writing' do
209
+ @io.close
210
+ lambda {
211
+ @io.puts
212
+ }.should raise_error(IOError)
213
+ lambda {
214
+ @io.gets
215
+ }.should raise_error(IOError)
216
+ end
217
+
218
+ end
219
+
220
+ describe '#closed?' do
221
+
222
+ it 'should only return true if both streams are closed' do
223
+ @io.close_read
224
+ @io.closed?.should == false
225
+ @io.close_write
226
+ @io.closed?.should == true
227
+ end
228
+
229
+ end
116
230
 
117
231
  describe '#each' do
118
232
 
@@ -136,7 +250,29 @@ describe Redisk::IO do
136
250
  end
137
251
 
138
252
  end
139
-
253
+
254
+ describe '#each_byte' do
255
+
256
+ it 'should yield each byte as a fixnum to a block' do
257
+ i = 0
258
+ all_bytes = @file_as_array.join('')
259
+ @io.each_byte {|b|
260
+ b.should be_kind_of(Fixnum)
261
+ b.should == all_bytes[i].ord
262
+ i+=1
263
+ }
264
+ end
265
+
266
+ it 'should advance the pos of the io' do
267
+ i = 0
268
+ @io.each_byte {|b|
269
+ i+=1
270
+ @io.pos.should == i
271
+ }
272
+ end
273
+
274
+ end
275
+
140
276
  describe '#eof' do
141
277
 
142
278
  it 'should return false if lineno is not the end of the file' do
@@ -150,6 +286,28 @@ describe Redisk::IO do
150
286
 
151
287
  end
152
288
 
289
+ describe '#getc' do
290
+
291
+ it 'should get the next byte from the file as a fixnum' do
292
+ val = @io.getc
293
+ val.should be_kind_of(Fixnum)
294
+ val.should == @file_as_array[0].ord
295
+ end
296
+
297
+ it 'should increment the pos of the io' do
298
+ @io.getc
299
+ @io.pos.should == 1
300
+ @io.getc
301
+ @io.pos.should == 2
302
+ end
303
+
304
+ it 'should get the next line if necessary' do
305
+ @io.pos = @file_as_array[0].length + 1
306
+ @io.getc.should == @file_as_array[1][0].ord
307
+ end
308
+
309
+ end
310
+
153
311
  describe '#gets' do
154
312
 
155
313
  it 'should return the next line from the io' do
@@ -185,12 +343,35 @@ describe Redisk::IO do
185
343
  @io.gets.should == @file_as_array[50]
186
344
  end
187
345
  end
346
+
347
+ describe '#pos' do
348
+
349
+ it 'should return the current pos' do
350
+ @io.pos.should == 0
351
+ end
352
+
353
+ end
354
+
355
+ describe '#pos=' do
356
+
357
+ it 'should set the pos' do
358
+ @io.pos = 5
359
+ @io.pos.should == 5
360
+ @io.getc.should == @file_as_array[0][5].ord
361
+ end
362
+
363
+ it 'should set the lineno based on the pos' do
364
+ @io.pos = @file_as_array[0].length + 2
365
+ @io.lineno.should == 2
366
+ end
367
+
368
+ end
188
369
 
189
370
  describe '#print' do
190
371
 
191
372
  it 'should append arguments into a string and write to io' do
192
373
  @io.print('My ', 'name ', 'is ', 'redisk')
193
- line = Redisk::IO.read(@io_name, 1, 100)
374
+ line = Redisk::IO.read_lines(@io_name, 1, 100)
194
375
  line.should == 'My name is redisk'
195
376
  end
196
377
 
@@ -201,7 +382,7 @@ describe Redisk::IO do
201
382
  it 'should write the contents of $_ if no arguments are provided' do
202
383
  @io.gets
203
384
  @io.print
204
- line = Redisk::IO.read(@io_name, 1, 100)
385
+ line = Redisk::IO.read_lines(@io_name, 1, 100)
205
386
  line.should == @file_as_array[0]
206
387
  end
207
388
  end
@@ -210,7 +391,7 @@ describe Redisk::IO do
210
391
 
211
392
  it 'should run the arguments through sprintf and print to the io' do
212
393
  @io.printf('My name is %s', 'redisk')
213
- line = Redisk::IO.read(@io_name, 1, 100)
394
+ line = Redisk::IO.read_lines(@io_name, 1, 100)
214
395
  line.should == 'My name is redisk'
215
396
  end
216
397
 
@@ -221,19 +402,68 @@ describe Redisk::IO do
221
402
  it 'should write each argument to the io' do
222
403
  @io.puts('1', '2', '3')
223
404
  @io.lineno = 100
224
- @io.gets.should == '1'
225
- @io.gets.should == '2'
226
- @io.gets.should == '3'
405
+ @io.gets.should == "1\n"
406
+ @io.gets.should == "2\n"
407
+ @io.gets.should == "3\n"
227
408
  end
228
409
 
229
410
  it 'should write a blank string if no argument is passed' do
230
411
  @io.puts
231
412
  @io.lineno = 100
232
- @io.gets.should == ''
413
+ @io.gets.should == "\n"
233
414
  end
234
415
 
235
416
  end
236
417
 
418
+ describe '#read' do
419
+
420
+ it 'should read to the end of the file if [length] is ommited' do
421
+ @io.read.should == @file_as_array.join("")
422
+ end
423
+
424
+ it 'should read into the [buffer] if a buffer is passed' do
425
+ string = "new string\n"
426
+ @io.read(nil, string)
427
+ string.should == "new string\n" + @file_as_array.join("")
428
+ end
429
+
430
+ it 'should read [length] bytes from the IO' do
431
+ val = @io.read(20)
432
+ val.length.should == 20
433
+ end
434
+
435
+ it 'should return nil if [length] is passed at the eof' do
436
+ @io.pos = 1000000
437
+ @io.eof?.should == true
438
+ @io.read(5).should == nil
439
+ end
440
+
441
+ it 'should return "" if no [length] is passed at the eof' do
442
+ @io.pos = 1000000
443
+ @io.eof?.should == true
444
+ @io.read(nil).should == ""
445
+ end
446
+
447
+ end
448
+
449
+ describe '#readbytes' do
450
+
451
+ it 'should read [n] bytes from the io' do
452
+ val = @io.readbytes(10)
453
+ val.length.should == 10
454
+ val.should == @file_as_array.join("")[0...10]
455
+ end
456
+
457
+ it 'should raise EOFError if the data is nil' do
458
+ @io.each_byte {|b| b }
459
+ @io.eof?.should == true
460
+ lambda {
461
+ @io.readbytes(10)
462
+ }.should raise_error(EOFError)
463
+ end
464
+
465
+ end
466
+
237
467
  describe '#readline' do
238
468
 
239
469
  it 'should read the next line with gets' do
@@ -270,26 +500,26 @@ describe Redisk::IO do
270
500
 
271
501
  describe '#seek' do
272
502
 
273
- it 'should set the lineno to the absolute location' do
503
+ it 'should set the pos to the absolute location' do
274
504
  @io.seek(10)
275
- @io.lineno.should == 10
505
+ @io.pos.should == 10
276
506
  end
277
507
 
278
- it 'should set the lineno to the absolute location with SEEK_SET' do
508
+ it 'should set the pos to the absolute location with SEEK_SET' do
279
509
  @io.seek(15, IO::SEEK_SET)
280
- @io.lineno.should == 15
510
+ @io.pos.should == 15
281
511
  end
282
512
 
283
- it 'should set the lineno to the location relative to the end with SEEK_END' do
513
+ it 'should set the pos to the location relative to the end with SEEK_END' do
284
514
  @io.seek(-5, IO::SEEK_END)
285
- @io.lineno.should == 95
515
+ @io.pos.should == @file_as_array.join.length - 5
286
516
  end
287
517
 
288
- it 'should set the lineno to an offset position from the current line with SEEK_CUR' do
289
- @io.lineno = 5
290
- @io.lineno.should == 5
518
+ it 'should set the pos to an offset position from the current line with SEEK_CUR' do
519
+ @io.pos = 5
520
+ @io.pos.should == 5
291
521
  @io.seek(5, IO::SEEK_CUR)
292
- @io.lineno.should == 10
522
+ @io.pos.should == 10
293
523
  end
294
524
 
295
525
  end
@@ -300,7 +530,7 @@ describe Redisk::IO do
300
530
  @stat = @io.stat
301
531
  @stat.should be_instance_of(Redisk::Stat)
302
532
  @stat.atime.should be_instance_of(Time)
303
- @stat.size.should == 0
533
+ @stat.size.should be_instance_of(Fixnum)
304
534
  end
305
535
 
306
536
  end
@@ -329,6 +559,42 @@ describe Redisk::IO do
329
559
 
330
560
  end
331
561
 
562
+ describe '#ungetc' do
563
+
564
+ it 'should put the string represented by a fixnum at the end of the io buffer' do
565
+ @io.ungetc 65
566
+ @io.flush
567
+ last_char = nil
568
+ @io.each_byte {|b| last_char = b }
569
+ last_char.should == 65
570
+ end
571
+
572
+ it 'should return nil' do
573
+ @io.ungetc(65).should == nil
574
+ end
575
+
576
+ end
577
+
578
+ describe '#unlink' do
579
+ before do
580
+ @io.unlink
581
+ end
582
+
583
+ it 'should delete all keys associated with the io' do
584
+ Redisk.redis.get(@key).should == nil
585
+ Redisk::Stat.new(@key).size.should == 0
586
+ end
587
+
588
+ it 'should close the stream' do
589
+ @io.closed?.should == true
590
+ end
591
+
592
+ it 'should remove the key from the list of ios' do
593
+ Redisk::IO.all.should_not include(@io_name)
594
+ end
595
+
596
+ end
597
+
332
598
  end
333
599
 
334
600
  describe 'As an interface for logger' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redisk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Quint
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-17 00:00:00 -05:00
12
+ date: 2009-12-22 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -54,9 +54,12 @@ extra_rdoc_files:
54
54
  files:
55
55
  - .document
56
56
  - .gitignore
57
+ - HISTORY
57
58
  - LICENSE
58
59
  - README.rdoc
59
60
  - Rakefile
61
+ - examples/rails.rb
62
+ - examples/yajl.rb
60
63
  - lib/redisk.rb
61
64
  - lib/redisk/helper.rb
62
65
  - lib/redisk/io.rb
@@ -103,3 +106,5 @@ test_files:
103
106
  - spec/redisk_logger_spec.rb
104
107
  - spec/redisk_stat_spec.rb
105
108
  - spec/spec_helper.rb
109
+ - examples/rails.rb
110
+ - examples/yajl.rb