rfilemaker 0.0.1 → 0.0.2

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/README.rdoc CHANGED
@@ -7,62 +7,64 @@ This library parses a Filemaker Pro FMPXMLRESULT type document, nothing more, no
7
7
  == Installation
8
8
 
9
9
  Easy, just use:
10
-
11
- gem install rfilemaker
12
-
10
+
11
+ gem install rfilemaker
12
+
13
13
  == Usage
14
14
 
15
15
  To parse a Filemaker Pro export file named 'export.xml', use:
16
16
 
17
- RFilemaker.parse('export.xml')
18
-
17
+ RFilemaker.parse('export.xml')
18
+
19
19
  This returns an array of hashes, each of which represent a row in your Filemaker database.
20
20
  Fields are automatically converted to their ruby types.
21
21
 
22
22
  For instance, parsing the following XML export:
23
23
 
24
- <FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
25
- <ERRORCODE>0</ERRORCODE>
26
- <PRODUCT BUILD="5/23/2002" NAME="FileMaker Pro"
27
- VERSION="7.0"/>
28
- <DATABASE DATEFORMAT="MM/dd/yy" LAYOUT="summary"
29
- NAME="Employees.fp7" RECORDS="23" TIMEFORMAT="hh:mm:ss"/>
30
- <METADATA>
31
- <FIELD EMPTYOK="NO" MAXREPEAT="1" NAME="First Name" TYPE="TEXT"/>
32
- <FIELD EMPTYOK="NO" MAXREPEAT="1" NAME="Last Name" TYPE="TEXT"/>
33
- <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="Department" TYPE="TEXT"/>
34
- </METADATA>
35
- <RESULTSET FOUND="2">
36
- <ROW MODID="47" RECORDID="34">
37
- <COL>
38
- <DATA>Joe</DATA>
39
- </COL>
40
- <COL>
41
- <DATA>Smith</DATA>
42
- </COL>
43
- <COL>
44
- <DATA>Engineering</DATA>
45
- </COL>
46
- </ROW>
47
- <ROW MODID="89" RECORDID="78">
48
- <COL>
49
- <DATA>Susan</DATA>
50
- </COL>
51
- <COL>
52
- <DATA>Jones</DATA>
53
- </COL>
54
- <COL>
55
- <DATA>Marketing</DATA>
56
- </COL>
57
- </ROW>
58
- </RESULTSET>
59
- </FMPXMLRESULT>
24
+ <FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
25
+ <ERRORCODE>0</ERRORCODE>
26
+ <PRODUCT BUILD="5/23/2002" NAME="FileMaker Pro"
27
+ VERSION="7.0"/>
28
+ <DATABASE DATEFORMAT="MM/dd/yy" LAYOUT="summary"
29
+ NAME="Employees.fp7" RECORDS="23" TIMEFORMAT="hh:mm:ss"/>
30
+ <METADATA>
31
+ <FIELD EMPTYOK="NO" MAXREPEAT="1" NAME="First Name" TYPE="TEXT"/>
32
+ <FIELD EMPTYOK="NO" MAXREPEAT="1" NAME="Last Name" TYPE="TEXT"/>
33
+ <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="Department" TYPE="TEXT"/>
34
+ </METADATA>
35
+ <RESULTSET FOUND="2">
36
+ <ROW MODID="47" RECORDID="34">
37
+ <COL>
38
+ <DATA>Joe</DATA>
39
+ </COL>
40
+ <COL>
41
+ <DATA>Smith</DATA>
42
+ </COL>
43
+ <COL>
44
+ <DATA>Engineering</DATA>
45
+ </COL>
46
+ </ROW>
47
+ <ROW MODID="89" RECORDID="78">
48
+ <COL>
49
+ <DATA>Susan</DATA>
50
+ </COL>
51
+ <COL>
52
+ <DATA>Jones</DATA>
53
+ </COL>
54
+ <COL>
55
+ <DATA>Marketing</DATA>
56
+ </COL>
57
+ </ROW>
58
+ </RESULTSET>
59
+ </FMPXMLRESULT>
60
60
 
61
61
  gives this Ruby hash:
62
62
 
63
- [{"Last Name"=>"Smith", "Department"=>"Engineering", "First Name"=>"Joe"},
64
- {"Last Name"=>"Jones", "Department"=>"Marketing", "First Name"=>"Susan"}]
65
-
63
+ [{"last name"=>"Smith", "department"=>"Engineering", "first name"=>"Joe"},
64
+ {"last name"=>"Jones", "department"=>"Marketing", "first name"=>"Susan"}]
65
+
66
+ The resulting hash is case-insensitive, so keys can be looked up in any given case.
67
+
66
68
  == Note on Patches/Pull Requests
67
69
 
68
70
  * Fork the project.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
