kdonovan-trufina 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -132,6 +132,11 @@ which is exactly the format Trufina requires to indicate we want to receive the
132
132
  * (Note that Trufina[http://www.trufina.com] itself doesn't support maxAge or timeframe yet)
133
133
  * Setting ResidenceAddress seed data isn't yet supported
134
134
 
135
+ == API Version
136
+
137
+ This is compatible with the latest Trufina API version as of the creation date: Trufina API 1.0.4
138
+
139
+
135
140
  == Compatibility
136
141
 
137
142
  The goal of this module is to be relatively framework agnostic. That being said, I've personally only tried to use it
data/TODO CHANGED
@@ -1,8 +1,5 @@
1
1
  PENDING:
2
2
  * Schema validation against the provided .xsd fails
3
- * Unable to set ResidenceAddress in seed data (e.g. Trufina.login_request(4, :seed => {:residence_address => {:state => 'CA'}}))
4
- Yields error: Attribute 'timeframe' must appear on element 'ResidenceAddress' (noted in README)
5
3
 
6
4
  UNSUPPORTED:
7
- * Setting StreetAddress seed data is unsupported (will generate extra <.> tags, and it is unclear how to set multiple lines)
8
5
  * Comparison or other request attributes (note that maxAge and timeframe are not even supported by Trufina yet)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
data/lib/elements.rb CHANGED
@@ -7,53 +7,61 @@ class Trufina
7
7
  module AllowCreationFromHash
8
8
 
9
9
  def initialize(seed_data = {})
10
- seed_data.is_a?(Array) ? create_empty_nodes(seed_data) : create_nodes(seed_data)
11
- end
10
+ create_nodes(seed_data)
12
11
 
13
- protected
14
-
15
- # e.g. Trufina::Name.new([:first, :suffix]) - no values provided, print empty nodes
16
- #
17
- # <Name>
18
- # <First/>
19
- # <Suffix/>
20
- # </Name>
21
- def create_empty_nodes(nodes)
22
- nodes.each do |node|
23
- create_node(node)
12
+ # Define attributes
13
+ self.class.attributes.each do |attr|
14
+ self.send("#{attr.method_name}=", nil) unless self.send(attr.method_name)
15
+ end
16
+
17
+ # Define elements
18
+ self.class.attributes.each do |elem|
19
+ self.send("#{elem.method_name}=", nil) unless self.send(elem.method_name)
24
20
  end
25
21
  end
26
22
 
27
- # e.g. Trufina::Name.new({:first => 'Bob', :suffix => 'III'}) - print nodes with values
28
- #
29
- # <Name>
30
- # <First>Bob</First>
31
- # <Suffix>III</Suffix>
32
- # </Name>
33
- def create_nodes(nodes)
34
- nodes.each do |node, content|
35
- create_node(node, content)
23
+ protected
24
+
25
+ def create_nodes(data)
26
+ data.each do |key, value|
27
+ create_node(key, value)
36
28
  end
37
29
  end
38
30
 
39
31
  # Handle the actual node creation
40
32
  def create_node(name, content = nil)
33
+ return create_nodes(name) if content.nil? && name.is_a?(Hash) # Handle accidentally passing in a full hash
34
+
35
+ element = self.class.elements.detect{|e| e.method_name.to_sym == name}
36
+ raise Exceptions::InvalidElement.new("No known element named '#{name}'") unless element || self.respond_to?("#{name}=")
37
+
41
38
  case name
42
- when Array then create_empty_nodes(name)
43
39
  when Hash then create_nodes(name)
40
+ when Array then create_empty_nodes(name)
44
41
  else
45
- element = self.class.elements.detect{|e| e.method_name.to_sym == name}
46
- raise Exceptions::InvalidElement.new("No known element named '#{name}'") unless element
47
-
48
- value = if HappyMapper::Item::Types.include?(element.type)
49
- content ? content : ''
50
- else
51
- content ? element.type.new(content) : element.type.new
42
+ value = if content.nil?
43
+ make_object?(element) ? element.type.new : ''
44
+ elsif content.is_a?(Array) && (element && !element.options[:single])
45
+ # If elements expects multiple instances, instantiate them all (e.g. StreetAddresses)
46
+ # Note that this assumes the object (only known case is Trufina::Elements::StreetAddress) has a :name element
47
+ out = content.collect do |local_content|
48
+ make_object?(element) ? element.type.new(:name => local_content) : local_content
49
+ end
50
+ else
51
+ make_object?(element) ? element.type.new(content) : content
52
52
  end
53
+
53
54
  self.send("#{name}=", value)
54
55
  end
55
56
  end
56
57
 
58
+ # Returns false if the given content is a simple type like a string, and we should just assign it.
59
+ # Returns true if the given content is another HappyMapper class, and we should instantiate the class
60
+ # rather than merely assigning the value.
61
+ def make_object?(element)
62
+ element && !HappyMapper::Item::Types.include?(element.type)
63
+ end
64
+
57
65
  end
58
66
 
59
67
  module Elements
@@ -93,29 +101,39 @@ class Trufina
93
101
  element :suffix, String, :tag => 'Suffix', :attributes => RESPONSE_XML_ATTRIBUTES
94
102
  end
95
103
 
96
- # Wrapper attempting to allow access to multiple StreetAddress tags per single ResidenceAddress
97
- class StreetAddress
104
+ # Encapsulates Trufina's address fields - has multiple street address fields
105
+ class ResidenceAddressResponse
98
106
  include AllowCreationFromHash
99
107
  include HappyMapper
100
108
  include EasyElementAccess
101
- tag 'StreetAddress'
102
-
103
- element :name, String, :tag => '.', :attributes => RESPONSE_XML_ATTRIBUTES
104
- end
109
+ tag 'ResidenceAddress'
110
+
111
+ has_many :street_addresses, String, :tag => 'StreetAddress', :attributes => RESPONSE_XML_ATTRIBUTES
112
+ element :city, String, :tag => 'City', :attributes => RESPONSE_XML_ATTRIBUTES
113
+ element :state, String, :tag => 'State', :attributes => RESPONSE_XML_ATTRIBUTES
114
+ element :zip, String, :tag => 'PostalCode', :attributes => RESPONSE_XML_ATTRIBUTES
115
+ attribute :timeframe, String
105
116
 
106
- # Encapsulates Trufina's address fields
107
- class ResidenceAddress
117
+ def street_address=(adr)
118
+ self.street_addresses ||= []
119
+ self.street_addresses << adr
120
+ end
121
+ end
122
+
123
+ # Encapsulates Trufina's address fields - only one street address field
124
+ class ResidenceAddressRequest
108
125
  include AllowCreationFromHash
109
126
  include HappyMapper
110
127
  include EasyElementAccess
111
128
  tag 'ResidenceAddress'
112
129
 
113
- has_many :street_addresses, StreetAddress, :tag => 'StreetAddress', :attributes => RESPONSE_XML_ATTRIBUTES
130
+ element :street_address, String, :tag => 'StreetAddress', :attributes => RESPONSE_XML_ATTRIBUTES
114
131
  element :city, String, :tag => 'City', :attributes => RESPONSE_XML_ATTRIBUTES
115
132
  element :state, String, :tag => 'State', :attributes => RESPONSE_XML_ATTRIBUTES
116
- element :postal_code, String, :tag => 'PostalCode', :attributes => RESPONSE_XML_ATTRIBUTES
133
+ element :zip, String, :tag => 'PostalCode', :attributes => RESPONSE_XML_ATTRIBUTES
117
134
  end
118
135
 
136
+
119
137
  # Encapsulates all response data Trufina may send back
120
138
  class AccessResponseGroup
121
139
  include AllowCreationFromHash
@@ -123,11 +141,11 @@ class Trufina
123
141
  include EasyElementAccess
124
142
  tag 'AccessResponse'
125
143
 
126
- element :name, Name, :single => true, :attributes => RESPONSE_XML_ATTRIBUTES
144
+ element :name, Name, :single => true
127
145
  # element :birth_date, Date, :tag => 'DateOfBirth', :attributes => RESPONSE_XML_ATTRIBUTES
128
146
  # element :birth_country, String, :tag => 'CountryOfBirth', :attributes => RESPONSE_XML_ATTRIBUTES
129
147
  element :phone, String, :tag => 'Phone', :attributes => RESPONSE_XML_ATTRIBUTES
130
- element :residence_address, ResidenceAddress, :single => true, :attributes => RESPONSE_XML_ATTRIBUTES
148
+ element :residence_address, ResidenceAddressResponse, :single => true
131
149
  element :ssn, String, :tag => 'fullSSN', :attributes => RESPONSE_XML_ATTRIBUTES
132
150
  element :last_4_ssn, String, :tag => 'Last4SSN', :attributes => RESPONSE_XML_ATTRIBUTES
133
151
  element :age, String, :tag => 'Age', :attributes => RESPONSE_XML_ATTRIBUTES
@@ -143,7 +161,7 @@ class Trufina
143
161
  element :birth_date, Date, :tag => 'DateOfBirth'
144
162
  element :birth_country, String, :tag => 'CountryOfBirth'
145
163
  element :phone, String, :tag => 'Phone' # If Trufina implemented it, could have timeframe and maxAge attributes
146
- element :residence_address, ResidenceAddress, :single => true # If Trufina implemented it, could have timeframe and maxAge attributes
164
+ element :residence_address, ResidenceAddressRequest, :single => true # If Trufina implemented it, could have timeframe and maxAge attributes
147
165
  element :ssn, String, :tag => 'fullSSN'
148
166
  element :last_4_ssn, String, :tag => 'Last4SSN'
149
167
  element :age, String, :tag => 'Age', :attributes => {:comparison => String}
@@ -156,15 +174,14 @@ class Trufina
156
174
  tag 'SeedInfo'
157
175
 
158
176
  element :name, Name, :single => true
159
- element :email, String, :single => true
160
177
  element :birth_date, Date, :tag => 'DateOfBirth'
161
178
  element :birth_country, String, :tag => 'CountryOfBirth'
162
179
  element :phone, String, :tag => 'Phone'
163
- element :residence_address, ResidenceAddress, :single => true
180
+ element :residence_address, ResidenceAddressResponse, :single => true
164
181
  element :ssn, String, :tag => 'fullSSN'
165
182
  element :last_4_ssn, String, :tag => 'Last4SSN'
166
183
  element :age, String, :tag => 'Age'
167
184
  end
168
185
 
169
186
  end
170
- end
187
+ end
data/lib/requests.rb CHANGED
@@ -126,6 +126,13 @@ class Trufina
126
126
 
127
127
  element :data, Elements::AccessRequest, :single => true
128
128
  element :seed, Elements::SeedInfoGroup, :single => true
129
+
130
+ def initialize *args
131
+ super(args)
132
+
133
+ # Trufina is brilliant, and they fail if this isn't in the request (even though they don't actually read the value)
134
+ seed.residence_address.timeframe = 'current'
135
+ end
129
136
  end
130
137
 
131
138
  end
data/lib/trufina.rb CHANGED
@@ -20,8 +20,7 @@ class Trufina
20
20
  # * seed -- Hash of seed data used to prefill the user's forms at Trufina's website
21
21
  def login_request(prt, opts = {})
22
22
  opts[:requested] ||= {:name => [:first, :last]}
23
- opts[:seed]
24
- xml = Requests::LoginRequest.new(:prt => prt, :data => opts[:requested], :seed => opts[:seed]).render
23
+ xml = Requests::LoginRequest.new(:prt => prt, :data => opts[:requested], :seed => remove_empties_from_hash(opts[:seed] || [])).render
25
24
  sendToTrufina(xml)
26
25
  end
27
26
 
@@ -137,5 +136,16 @@ class Trufina
137
136
  "http://#{domain}#{path}"
138
137
  end
139
138
 
139
+ # Removes any hash keys with empty values - seed data can't have any blanks, or Trufina gets mad
140
+ def remove_empties_from_hash(old_hash)
141
+ new_hash = {}
142
+ old_hash.each do |key, value|
143
+ next if value.nil? || value == '' || value == [] || value == {}
144
+ new_hash[key] = value.is_a?(Hash) ? remove_empties_from_hash(value) : value
145
+ end
146
+
147
+ return new_hash
148
+ end
149
+
140
150
  end
141
151
  end
data/trufina.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{trufina}
8
- s.version = "0.1.2"
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 = ["Kali Donovan"]
12
- s.date = %q{2009-09-03}
12
+ s.date = %q{2009-09-04}
13
13
  s.description = %q{Provides a DSL to easily interact with the XML API offered by Trufina.com, an identity verification company.}
14
14
  s.email = %q{kali.donovan@gmail.com}
15
15
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kdonovan-trufina
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kali Donovan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-03 00:00:00 -07:00
12
+ date: 2009-09-04 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -63,6 +63,7 @@ files:
63
63
  - trufina.yml.template
64
64
  has_rdoc: false
65
65
  homepage: http://github.com/kdonovan/trufina
66
+ licenses:
66
67
  post_install_message:
67
68
  rdoc_options:
68
69
  - --charset=UTF-8
@@ -83,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
84
  requirements: []
84
85
 
85
86
  rubyforge_project:
86
- rubygems_version: 1.2.0
87
+ rubygems_version: 1.3.5
87
88
  signing_key:
88
89
  specification_version: 3
89
90
  summary: DSL to easily interact with Trufina's verification API