[DRE-commits] [SCM] ruby-dbf.git branch, master, updated. debian/2.0.3-1-4-ge6394f0

Christopher Baines cbaines8 at gmail.com
Sat Jul 6 15:55:51 UTC 2013


The following commit has been merged in the master branch:
commit 00efc89048aa1994a1e62b75f9dd28020734a2a6
Author: Christopher Baines <cbaines8 at gmail.com>
Date:   Sat Jul 6 16:43:06 2013 +0100

    Imported Upstream version 2.0.5

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 731a80e..b4ab56e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 2.0.5
+  - use correct FoxPro memo block size
+
+# 2.0.4
+  - memo fields return nil if memo file is missing
+
 # 2.0.3
   - set encoding if table encoding is nil
 
@@ -38,7 +44,7 @@
 
 # 1.6.6
   - add binary data type support to ActiveRecord schema output
-  
+
 # 1.6.5
   - support for visual foxpro double (b) data type
 
diff --git a/Gemfile b/Gemfile
index 7e083bb..56d5169 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,2 +1,2 @@
 gemspec
-source :rubygems
+source 'https://rubygems.org'
diff --git a/Gemfile.lock b/Gemfile.lock
index 204d275..ac17d88 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,30 +1,29 @@
 PATH
   remote: .
   specs:
-    dbf (1.7.4)
+    dbf (2.0.4)
+      fastercsv (~> 1.5.4)
 
 GEM
-  remote: http://rubygems.org/
+  remote: https://rubygems.org/
   specs:
-    diff-lcs (1.1.3)
-    json (1.6.5)
-    rake (0.9.2.2)
-    rdoc (3.12)
-      json (~> 1.4)
-    rspec (2.8.0)
-      rspec-core (~> 2.8.0)
-      rspec-expectations (~> 2.8.0)
-      rspec-mocks (~> 2.8.0)
-    rspec-core (2.8.0)
-    rspec-expectations (2.8.0)
-      diff-lcs (~> 1.1.2)
-    rspec-mocks (2.8.0)
+    diff-lcs (1.2.4)
+    fastercsv (1.5.5)
+    rake (10.0.4)
+    rspec (2.13.0)
+      rspec-core (~> 2.13.0)
+      rspec-expectations (~> 2.13.0)
+      rspec-mocks (~> 2.13.0)
+    rspec-core (2.13.1)
+    rspec-expectations (2.13.0)
+      diff-lcs (>= 1.1.3, < 2.0)
+    rspec-mocks (2.13.1)
 
 PLATFORMS
+  java
   ruby
 
 DEPENDENCIES
   dbf!