data/lib/rfilemaker.rb CHANGED
@@ -1,6 +1,19 @@
1
1
  require 'nokogiri'
2
2
 
3
3
  module RFilemaker
4
+ class SpecialHash < Hash # :nodoc: all
5
+ def []=(key, value)
6
+ super(key.downcase, value)
7
+ end
8
+
9
+ def [](key)
10
+ super(key.to_s.downcase)
11
+ end
12
+ end
13
+
14
+ # Parse a FMPXMLRESULT string into an Array
15
+ #
16
+ # Each element in the Array is a Hash, representing a row in the imported XML
4
17
  def self.parse(string)
5
18
  doc = Nokogiri::XML.parse(string)
6
19
  ResultSet.new(doc)
@@ -1,6 +1,9 @@
1
1
  module RFilemaker
2
2
  class Field
3
- attr_reader :name, :type
3
+ # Name of the field
4
+ attr_reader :name
5
+ # Type of the field as symbol
6
+ attr_reader :type
4
7
 
5
8
  def initialize(xml, result_set)
6
9
  @name = xml['NAME']
@@ -8,7 +11,14 @@ module RFilemaker
8
11
  @empty_ok = xml['EMPTYOK'] == 'YES'
9
12
  @result_set = result_set
10
13
  end
11
-
14
+
15
+ # Coerce a value to the Ruby equivalent of the Filemaker Type
16
+ #
17
+ # * 'DATE' gets converted to Date
18
+ # * 'TIME' gets converted to DateTime
19
+ # * 'TIMESTAMP' gets converted to DateTime
20
+ # * 'NUMBER' gets converted to float or integer
21
+ # * everything else gets converted to a string
12
22
  def coerce(value)
13
23
  return nil if value.nil? || value == ''
14
24
 
@@ -1,14 +1,18 @@
1
1
  module RFilemaker
2
- class Record < Hash
3
- attr_reader :record_id, :mod_id
2
+ # Represents a Row in the Filemaker database, as a plain Hash
3
+ class Record < SpecialHash
4
+ # Record id from Filemaker
5
+ attr_reader :record_id
6
+
7
+ # Modification id from Filemaker
8
+ attr_reader :mod_id
4
9
 
5
10
  def initialize(row, fields)
6
- @row = row
7
- @record_id = @row.record_id
8
- @mod_id = @row.mod_id
11
+ @record_id = row[:record_id]
12
+ @mod_id = row[:mod_id]
9
13
 
10
14
  fields.each_with_index do |field, index|
11
- data = row.columns[index]
15
+ data = row[:columns][index]
12
16
 
13
17
  if data.is_a?(Array)
14
18
  self[field.name] = []
@@ -17,6 +21,8 @@ module RFilemaker
17
21
  self[field.name] = field.coerce(data)
18
22
  end
19
23
  end
24
+
25
+ freeze
20
26
  end
21
27
  end
22
28
  end
@@ -1,5 +1,6 @@
1
1
  module RFilemaker
2
2
  class ResultSet < Array
3
+ # Parse a Filemaker date format to something strptime understands
3
4
  def self.parse_date_format(string)
4
5
  string = string.gsub(/yyyy|yy/, '%y').gsub(/mm|m|MM|M/, '%m').gsub(/dd|d|DD|D/, '%d')
5
6
  string.gsub(/hh|h/, '%I').gsub(/kk|k/, '%H').gsub(/mm/, '%M').gsub(/ss/, '%S').gsub(/a/, '%p')
@@ -8,6 +9,8 @@ module RFilemaker
8
9
  attr_reader :fields, :rows
9
10
  attr_reader :date_format, :time_format
10
11
 
12
+ # Generates a new ResultSet (or plain Ruby Array) for the given XML document
13
+ # Items in the ResultSet are Hashes, representing rows in the Filemaker export
11
14
  def initialize(doc)
12
15
  @fields = extract_fields(doc)
13
16
  @rows = extract_rows(doc)
@@ -21,7 +24,7 @@ module RFilemaker
21
24
  end
22
25
  end
23
26
 
24
- private
27
+ private # :nodoc: all
25
28
  def extract_fields(doc)
26
29
  doc.css('METADATA FIELD').collect do |xml|
27
30
  Field.new(xml, self)
@@ -1,18 +1,15 @@
1
1
  module RFilemaker
2
- class Row
3
- attr_reader :record_id, :mod_id, :columns
4
-
2
+ class Row < Hash # :nodoc: all
5
3
  def initialize(xml)
6
- @record_id = xml['RECORDID'].to_i
7
- @mod_id = xml['MODID'].to_i
8
-
9
- @columns = []
10
- xml.css('COL').each do |col|
4
+ self[:record_id] = xml['RECORDID'].to_i
5
+ self[:mod_id] = xml['MODID'].to_i
6
+
7
+ self[:columns] = xml.css('COL').collect do |col|
11
8
  datas = col.css('DATA')
