rfilemaker 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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