redisk 0.1.0 → 0.2.0

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/.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