12
9
  if datas.size > 1
13
- @columns << datas.collect { |x| x.inner_text }
10
+ datas.collect { |x| x.inner_text }
14
11
  else
15
- @columns << datas.inner_text
12
+ datas.inner_text
16
13
  end
17
14
  end
18
15
  end
data/rfilemaker.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rfilemaker}
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bart Zonneveld"]
12
- s.date = %q{2010-06-01}
12
+ s.date = %q{2010-06-02}
13
13
  s.description = %q{Ruby library to parse Filemaker Pro FMPXMLRESULT files}
14
14
  s.email = %q{loop@superinfinite.com}
15
15
  s.extra_rdoc_files = [
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
31
31
  "rfilemaker.gemspec",
32
32
  "spec/full_parse_test_spec.rb",
33
33
  "spec/rfilemaker/field_spec.rb",
34
+ "spec/rfilemaker/record_spec.rb",
34
35
  "spec/rfilemaker/result_set_spec.rb",
35
36
  "spec/rfilemaker_spec.rb",
36
37
  "spec/spec.opts",
@@ -44,6 +45,7 @@ Gem::Specification.new do |s|
44
45
  s.test_files = [
45
46
  "spec/full_parse_test_spec.rb",
46
47
  "spec/rfilemaker/field_spec.rb",
48
+ "spec/rfilemaker/record_spec.rb",
47
49
  "spec/rfilemaker/result_set_spec.rb",
48
50
  "spec/rfilemaker_spec.rb",
49
51
  "spec/spec_helper.rb"
@@ -43,14 +43,14 @@ describe RFilemaker do
43
43
  describe "records" do
44
44
  it "should parse the first record correctly" do
45
45
  r = @result[0]
46
- r.should == { 'Name' => 'Joe Smith', 'Date joined' => [Date.new(2010,3,2), Date.new(2010,5,2)] }
46
+ r.should == { 'name' => 'Joe Smith', 'date joined' => [Date.new(2010,3,2), Date.new(2010,5,2)] }
47
47
  r.mod_id.should == 47
48
48
  r.record_id.should == 34
49
49
  end
50
50
 
51
51
  it "should parse the second record correctly" do
52
52
  r = @result[1]
53
- r.should == { 'Name' => 'Susan Jones', 'Date joined' => [Date.new(2009,4,5), Date.new(2009,10,5)] }
53
+ r.should == { 'name' => 'Susan Jones', 'date joined' => [Date.new(2009,4,5), Date.new(2009,10,5)] }
54
54
  r.mod_id.should == 89
55
55
  r.record_id.should == 78
56
56
  end
@@ -0,0 +1,12 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe RFilemaker::Record do
4
+ before(:each) do
5
+ @row = { :record_id => 1, :mod_id => 2 }
6
+ end
7
+
8
+ it "should be frozen" do
9
+ r = RFilemaker::Record.new(@row, [])
10
+ r.should be_frozen
11
+ end
12
+ end
@@ -24,4 +24,19 @@ describe RFilemaker do
24
24
  it "should return the resultset" do
25
25
  parse.should == 'result set'
26
26
  end
27
+
28
+ describe "'special' hash" do
29
+ before(:each) do
30
+ @h = RFilemaker::SpecialHash.new
31
+ @h['Foo BAR'] = 'baz'
32
+ end
33
+
34
+ it "should lookup keys as string" do
35
+ @h['Foo BAR'].should == 'baz'
36
+ end
37
+
38
+ it "should lookup keys as lowercase strings" do
39
+ @h['foo bar'].should == 'baz'
40
+ end
41
+ end
27
42
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 1
9
- version: 0.0.1
8
+ - 2
9
+ version: 0.0.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Bart Zonneveld
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-01 00:00:00 +02:00
17
+ date: 2010-06-02 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -69,6 +69,7 @@ files:
69
69
  - rfilemaker.gemspec
70
70
  - spec/full_parse_test_spec.rb
71
71
  - spec/rfilemaker/field_spec.rb
72
+ - spec/rfilemaker/record_spec.rb
72
73
  - spec/rfilemaker/result_set_spec.rb
73
74
  - spec/rfilemaker_spec.rb
74
75
  - spec/spec.opts
@@ -106,6 +107,7 @@ summary: Ruby library to parse Filemaker Pro FMPXMLRESULT files
106
107
  test_files:
107
108
  - spec/full_parse_test_spec.rb
108
109
  - spec/rfilemaker/field_spec.rb
110
+ - spec/rfilemaker/record_spec.rb
109
111
  - spec/rfilemaker/result_set_spec.rb
110
112
  - spec/rfilemaker_spec.rb
111
113
  - spec/spec_helper.rb