-  rake (~> 0.9.2)
-  rdoc (~> 3.11)
-  rspec (~> 2.8.0)
+  rake (>= 0.9.2)
+  rspec (~> 2.13.0)
diff --git a/README.md b/README.md
index 189ee28..ac1dcce 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,8 @@
-# DBF [![Build Status](https://secure.travis-ci.org/infused/dbf.png)](http://travis-ci.org/infused/dbf)
+# DBF
+[![Build Status](https://secure.travis-ci.org/infused/dbf.png)](http://travis-ci.org/infused/dbf)
+[![Gem Version](https://badge.fury.io/rb/dbf.png)](http://badge.fury.io/rb/dbf)
+[![Code Climate](https://codeclimate.com/github/infused/dbf.png)](https://codeclimate.com/github/infused/dbf)
+[![Dependency Status](https://gemnasium.com/infused/dbf.png)](https://gemnasium.com/infused/dbf)
 
 DBF is a small fast library for reading dBase, xBase, Clipper and FoxPro
 database files
@@ -6,22 +10,22 @@ database files
 * Project page: <http://github.com/infused/dbf>
 * API Documentation: <http://rubydoc.info/github/infused/dbf/frames>
 * Report bugs: <http://github.com/infused/dbf/issues>
-* Questions: Email <mailto:keithm at infused.org> and put DBF somewhere in the 
+* Questions: Email <mailto:keithm at infused.org> and put DBF somewhere in the
   subject line
 
 ## Compatibility
 
 DBF is tested to work with the following versions of ruby:
 
-* MRI Ruby 1.8.6, 1.8.7, 1.9.1, 1.9.2 and 1.9.3
+* MRI Ruby 1.8.6, 1.8.7, 1.9.1, 1.9.2, 1.9.3, 2.0.0
 * JRuby 1.6.x, 1.7.x
-* REE 1.8.6, 1.8.7
-* Rubinius (1.8 mode)
+* REE 1.8.7
+* Rubinius (1.8 and 1.9 modes)
 
 ## Installation
-  
+
     gem install dbf
-  
+
 ## Basic Usage
 
 Open a DBF file:
@@ -35,11 +39,11 @@ Enumerate all records
       puts record.name
       puts record.email
     end
-    
+
 Find a single record
 
     widget = widgets.find(6)
-    
+
 Note that find() will return nil if the requested record has been deleted
 and not yet pruned from the database.
 
@@ -49,16 +53,16 @@ ways
     widget["SlotNumber"]   # original field name in dbf file
     widget['slot_number']  # underscored field name string
     widget[:slot_number]   # underscored field name symbol
-    
+
 Get a hash of all attributes. The keys are the original column names.
 
     widgets.attributes
     => {"Name" => "Thing1", "SlotNumber" => 1}
-  
+
 Search for records using a simple hash format. Multiple search criteria are
 ANDed. Use the block form if the resulting recordset could be large, otherwise
 all records will be loaded into memory.
-    
+
     # find all records with slot_number equal to s42
     widgets.find(:all, :slot_number => 's42') do |widget|
       # the record will be nil if deleted, but not yet pruned from the database
@@ -66,13 +70,13 @@ all records will be loaded into memory.
         puts widget.serial_number
       end
     end
-    
+
     # find the first record with slot_number equal to s42
     widgets.find :first, :slot_number => 's42'
-    
+
     # find record number 10
     widgets.find(10)
-  
+
 ## Migrating to ActiveRecord
 
 An example of migrating a DBF book table to ActiveRecord using a migration:
@@ -80,12 +84,12 @@ An example of migrating a DBF book table to ActiveRecord using a migration:
     require 'dbf'
 
     class Book < ActiveRecord::Base; end
-    
+
     class CreateBooks < ActiveRecord::Migration
       def self.up
         table = DBF::Table.new('db/dbf/books.dbf')
         eval(table.schema)
-        
+
         Book.reset_column_information
         table.each do |record|
           Book.create(:title => record.title, :author => record.author)
@@ -96,7 +100,7 @@ An example of migrating a DBF book table to ActiveRecord using a migration:
         drop_table :books
       end
     end
-  
+
 ## Command-line utility
 
 A small command-line utility called dbf is installed along with the gem.
@@ -107,16 +111,16 @@ A small command-line utility called dbf is installed along with the gem.
       -s = print summary information
       -a = create an ActiveRecord::Schema
       -c = create a csv file
-      
+
 Create an executable ActiveRecord schema:
-    
+
     dbf -a books.dbf > books_schema.rb
-    
+
 Dump all records to a CSV file:
 
     dbf -c books.dbf > books.csv
-      
-## dBase version support
+
+## dBase version compatibility
 
 The basic dBase data types are generally supported well. Support for the
 advanced data types in dbase V and FoxPro are still experimental or not
@@ -135,7 +139,7 @@ for a full list of supported column types.
 
 ## License
 
-Copyright (c) 2006-2012 Keith Morrison <keithm at infused.org>
+Copyright (c) 2006-2013 Keith Morrison <<keithm at infused.org>>
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
diff --git a/bin/dbf b/bin/dbf
index 9eea9a6..d3f9a39 100755
--- a/bin/dbf
+++ b/bin/dbf
@@ -1,6 +1,5 @@
 #!/usr/bin/env ruby -s
 
-require 'rubygems'
 require 'dbf'
 
 $a ||= false
@@ -23,15 +22,15 @@ else
     table = DBF::Table.new filename
     puts table.schema
   end
-  
+
   if $s
     table = DBF::Table.new filename
     puts
     puts "Database: #{filename}"
     puts "Type: (#{table.version}) #{table.version_description}"
-    puts "Memo File: #{table.has_memo_file? ? 'true' : false}"
+    puts "Memo File: #{table.has_memo_file? ? 'true' : 'false'}"
     puts "Records: #{table.record_count}"
-    
+
     puts "\nFields:"
     puts "Name             Type       Length     Decimal"
     puts "-" * 78
diff --git a/checksums.yaml.gz b/checksums.yaml.gz
new file mode 100644
index 0000000..3ac8c1a
Binary files /dev/null and b/checksums.yaml.gz differ
diff --git a/dbf.gemspec b/dbf.gemspec
index c6d7277..3dcae38 100644
--- a/dbf.gemspec
+++ b/dbf.gemspec
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
   s.homepage = 'http://github.com/infused/dbf'
   s.summary = 'Read xBase files'
   s.description = 'A small fast library for reading dBase, xBase, Clipper and FoxPro database files.'
-  
+
   s.executables = ['dbf']
   s.rdoc_options = ['--charset=UTF-8']
   s.extra_rdoc_files = ['README.md', 'CHANGELOG.md', 'MIT-LICENSE']
@@ -20,9 +20,9 @@ Gem::Specification.new do |s|
 
   s.required_rubygems_version = '>= 1.3.0'
   s.add_dependency 'fastercsv', '~> 1.5.4'
-  
-  s.add_development_dependency 'rspec', '~> 2.11.0'
-  s.add_development_dependency 'rake', '~> 0.9.2'
+
+  s.add_development_dependency 'rspec', '~> 2.13.0'
+  s.add_development_dependency 'rake', '>= 0.9.2'
 
   # if RUBY_VERSION.to_f >= 1.9
   #   s.add_development_dependency 'ruby-debug19'
diff --git a/lib/dbf/column/base.rb b/lib/dbf/column/base.rb
index 21f7c6b..b1a2a19 100644
--- a/lib/dbf/column/base.rb
+++ b/lib/dbf/column/base.rb
@@ -2,7 +2,7 @@ module DBF
   module Column
     class LengthError < StandardError; end
     class NameError < StandardError; end
-    
+
     class Base
       attr_reader :name, :type, :length, :decimal
 
@@ -32,7 +32,6 @@ module DBF
           when 'D' then decode_date(value)
           when 'T' then decode_datetime(value)
           when 'L' then boolean(value)
-          when 'B' then unpack_binary(value)
           when 'M' then decode_memo(value)
           else          encode_string(value.to_s).strip
         end
@@ -75,7 +74,7 @@ module DBF
         seconds = (milliseconds / 1000).to_i
         DateTime.jd(days, (seconds/3600).to_i, (seconds/60).to_i % 60, seconds % 60) rescue nil
       end
-      
+
       def decode_memo(value) #nodoc
         encode_string(value) if value
       end
@@ -88,9 +87,6 @@ module DBF
         value.unpack('V')[0]
       end
 
-      def unpack_binary(value) #nodoc
-      end
-
       def boolean(value) #nodoc
         value.strip =~ /^(y|t)$/i ? true : false
       end
diff --git a/lib/dbf/memo/base.rb b/lib/dbf/memo/base.rb
index 3fb539c..8c20961 100644
--- a/lib/dbf/memo/base.rb
+++ b/lib/dbf/memo/base.rb
@@ -2,31 +2,32 @@ module DBF
   module Memo
     class Base
       BLOCK_HEADER_SIZE = 8
-    
+      BLOCK_SIZE = 512
+
       def self.open(filename, version)
         self.new File.open(filename, 'rb'), version
       end
-    
+
       def initialize(data, version)
         @data, @version = data, version
       end
-    
+
       def get(start_block)
         if start_block > 0
-          build_memo start_block 
+          build_memo start_block
         end
       end
-    
+
       def close
         @data.close && @data.closed?
       end
-      
+
       def closed?
         @data.closed?
       end
-    
+
       private
-    
+
       def offset(start_block) #nodoc
         start_block * block_size
       end
@@ -38,9 +39,9 @@ module DBF
       def block_content_size #nodoc
         @block_content_size ||= block_size - BLOCK_HEADER_SIZE
       end
-    
-      def block_size #nodoc
-        512
+
+      def block_size
+        BLOCK_SIZE
       end
     end
   end
diff --git a/lib/dbf/memo/dbase3.rb b/lib/dbf/memo/dbase3.rb
index 4780b19..2ec3982 100644
--- a/lib/dbf/memo/dbase3.rb
+++ b/lib/dbf/memo/dbase3.rb
@@ -5,9 +5,9 @@ module DBF
         @data.seek offset(start_block)
         memo_string = ""
         begin
-          block = @data.read(block_size).gsub(/(\000|\032)/, '')
+          block = @data.read(BLOCK_SIZE).gsub(/(\000|\032)/, '')
           memo_string << block
-        end until block.size < block_size
+        end until block.size < BLOCK_SIZE
         memo_string
       end
     end
diff --git a/lib/dbf/memo/foxpro.rb b/lib/dbf/memo/foxpro.rb
index d1a03ee..20acbaf 100644
--- a/lib/dbf/memo/foxpro.rb
+++ b/lib/dbf/memo/foxpro.rb
@@ -2,13 +2,13 @@ module DBF
   module Memo
     class Foxpro < Base
       FPT_HEADER_SIZE = 512
-      
+
       def build_memo(start_block) #nodoc
         @data.seek offset(start_block)
-        
+
         memo_type, memo_size, memo_string = @data.read(block_size).unpack("NNa*")
         return nil unless memo_type == 1 && memo_size > 0
-        
+
         if memo_size > block_content_size
           memo_string << @data.read(content_size(memo_size))
         else
@@ -16,9 +16,9 @@ module DBF
         end
         memo_string
       end
-      
+
       private
-      
+
       def block_size #nodoc
         @block_size ||= begin
           @data.rewind
diff --git a/lib/dbf/record.rb b/lib/dbf/record.rb
index b886af4..2224a93 100644
--- a/lib/dbf/record.rb
+++ b/lib/dbf/record.rb
@@ -1,8 +1,8 @@
 module DBF
-  # An instance of DBF::Record represents a row in the DBF file 
+  # An instance of DBF::Record represents a row in the DBF file
   class Record
     # Initialize a new DBF::Record
-    # 
+    #
     # @data [String, StringIO] data
     # @columns [Column]
     # @version [String]
@@ -11,7 +11,7 @@ module DBF
       @data = StringIO.new(data)
       @columns, @version, @memo = columns, version, memo
     end
-    
+
     # Equality
     #
     # @param [DBF::Record] other
@@ -19,14 +19,14 @@ module DBF
     def ==(other)
       other.respond_to?(:attributes) && other.attributes == attributes
     end
-    
+
     # Maps a row to an array of values
-    # 
+    #
     # @return [Array]
     def to_a
       @columns.map {|column| attributes[column.name]}
     end
-    
+
     # Do all search parameters match?
     #
     # @param [Hash] options
@@ -44,15 +44,18 @@ module DBF
         attributes[@columns[index].name]
       end
     end
-    
+
     # @return [Hash]
     def attributes
       @attributes ||= Hash[@columns.map {|column| [column.name, init_attribute(column)]}]
     end
-    
+
     def respond_to?(method, *args)
-      return true if column_names.include?(method.to_s)
-      super
+      if column_names.include?(method.to_s)
+        true
+      else
+        super
+      end
     end
 
     def method_missing(method, *args)
@@ -68,27 +71,25 @@ module DBF
     def column_names
       @column_names ||= @columns.map {|column| column.underscored_name}
     end
-    
+
     def init_attribute(column) #nodoc
       value = if column.memo?
-        @memo.get get_memo_start_block(column)
+        @memo && @memo.get(memo_start_block(column))
       else
         unpack_data(column)
       end
-      column.type_cast value
+      column.type_cast(value)
     end
-   
-    def get_memo_start_block(column) #nodoc
-      if %w(30 31).include?(@version)
-        @data.read(column.length).unpack('V').first
-      else
-        unpack_data(column).to_i
-      end
+
+    def memo_start_block(column) #nodoc
+      format = 'V' if %w(30 31).include?(@version)
+      unpack_data(column, format).to_i
     end
 
-    def unpack_data(column) #nodoc
-      @data.read(column.length).unpack("a#{column.length}").first
+    def unpack_data(column, format=nil) #nodoc
+      format ||= "a#{column.length}"
+      @data.read(column.length).unpack(format).first
     end
-    
+
   end
 end
diff --git a/lib/dbf/table.rb b/lib/dbf/table.rb
index 475ba39..924bb82 100644
--- a/lib/dbf/table.rb
+++ b/lib/dbf/table.rb
@@ -15,15 +15,18 @@ module DBF
       "07" => "Visual Objects 1.x",
       "30" => "Visual FoxPro",
       "31" => "Visual FoxPro with AutoIncrement field",
+      "43" => "dBASE IV SQL table files, no memo",
+      "63" => "dBASE IV SQL system files, no memo",
       "7b" => "dBase IV with memo file",
       "83" => "dBase III with memo file",
       "87" => "Visual Objects 1.x with memo file",
       "8b" => "dBase IV with memo file",
       "8e" => "dBase IV with SQL table",
+      "cb" => "dBASE IV SQL table files, with memo",
       "f5" => "FoxPro with memo file",
       "fb" => "FoxPro without memo file"
     }
-    
+
     FOXPRO_VERSIONS = {
       "30" => "Visual FoxPro",
       "31" => "Visual FoxPro with AutoIncrement field",
@@ -58,11 +61,11 @@ module DBF
     # @param [optional String, Encoding] encoding Name of the encoding or an Encoding object
     def initialize(data, memo = nil, encoding = nil)
       @data = open_data(data)
-      get_header_info
-      @encoding = encoding || @encoding
+      @version, @record_count, @header_length, @record_length, @encoding_key, @encoding = get_header_info
+      @encoding = encoding if encoding
       @memo = open_memo(data, memo)
     end
-    
+
     # @return [TrueClass, FalseClass]
     def has_memo_file?
       !!@memo
@@ -75,7 +78,7 @@ module DBF
       @data.close
       @memo && @memo.close
     end
-    
+
     # @return [TrueClass, FalseClass]
     def closed?
       if @memo
@@ -84,7 +87,7 @@ module DBF
         @data.closed?
       end
     end
-    
+
     # @return String
     def filename
       File.basename @data.path
@@ -213,32 +216,28 @@ module DBF
         columns
       end
     end
-    
+
     def supports_encoding?
       String.new.respond_to?(:encoding)
     end
-    
+
     def supports_iconv?
       require 'iconv'
       true
     rescue
       false
     end
-    
+
     def foxpro?
       FOXPRO_VERSIONS.keys.include? @version
     end
 
     private
-    
+
     def column_class #nodoc
-      @column_class ||= if foxpro?
-        Column::Foxpro
-      else
-        Column::Dbase
-      end
+      @column_class ||= foxpro? ? Column::Foxpro : Column::Dbase
     end
-    
+
     def memo_class #nodoc
       @memo_class ||= if foxpro?
         Memo::Foxpro
@@ -250,7 +249,7 @@ module DBF
         end
       end
     end
-    
+
     def column_count #nodoc
       @column_count ||= ((@header_length - DBF_HEADER_SIZE + 1) / DBF_HEADER_SIZE).to_i
     end
@@ -265,15 +264,19 @@ module DBF
       elsif memo
         memo_class.open(memo, version)
       elsif !data.is_a? StringIO
-        dirname = File.dirname(data)
-        basename = File.basename(data, '.*')
-        files = Dir.glob("#{dirname}/#{basename}*.{fpt,FPT,dbt,DBT}")
+        files = Dir.glob(memo_search_path(data))
         files.any? ? memo_class.open(files.first, version) : nil
       else
         nil
       end
     end
 
+    def memo_search_path(io) #nodoc
+      dirname = File.dirname(io)
+      basename = File.basename(io, '.*')
+      "#{dirname}/#{basename}*.{fpt,FPT,dbt,DBT}"
+    end
+
     def find_all(options) #nodoc
       map do |record|
         if record && record.match?(options)
@@ -293,10 +296,11 @@ module DBF
 
     def get_header_info #nodoc
       @data.rewind
-      @version, @record_count, @header_length, @record_length, @encoding_key = read_header
-      @encoding = ENCODINGS[@encoding_key] if supports_encoding? || supports_iconv?
+      version, record_count, header_length, record_length, encoding_key = read_header
+      encoding = ENCODINGS[encoding_key] if supports_encoding? || supports_iconv?
+      [version, record_count, header_length, record_length, encoding_key, encoding]
     end
-    
+
     def read_header #nodoc
       @data.read(DBF_HEADER_SIZE).unpack("H2 x3 V v2 x17H2")
     end
diff --git a/lib/dbf/version.rb b/lib/dbf/version.rb
index 8dcfa79..15ca560 100644
--- a/lib/dbf/version.rb
+++ b/lib/dbf/version.rb
@@ -1,3 +1,3 @@
 module DBF
-  VERSION = '2.0.3'
+  VERSION = '2.0.5'
 end
\ No newline at end of file
diff --git a/metadata.yml b/metadata.yml
index f6ad3ac..83d7b0a 100644
--- a/metadata.yml
+++ b/metadata.yml
@@ -1,20 +1,18 @@
 --- !ruby/object:Gem::Specification
 name: dbf
 version: !ruby/object:Gem::Version
-  version: 2.0.3
-  prerelease: 
+  version: 2.0.5
 platform: ruby
 authors:
 - Keith Morrison
 autorequire: 
 bindir: bin
 cert_chain: []
-date: 2012-11-28 00:00:00.000000000 Z
+date: 2013-07-02 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: fastercsv
   requirement: !ruby/object:Gem::Requirement
-    none: false
     requirements:
     - - ~>
       - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
   type: :runtime
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
-    none: false
     requirements:
     - - ~>
       - !ruby/object:Gem::Version
@@ -30,33 +27,29 @@ dependencies:
 - !ruby/object:Gem::Dependency
   name: rspec
   requirement: !ruby/object:Gem::Requirement
-    none: false
     requirements:
     - - ~>
       - !ruby/object:Gem::Version
-        version: 2.11.0
+        version: 2.13.0
   type: :development
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
-    none: false
     requirements:
     - - ~>
       - !ruby/object:Gem::Version
-        version: 2.11.0
+        version: 2.13.0
 - !ruby/object:Gem::Dependency
   name: rake
   requirement: !ruby/object:Gem::Requirement
-    none: false
     requirements:
-    - - ~>
+    - - '>='
       - !ruby/object:Gem::Version
         version: 0.9.2
   type: :development
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
-    none: false
     requirements:
-    - - ~>
+    - - '>='
       - !ruby/object:Gem::Version
         version: 0.9.2
 description: A small fast library for reading dBase, xBase, Clipper and FoxPro database
@@ -101,6 +94,7 @@ files:
 - spec/fixtures/dbase_31.dbf
 - spec/fixtures/dbase_83.dbf
 - spec/fixtures/dbase_83.dbt
+- spec/fixtures/dbase_83_missing_memo.dbf
 - spec/fixtures/dbase_83_schema.txt
 - spec/fixtures/dbase_8b.dbf
 - spec/fixtures/dbase_8b.dbt
@@ -111,28 +105,27 @@ files:
 - dbf.gemspec
 homepage: http://github.com/infused/dbf
 licenses: []
+metadata: {}
 post_install_message: 
 rdoc_options:
 - --charset=UTF-8
 require_paths:
 - lib
 required_ruby_version: !ruby/object:Gem::Requirement
-  none: false
   requirements:
-  - - ! '>='
+  - - '>='
     - !ruby/object:Gem::Version
       version: '0'
 required_rubygems_version: !ruby/object:Gem::Requirement
-  none: false
   requirements:
-  - - ! '>='
+  - - '>='
     - !ruby/object:Gem::Version
       version: 1.3.0
 requirements: []
 rubyforge_project: 
-rubygems_version: 1.8.24
+rubygems_version: 2.0.3
 signing_key: 
-specification_version: 3
+specification_version: 4
 summary: Read xBase files
 test_files:
 - spec/dbf/column_spec.rb
diff --git a/spec/dbf/column_spec.rb b/spec/dbf/column_spec.rb
index 585b12d..7b655b4 100644
--- a/spec/dbf/column_spec.rb
+++ b/spec/dbf/column_spec.rb
@@ -1,235 +1,245 @@
+# encoding: ascii-8bit
+
 require "spec_helper"
 
 describe DBF::Column::Dbase do
-  
+
   context "when initialized" do
     let(:column) { DBF::Column::Dbase.new "ColumnName", "N", 1, 0, "30" }
-    
-    it "sets the #name accessor" do
-      column.name.should == "ColumnName"
+
+    it "sets :name accessor" do
+      expect(column.name).to eq "ColumnName"
     end
-    
-    it "sets the #type accessor" do
-      column.type.should == "N"
+
+    it "sets :type accessor" do
+      expect(column.type).to eq "N"
     end
-    
+
     it "sets the #length accessor" do
-      column.length.should == 1
+      expect(column.length).to eq 1
     end
-    
+
     it "sets the #decimal accessor" do
-      column.decimal.should == 0
+      expect(column.decimal).to eq 0
     end
-    
+
     describe 'with length of 0' do
       it 'raises DBF::Column::LengthError' do
         expect { DBF::Column::Dbase.new "ColumnName", "N", 0, 0, "30" }.to raise_error(DBF::Column::LengthError)
       end
     end
-    
+
     describe 'with length less than 0' do
       it 'raises DBF::Column::LengthError' do
         expect { DBF::Column::Dbase.new "ColumnName", "N", -1, 0, "30" }.to raise_error(DBF::Column::LengthError)
       end
     end
-    
+
     describe 'with empty column name' do
       it 'raises DBF::Column::NameError' do
         expect { DBF::Column::Dbase.new "\xFF\xFC", "N", 1, 0, "30" }.to raise_error(DBF::Column::NameError)
       end
     end
   end
-  
+
   context '#type_cast' do
     context 'with type N (number)' do
       context 'and 0 decimals' do
         it 'casts value to Fixnum' do
           value = '135'
           column = DBF::Column::Dbase.new "ColumnName", "N", 3, 0, "30"
-          column.type_cast(value).should be_a(Fixnum)
-          column.type_cast(value).should == 135
+          expect(column.type_cast(value)).to be_a(Fixnum)
+          expect(column.type_cast(value)).to eq 135
         end
       end
-      
+
       context 'and more than 0 decimals' do
         it 'casts value to Float' do
           value = '13.5'
           column = DBF::Column::Dbase.new "ColumnName", "N", 2, 1, "30"
-          column.type_cast(value).should be_a(Float)
-          column.type_cast(value).should == 13.5
+          expect(column.type_cast(value)).to be_a(Float)
+          expect(column.type_cast(value)).to eq 13.5
         end
       end
     end
-    
+
     context 'with type F (float)' do
       it 'casts value to Float' do
         value = '135'
         column = DBF::Column::Dbase.new "ColumnName", "F", 3, 0, "30"
-        column.type_cast(value).should be_a(Float)
-        column.type_cast(value).should == 135.0
+        expect(column.type_cast(value)).to be_a(Float)
+        expect(column.type_cast(value)).to eq 135.0
       end
     end
-    
+
     context 'with type I (integer)' do
       it "casts value to Fixnum" do
         value = "\203\171\001\000"
         column = DBF::Column::Dbase.new "ColumnName", "I", 3, 0, "30"
-        column.type_cast(value).should == 96643
+        expect(column.type_cast(value)).to eq 96643
       end
     end
-    
+
     context 'with type L (logical/boolean)' do
       let(:column) { DBF::Column::Dbase.new "ColumnName", "L", 1, 0, "30" }
-      
+
       it "casts 'y' to true" do
-        column.type_cast('y').should == true
+        expect(column.type_cast('y')).to eq true
       end
-      
+
       it "casts 't' to true" do
-        column.type_cast('t').should == true
+        expect(column.type_cast('t')).to eq true
       end
-      
+
       it "casts value other than 't' or 'y' to false" do
-        column.type_cast('n').should == false
+        expect(column.type_cast('n')).to eq false
       end
     end
-    
+
     context 'with type T (datetime)' do
       let(:column) { DBF::Column::Dbase.new "ColumnName", "T", 16, 0, "30" }
-      
+
       context 'with valid datetime' do
         it "casts to DateTime" do
-          column.type_cast("Nl%\000\300Z\252\003").should == DateTime.parse("2002-10-10T17:04:56+00:00")
+          expect(column.type_cast("Nl%\000\300Z\252\003")).to eq DateTime.parse("2002-10-10T17:04:56+00:00")
         end
       end
-      
+
       if ruby_supports_mathn?
         context 'when requiring mathn' do
           it "casts to DateTime" do
-            lambda {
+            with_mathn = lambda do
               require 'mathn'
               column.type_cast("Nl%\000\300Z\252\003")
-            }.call.should == DateTime.parse("2002-10-10T17:04:56+00:00")
+            end
+            expect(with_mathn.call).to eq DateTime.parse("2002-10-10T17:04:56+00:00")
           end
         end
       end
-      
+
       context 'with invalid datetime' do
         it "casts to nil" do
-          column.type_cast("Nl%\000\000A\000\999").should be_nil
+          expect(column.type_cast("Nl%\000\000A\000\999")).to be_nil
         end
       end
     end
-    
+
     context 'with type D (date)' do
       let(:column) { DBF::Column::Dbase.new "ColumnName", "D", 8, 0, "30" }
-      
+
       context 'with valid date' do
         it "casts to Date" do
-          column.type_cast("20050712").should == Date.new(2005,7,12)
+          expect(column.type_cast("20050712")).to eq Date.new(2005,7,12)
         end
       end
-      
+
       context 'with invalid date' do
         it "casts to nil" do
-          column.type_cast("0").should be_nil
+          expect(column.type_cast("0")).to be_nil
         end
       end
     end
-    
+
     context 'with type M (memo)' do
       it "casts to string" do
         column = DBF::Column::Dbase.new "ColumnName", "M", 3, 0, "30"
-        column.type_cast('abc').should be_a(String)
+        expect(column.type_cast('abc')).to be_a(String)
+      end
+
+      it 'casts nil to nil' do
+        column = DBF::Column::Dbase.new "ColumnName", "M", 3, 0, "30"
+        expect(column.type_cast(nil)).to be_nil
       end
     end
   end
-  
+
   context 'with type Y (currency)' do
     let(:column) { DBF::Column::Dbase.new "ColumnName", "Y", 8, 4, "31" }
-    
+
     it 'casts to float' do
-      column.type_cast(" \xBF\x02\x00\x00\x00\x00\x00").should == 18.0
+      expect(column.type_cast(" \xBF\x02\x00\x00\x00\x00\x00")).to eq 18.0
     end
   end
-  
+
   context "#schema_definition" do
     context 'with type N (number)' do
       it "outputs an integer column" do
         column = DBF::Column::Dbase.new "ColumnName", "N", 1, 0, "30"
-        column.schema_definition.should == "\"column_name\", :integer\n"
+        expect(column.schema_definition).to eq "\"column_name\", :integer\n"
       end
     end
-    
+
     context "with type B (binary)" do
       context "with Foxpro dbf" do
         context "when decimal is greater than 0" do
           it "outputs an float column" do
             column = DBF::Column::Dbase.new "ColumnName", "B", 1, 2, "f5"
-            column.schema_definition.should == "\"column_name\", :float\n"
+            expect(column.schema_definition).to eq "\"column_name\", :float\n"
           end
         end
-        
+
         context "when decimal is 0" do
-          column = DBF::Column::Dbase.new "ColumnName", "B", 1, 0, "f5"
-          column.schema_definition.should == "\"column_name\", :integer\n"
+          it "outputs an integer column" do
+            column = DBF::Column::Dbase.new "ColumnName", "B", 1, 0, "f5"
+            expect(column.schema_definition).to eq "\"column_name\", :integer\n"
+          end
         end
       end
     end
-    
+
     it "defines a float colmn if type is (N)umber with more than 0 decimals" do
       column = DBF::Column::Dbase.new "ColumnName", "N", 1, 2, "30"
-      column.schema_definition.should == "\"column_name\", :float\n"
+      expect(column.schema_definition).to eq "\"column_name\", :float\n"
     end
-    
+
     it "defines a date column if type is (D)ate" do
       column = DBF::Column::Dbase.new "ColumnName", "D", 8, 0, "30"
-      column.schema_definition.should == "\"column_name\", :date\n"
+      expect(column.schema_definition).to eq "\"column_name\", :date\n"
     end
-    
+
     it "defines a datetime column if type is (D)ate" do
       column = DBF::Column::Dbase.new "ColumnName", "T", 16, 0, "30"
-      column.schema_definition.should == "\"column_name\", :datetime\n"
+      expect(column.schema_definition).to eq "\"column_name\", :datetime\n"
     end
-    
+
     it "defines a boolean column if type is (L)ogical" do
       column = DBF::Column::Dbase.new "ColumnName", "L", 1, 0, "30"
-      column.schema_definition.should == "\"column_name\", :boolean\n"
+      expect(column.schema_definition).to eq "\"column_name\", :boolean\n"
     end
-    
+
     it "defines a text column if type is (M)emo" do
       column = DBF::Column::Dbase.new "ColumnName", "M", 1, 0, "30"
-      column.schema_definition.should == "\"column_name\", :text\n"
+      expect(column.schema_definition).to eq "\"column_name\", :text\n"
     end
-    
+
     it "defines a string column with length for any other data types" do
       column = DBF::Column::Dbase.new "ColumnName", "X", 20, 0, "30"
-      column.schema_definition.should == "\"column_name\", :string, :limit => 20\n"
+      expect(column.schema_definition).to eq "\"column_name\", :string, :limit => 20\n"
     end
   end
-  
-  context "#name" do    
+
+  context "#name" do
     it "contains only ASCII characters" do
       column = DBF::Column::Dbase.new "--\x1F-\x68\x65\x6C\x6C\x6F world-\x80--", "N", 1, 0, "30"
-      column.name.should == "---hello world---"
+      expect(column.name).to eq "---hello world---"
     end
 
     it "is truncated at the null character" do
       column = DBF::Column::Dbase.new "--\x1F-\x68\x65\x6C\x6C\x6F \x00 world-\x80--", "N", 1, 0, "30"
-      column.name.should == "---hello "
+      expect(column.name).to eq "---hello "
     end
   end
-  
+
   context '#decode_date' do
     let(:column) { DBF::Column::Dbase.new "ColumnName", "N", 1, 0, "30" }
-    
+
     it 'is nil if value is blank' do
-      column.send(:decode_date, '').should be_nil
+      expect(column.send(:decode_date, '')).to be_nil
     end
-    
+
     it 'interperets spaces as zeros' do
-      column.send(:decode_date, '2010 715').should == Date.parse('20100715')
+      expect(column.send(:decode_date, '2010 715')).to eq Date.parse('20100715')
     end
   end
-  
+
 end
diff --git a/spec/dbf/file_formats_spec.rb b/spec/dbf/file_formats_spec.rb
index cc09a43..5f7c674 100644
--- a/spec/dbf/file_formats_spec.rb
+++ b/spec/dbf/file_formats_spec.rb
@@ -4,151 +4,155 @@ shared_examples_for 'DBF' do
   specify "sum of column lengths should equal record length specified in header plus one" do
     header_record_length = table.instance_eval {@record_length}
     sum_of_column_lengths = table.columns.inject(1) {|sum, column| sum += column.length}
-    
-    header_record_length.should == sum_of_column_lengths
+
+    expect(header_record_length).to eq sum_of_column_lengths
   end
 
   specify "records should be instances of DBF::Record" do
-    table.all? {|record| record.is_a?(DBF::Record)}.should be_true
+    expect(table.all? {|record| record.is_a?(DBF::Record)}).to be_true
   end
-  
+
   specify "record count should be the same as reported in the header" do
-    table.entries.size.should == table.record_count
+    expect(table.entries.size).to eq table.record_count
   end
-  
+
   specify "column names should not be blank" do
-    table.columns.all? {|column| !column.name.empty?}.should be_true
+    expect(table.columns.all? {|column| !column.name.empty?}).to be_true
   end
-  
+
   specify "column types should be valid" do
     valid_column_types = %w(C N L D M F B G P Y T I V X @ O + 0)
-    table.columns.all? {|column| valid_column_types.include?(column.type)}.should be_true
+    expect(table.columns.all? {|column| valid_column_types.include?(column.type)}).to be_true
   end
-  
+
   specify "column lengths should be instances of Fixnum" do
-    table.columns.all? {|column| column.length.is_a?(Fixnum)}.should be_true
+    expect(table.columns.all? {|column| column.length.is_a?(Fixnum)}).to be_true
   end
-  
+
   specify "column lengths should be larger than 0" do
-    table.columns.all? {|column| column.length > 0}.should be_true
+    expect(table.columns.all? {|column| column.length > 0}).to be_true
   end
-  
+
   specify "column decimals should be instances of Fixnum" do
-    table.columns.all? {|column| column.decimal.is_a?(Fixnum)}.should be_true
+    expect(table.columns.all? {|column| column.decimal.is_a?(Fixnum)}).to be_true
   end
 end
 
 shared_examples_for 'Foxpro DBF' do
   specify "columns should be instances of DBF::FoxproColumn" do
-    table.columns.all? {|column| column.is_a?(DBF::Column::Foxpro)}.should be_true
+    expect(table.columns.all? {|column| column.is_a?(DBF::Column::Foxpro)}).to be_true
   end
 end
 
 describe DBF, "of type 03 (dBase III without memo file)" do
   let(:table) { DBF::Table.new "#{DB_PATH}/dbase_03.dbf" }
-  
+
   it_should_behave_like "DBF"
-  
+
   it "should report the correct version number" do
-    table.version.should == "03"
+    expect(table.version).to eq "03"
   end
-  
+
   it "should report the correct version description" do
-    table.version_description.should == "dBase III without memo file"
+    expect(table.version_description).to eq "dBase III without memo file"
   end
-  
+
   it "should determine the number of records" do
-    table.record_count.should == 14
+    expect(table.record_count).to eq 14
   end
 end
 
 describe DBF, "of type 30 (Visual FoxPro)" do
   let(:table) { DBF::Table.new "#{DB_PATH}/dbase_30.dbf" }
-  
+
   it_should_behave_like "DBF"
-  
+
   it "should report the correct version number" do
-    table.version.should == "30"
+    expect(table.version).to eq "30"
   end
-  
+
   it "should report the correct version description" do
-    table.version_description.should == "Visual FoxPro"
+    expect(table.version_description).to eq "Visual FoxPro"
   end
 
   it "should determine the number of records" do
-    table.record_count.should == 34
+    expect(table.record_count).to eq 34
   end
 end
 
 describe DBF, "of type 31 (Visual FoxPro with AutoIncrement field)" do
   let(:table) { DBF::Table.new "#{DB_PATH}/dbase_31.dbf" }
-  
+
   it_should_behave_like "DBF"
-  
+
   it "should have a dBase version of 31" do
-    table.version.should == "31"
+    expect(table.version).to eq "31"
   end
-  
+
   it "should report the correct version description" do
-    table.version_description.should == "Visual FoxPro with AutoIncrement field"
+    expect(table.version_description).to eq "Visual FoxPro with AutoIncrement field"
   end
-  
+
   it "should determine the number of records" do
-    table.record_count.should == 77
+    expect(table.record_count).to eq 77
   end
 end
 
 describe DBF, "of type 83 (dBase III with memo file)" do
   let(:table) { DBF::Table.new "#{DB_PATH}/dbase_83.dbf" }
-  
+
   it_should_behave_like "DBF"
-  
+
   it "should report the correct version number" do
-    table.version.should == "83"
+    expect(table.version).to eq "83"
   end
-  
+
   it "should report the correct version description" do
-    table.version_description.should == "dBase III with memo file"
+    expect(table.version_description).to eq "dBase III with memo file"
   end
-  
+
   it "should determine the number of records" do
-    table.record_count.should == 67
+    expect(table.record_count).to eq 67
   end
 end
 
 describe DBF, "of type 8b (dBase IV with memo file)" do
   let(:table) { DBF::Table.new "#{DB_PATH}/dbase_8b.dbf" }
-  
+
   it_should_behave_like "DBF"
-  
+
   it "should report the correct version number" do
-    table.version.should == "8b"
+    expect(table.version).to eq "8b"
   end
-  
+
   it "should report the correct version description" do
-    table.version_description.should == "dBase IV with memo file"
+    expect(table.version_description).to eq "dBase IV with memo file"
   end
-  
+
   it "should determine the number of records" do
-    table.record_count.should == 10
+    expect(table.record_count).to eq 10
   end
 end
 
 describe DBF, "of type f5 (FoxPro with memo file)" do
   let(:table) { DBF::Table.new "#{DB_PATH}/dbase_f5.dbf" }
-  
+
   it_should_behave_like "DBF"
   it_should_behave_like "Foxpro DBF"
-  
+
   it "should report the correct version number" do
-    table.version.should == "f5"
+    expect(table.version).to eq "f5"
   end
-  
+
   it "should report the correct version description" do
-    table.version_description.should == "FoxPro with memo file"
+    expect(table.version_description).to eq "FoxPro with memo file"
   end
-  
+
   it "should determine the number of records" do
-    table.record_count.should == 975
+    expect(table.record_count).to eq 975
+  end
+
+  it "reads memo data" do
+    expect(table.record(3).obse).to match(/\Ajos.*pare\.\Z/m)
   end
 end
diff --git a/spec/dbf/record_spec.rb b/spec/dbf/record_spec.rb
index b24873a..2d0b51f 100644
--- a/spec/dbf/record_spec.rb
+++ b/spec/dbf/record_spec.rb
@@ -3,26 +3,34 @@ require "spec_helper"
 describe DBF::Record do
 
   describe '#to_a' do
+    let(:table) { DBF::Table.new "#{DB_PATH}/dbase_83.dbf" }
     it 'should return an ordered array of attribute values' do
-      table = DBF::Table.new "#{DB_PATH}/dbase_8b.dbf"
-
       record = table.record(0)
-      record.to_a.should == ["One", 1.0, Date.new(1970, 1, 1), true, 1.23456789012346, "First memo\r\n\037 \037 \037 \037 "]
+      expect(record.to_a).to eq [87, 2, 0, 0, 87, "1", "Assorted Petits Fours", "graphics/00000001/t_1.jpg", "graphics/00000001/1.jpg", 0.0, 0.0, "Our Original assortment...a little taste of heaven for everyone.  Let us\r\nselect a special assortment of our chocolate and pastel favorites for you.\r\nEach petit four is its own special hand decorated creation. Multi-layers of\r\nmoist cake with combinations of specialty fillings create memorable cake\r\nconfections. Varietes include; Luscious Lemon, Strawberry Hearts, White\r\nChocolate, Mocha Bean, Roasted Almond, Triple Chocolate, Chocolate Hazelnut,\r\nGrand Orange, Plum Squares, Milk chocolate squares, and Raspberry Blanc.", 5.51, true, true]
 
       record = table.record(9)
-      record.to_a.should == ["Ten records stored in this database", 10.0, nil, false, 0.1, nil]
+      expect(record.to_a).to eq [34, 1, 0, 0, 34, "AB01", "Apricot Brandy Fruitcake", "graphics/00000001/t_AB01.jpg", "graphics/00000001/AB01.jpg", 37.95, 37.95, "Once tasted you will understand why we won The\r\nBoston Herald's Fruitcake Taste-off. Judges liked its generous size,\r\nluscious appearance, moist texture and fruit to cake ratio ... commented one\r\njudge \"It's a lip Smacker!\" Our signature fruitcake is baked with carefully\r\nselected ingredients that will be savored until the last moist crumb is\r\ndevoured each golden slice is brimming with Australian glaced apricots,\r\ntoasted pecans, candied orange peel, and currants, folded gently into a\r\nbrandy butter batter and slowly baked to perfection and then generously\r\nimbibed with \"Holiday Spirits\". Presented in a gift tin.  (3lbs. 4oz)", 0.0, false, true]
+    end
+
+    describe 'with missing memo file' do
+      let(:table) { DBF::Table.new "#{DB_PATH}/dbase_83_missing_memo.dbf" }
+
+      it 'returns nil values for memo fields' do
+        record = table.record(0)
+        expect(record.to_a).to eq [87, 2, 0, 0, 87, "1", "Assorted Petits Fours", "graphics/00000001/t_1.jpg", "graphics/00000001/1.jpg", 0.0, 0.0, nil, 1.0, false, false]
+      end
     end
   end
 
-  describe '#==' do    
+  describe '#==' do
     let :record do
       table = DBF::Table.new "#{DB_PATH}/dbase_8b.dbf"
       table.record(9)
     end
-    
+
     describe 'when other does not have attributes' do
       it 'is false' do
-        (record == mock('other')).should be_false
+        expect((record == mock('other'))).to be_false
       end
     end
 
@@ -31,10 +39,10 @@ describe DBF::Record do
         attributes = {:x => 1, :y => 2}
         record.stub!(:attributes).and_return(attributes)
         other = mock('object', :attributes => attributes)
-        (record == other).should be_true
+        expect((record == other)).to be_true
       end
     end
-    
+
   end
 
   describe 'column accessors' do
@@ -42,16 +50,16 @@ describe DBF::Record do
     let(:record) { table.find(0) }
 
     it 'should have dynamic accessors for the columns' do
-      record.should respond_to(:character)
-      record.character.should == 'One'
-      record.float.should == 1.23456789012346
-      record.logical.should == true
+      expect(record).to respond_to(:character)
+      expect(record.character).to eq 'One'
+      expect(record.float).to eq 1.23456789012346
+      expect(record.logical).to eq true
     end
 
     it 'should not define accessor methods on the base class' do
       second_table = DBF::Table.new "#{DB_PATH}/dbase_03.dbf"
       second_record = second_table.find(0)
-      record.character.should == 'One'
+      expect(record.character).to eq 'One'
       expect { second_record.character }.to raise_error(NoMethodError)
     end
   end
@@ -63,8 +71,8 @@ describe DBF::Record do
       let(:record) { table.find(0) }
       it 'should automatically encodes to default system encoding' do
         if table.supports_encoding?
-          record.name.encoding.should == Encoding.default_external
-          record.name.encode("UTF-8").unpack("H4").should == ["d0b0"] # russian a
+          expect(record.name.encoding).to eq Encoding.default_external
+          expect(record.name.encode("UTF-8").unpack("H4")).to eq ["d0b0"] # russian a
         end
       end
     end
@@ -75,25 +83,25 @@ describe DBF::Record do
       let(:record) { table.find(0) }
       it 'should transcode from manually specified encoding to default system encoding' do
         if table.supports_encoding?
-          record.name.encoding.should == Encoding.default_external
-          record.name.encode("UTF-8").unpack("H4").should == ["d180"] # russian а encoded in cp1251 and read as if it was encoded in cp866
+          expect(record.name.encoding).to eq Encoding.default_external
+          expect(record.name.encode("UTF-8").unpack("H4")).to eq ["d180"] # russian а encoded in cp1251 and read as if it was encoded in cp866
         end
       end
     end
   end
-  
+
   describe '#attributes' do
     let(:table) { DBF::Table.new "#{DB_PATH}/dbase_8b.dbf"}
     let(:record) { table.find(0) }
-    
+
     it 'is a hash of attribute name/value pairs' do
-      record.attributes.should be_a(Hash)
-      record.attributes['CHARACTER'] == 'One'
+      expect(record.attributes).to be_a(Hash)
+      expect(record.attributes['CHARACTER']).to eq 'One'
     end
-    
+
     it 'has only original field names as keys' do
       original_field_names = %w(CHARACTER DATE FLOAT LOGICAL MEMO NUMERICAL)
-      record.attributes.keys.sort.should == original_field_names
+      expect(record.attributes.keys.sort).to eq original_field_names
     end
   end
 end
diff --git a/spec/dbf/table_spec.rb b/spec/dbf/table_spec.rb
index 4edd598..7954f4e 100644
--- a/spec/dbf/table_spec.rb
+++ b/spec/dbf/table_spec.rb
@@ -1,8 +1,8 @@
 require "spec_helper"
 
-describe DBF::Table do  
+describe DBF::Table do
   specify 'foxpro versions' do
-    DBF::Table::FOXPRO_VERSIONS.keys.sort.should == %w(30 31 f5 fb).sort
+    expect(DBF::Table::FOXPRO_VERSIONS.keys.sort).to eq %w(30 31 f5 fb).sort
   end
 
   describe '#initialize' do
@@ -25,42 +25,42 @@ describe DBF::Table do
       expect { DBF::Table.new data, memo }.to_not raise_error
     end
   end
-  
+
   context "when closed" do
     it "closes the data and memo files" do
       table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
       table.close
-      table.should be_closed
+      expect(table).to be_closed
     end
-    
+
     it "closes the data" do
       table = DBF::Table.new "#{DB_PATH}/dbase_30.dbf"
       table.close
-      table.should be_closed
+      expect(table).to be_closed
     end
   end
-  
+
   describe "#schema" do
     it "matches the test schema fixture" do
       table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
       control_schema = File.read("#{DB_PATH}/dbase_83_schema.txt")
-      table.schema.should == control_schema
+      expect(table.schema).to eq control_schema
     end
   end
-  
+
   describe '#to_csv' do
     let(:table) { DBF::Table.new "#{DB_PATH}/dbase_83.dbf" }
-    
+
     after do
       FileUtils.rm_f 'test.csv'
     end
-    
+
     describe 'when no path param passed' do
       it 'writes to STDOUT' do
         begin
           $stdout = StringIO.new
           table.to_csv
-          $stdout.string.should_not be_empty
+          expect($stdout.string).not_to be_empty
         ensure
           $stdout = STDOUT
         end
@@ -70,91 +70,91 @@ describe DBF::Table do
     describe 'when path param passed' do
       it 'creates a custom csv file' do
         table.to_csv('test.csv')
-        File.exists?('test.csv').should be_true
+        expect(File.exists?('test.csv')).to be_true
       end
     end
   end
-  
+
   describe "#record" do
     it "return nil for deleted records" do
       table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
       table.stub!(:deleted_record?).and_return(true)
-      table.record(5).should be_nil
+      expect(table.record(5)).to be_nil
     end
   end
-  
+
   describe "#current_record" do
     it "should return nil for deleted records" do
       table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
       table.stub!(:deleted_record?).and_return(true)
-      table.record(0).should be_nil
+      expect(table.record(0)).to be_nil
     end
   end
-  
+
   describe "#find" do
     let(:table) { DBF::Table.new "#{DB_PATH}/dbase_83.dbf" }
-    
+
     describe "with index" do
       it "returns the correct record" do
-        table.find(5).should == table.record(5)
+        expect(table.find(5)).to eq table.record(5)
       end
     end
-    
-    describe 'with array of indexes' do      
+
+    describe 'with array of indexes' do
       it "returns the correct records" do
-        table.find([1, 5, 10]).should == [table.record(1), table.record(5), table.record(10)]
+        expect(table.find([1, 5, 10])).to eq [table.record(1), table.record(5), table.record(10)]
       end
     end
-    
+
     describe "with :all" do
       it "accepts a block" do
         records = []
         table.find(:all, :weight => 0.0) do |record|
           records << record
         end
-        records.should == table.find(:all, :weight => 0.0)
+        expect(records).to eq table.find(:all, :weight => 0.0)
       end
 
       it "returns all records if options are empty" do
-        table.find(:all).should == table.to_a
+        expect(table.find(:all)).to eq table.to_a
       end
 
       it "returns matching records when used with options" do
-        table.find(:all, "WEIGHT" => 0.0).should == table.select {|r| r["weight"] == 0.0}
+        expect(table.find(:all, "WEIGHT" => 0.0)).to eq table.select {|r| r["weight"] == 0.0}
       end
 
       it "should AND multiple search terms" do
-        table.find(:all, "ID" => 30, "IMAGE" => "graphics/00000001/TBC01.jpg").should == []
+        expect(table.find(:all, "ID" => 30, "IMAGE" => "graphics/00000001/TBC01.jpg")).to eq []
       end
-      
+
       it "should match original column names" do
-        table.find(:all, "WEIGHT" => 0.0).should_not be_empty
+        expect(table.find(:all, "WEIGHT" => 0.0)).not_to be_empty
       end
-      
+
       it "matches symbolized column names" do
-        table.find(:all, :WEIGHT => 0.0).should_not be_empty
+        expect(table.find(:all, :WEIGHT => 0.0)).not_to be_empty
       end
-      
+
       it "matches downcased column names" do
-        table.find(:all, "weight" => 0.0).should_not be_empty
+        expect(table.find(:all, "weight" => 0.0)).not_to be_empty
       end
-      
+
       it "matches symbolized downcased column names" do
-        table.find(:all, :weight => 0.0).should_not be_empty
+        expect(table.find(:all, :weight => 0.0)).not_to be_empty
       end
     end
-    
+
     describe "with :first" do
       it "returns the first record if options are empty" do
-        table.find(:first).should == table.record(0)
+        expect(table.find(:first)).to eq table.record(0)
       end
 
       it "returns the first matching record when used with options" do
-        table.find(:first, "CODE" => "C").should == table.record(5)
+        expect(table.find(:first, "CODE" => "C")).to eq table.record(5)
       end
 
       it "ANDs multiple search terms" do
-        table.find(:first, "ID" => 30, "IMAGE" => "graphics/00000001/TBC01.jpg").should be_nil
+        expect(table.find(:first, "ID" => 30, "IMAGE" => "graphics/00000001/TBC01.jpg")).to be_nil
       end
     end
   end
@@ -162,22 +162,22 @@ describe DBF::Table do
   describe "filename" do
     it 'is dbase_03.dbf' do
       table = DBF::Table.new "#{DB_PATH}/dbase_03.dbf"
-      table.filename.should == "dbase_03.dbf"
+      expect(table.filename).to eq "dbase_03.dbf"
     end
   end
-  
+
   describe 'has_memo_file?' do
     describe 'without a memo file' do
       it 'is false' do
         table = DBF::Table.new "#{DB_PATH}/dbase_03.dbf"
-        table.has_memo_file?.should be_false
+        expect(table.has_memo_file?).to be_false
       end
     end
-    
+
     describe 'with a memo file' do
       it 'is true' do
-        table = DBF::Table.new "#{DB_PATH}/dbase_30.dbf" 
-        table.has_memo_file?.should be_true
+        table = DBF::Table.new "#{DB_PATH}/dbase_30.dbf"
+        expect(table.has_memo_file?).to be_true
       end
     end
   end
@@ -186,12 +186,12 @@ describe DBF::Table do
     let(:table) { DBF::Table.new "#{DB_PATH}/dbase_03.dbf" }
 
     it 'should have correct size' do
-      table.columns.size.should == 31
+      expect(table.columns.size).to eq 31
     end
 
     it 'should have correct names' do
-      table.columns.first.name.should == 'Point_ID'
-      table.columns[29].name.should == 'Easting'
+      expect(table.columns.first.name).to eq 'Point_ID'
+      expect(table.columns[29].name).to eq 'Easting'
     end
   end
 end
diff --git a/spec/fixtures/dbase_83.dbf b/spec/fixtures/dbase_83_missing_memo.dbf
similarity index 100%
copy from spec/fixtures/dbase_83.dbf
copy to spec/fixtures/dbase_83_missing_memo.dbf
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 7ff70dd..ddf9bc5 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,7 +1,8 @@
-$:.unshift(File.dirname(__FILE__) + '/../lib/')
 require 'dbf'
 require 'rspec'
 
+Encoding.default_external = "UTF-8" if defined?(Encoding)
+
 DB_PATH = File.dirname(__FILE__) + '/fixtures' unless defined?(DB_PATH)
 
 if RUBY_VERSION == "1.8.6"

-- 
ruby-dbf.git



More information about the Pkg-ruby-extras-commits mailing list