melissa 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fb291d59288648da0db3f3c32dd53dc59fe4fb51
4
+ data.tar.gz: c3108433ae2a69e654267e172b77cbee2e546258
5
+ SHA512:
6
+ metadata.gz: 7adf1de091986fe471e96f2b090feeab46d88bff99ba672b464319e469ea905b2d3965eb9ceffa314b7bdaff95431b09161c501df5f732e1e04b9641d9098c3c
7
+ data.tar.gz: 6f02f3f05fb70f0d4d9eb13e3ccded9465e6c603c70a6f10597d3370a2a3a648c983625de481291ed0fead33566dc561a6df4ec8b40eed797d913d4a5ba3615a
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .idea
7
+ InstalledFiles
8
+ _yardoc
9
+ bin/
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ vendor
@@ -0,0 +1 @@
1
+ jruby-1.7.9
@@ -0,0 +1 @@
1
+ 2.1.2
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in melissa.gemspec
4
+ gemspec
5
+
6
+ gem 'rake'
7
+ gem 'minitest'
8
+ gem 'minitest-reporters'
9
+ gem 'minitest-stub_any_instance'
10
+ gem 'shoulda-context'
@@ -0,0 +1,50 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ melissa (0.0.1)
5
+ activesupport
6
+ ffi
7
+ minitest
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activesupport (4.2.0)
13
+ i18n (~> 0.7)
14
+ json (~> 1.7, >= 1.7.7)
15
+ minitest (~> 5.1)
16
+ thread_safe (~> 0.3, >= 0.3.4)
17
+ tzinfo (~> 1.1)
18
+ ansi (1.5.0)
19
+ builder (3.2.2)
20
+ ffi (1.9.6)
21
+ ffi (1.9.6-java)
22
+ i18n (0.7.0)
23
+ json (1.8.2)
24
+ json (1.8.2-java)
25
+ minitest (5.4.0)
26
+ minitest-reporters (1.0.8)
27
+ ansi
28
+ builder
29
+ minitest (>= 5.0)
30
+ ruby-progressbar
31
+ minitest-stub_any_instance (1.0.0)
32
+ rake (10.4.2)
33
+ ruby-progressbar (1.7.1)
34
+ shoulda-context (1.2.1)
35
+ thread_safe (0.3.4)
36
+ thread_safe (0.3.4-java)
37
+ tzinfo (1.2.2)
38
+ thread_safe (~> 0.1)
39
+
40
+ PLATFORMS
41
+ java
42
+ ruby
43
+
44
+ DEPENDENCIES
45
+ melissa!
46
+ minitest
47
+ minitest-reporters
48
+ minitest-stub_any_instance
49
+ rake
50
+ shoulda-context
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Svetlana Marinskaya
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,142 @@
1
+ # Melissa
2
+
3
+ Configurable interface to Melissa Data Address and GeoCoder objects
4
+
5
+ ##Description
6
+
7
+ Melissa Gem allows you to use ruby wrappers for Melissa Data's AddrObj and GeoPoint objects or use the mock objects depending on configuration.
8
+
9
+ Address Object’s functionality is divided into four interfaces, AddressCheck, Parse,
10
+ StreetData, and Data. We are using AddressCheck Interface.
11
+
12
+ The AddressCheck Interface verifies and standardizes your address data using the
13
+ most current data from the U. S. Postal Service®. The programming logic used by
14
+ AddressCheck is CASS Certified™. This stringent certification ensures the quality of
15
+ the data that is passed through the AddressCheck Interface and must be renewed
16
+ every year.
17
+
18
+ The GeoCoder Object enables you to access geographic data using your
19
+ ZIP Code™ and optional Plus4. You will be able to obtain latitude and
20
+ longitude geographic coordinates, census tract and block numbers, as well as
21
+ county name and FIPS numbers.
22
+
23
+ The Standard version of GeoCoder Object includes GeoPoints 11-digit
24
+ (ZIP + 4 + 2) doorstop geolocation data on over 121,827,000 addresses in
25
+ the United States.
26
+ GeoPoints data is multi-sourced, including interpolated points mathematically
27
+ calculated for valid addresses where no GeoPoints data is found, and covers
28
+ 95 percent of all U.S. delivery addresses, business and residential.
29
+
30
+
31
+ ## Installation
32
+
33
+ Add this line to your application's Gemfile:
34
+
35
+ gem 'melissa'
36
+
37
+ And then execute:
38
+
39
+ $ bundle
40
+
41
+ Or install it yourself as:
42
+
43
+ $ gem install melissa
44
+
45
+ ## Usage
46
+
47
+ It is recommended to read the following config options from environment variables
48
+ From Melissa Data documentation:
49
+ The license string should be entered as an environment variable named
50
+ MD_LICENSE. This allows you to update your license string without editing
51
+ and recompiling your code
52
+
53
+ ```ruby
54
+ self.config_path = ENV['MELISSA_CONFIG_PATH'] if ENV['MELISSA_CONFIG_PATH']
55
+ self.home = ENV['MELISSA_HOME'] if ENV['MELISSA_HOME']
56
+ @data_path = ENV['MELISSA_DATA_PATH'] if ENV['MELISSA_DATA_PATH']
57
+ @addr_obj_lib = ENV['MELISSA_ADDR_OBJ_LIB'] if ENV['MELISSA_ADDR_OBJ_LIB']
58
+ @geo_point_lib = ENV['MELISSA_GEO_POINT_LIB'] if ENV['MELISSA_GEO_POINT_LIB']
59
+ @license = ENV['MD_LICENSE'] if ENV['MD_LICENSE']
60
+ ```
61
+ It is also possible to set HOME and LICENSE variables in configuration file, which can be accesses
62
+
63
+ ```ruby
64
+ Melissa.configure do |config|
65
+ config.config_path = "/etc/config/melissa"
66
+ end
67
+ ```
68
+
69
+ A suite number can be passed at the end of the values passed to :address
70
+ option, or as the parameter of either the :address2 or the :suite option.
71
+ If the value passed to the :address option cannot be verified, Address Object
72
+ will attempt to verify the value passed via the :address2 option. See Address
73
+ Handling in Melissa Data Documentation for more information.
74
+ If you use :zip option, :city and :state parameters are optional.
75
+ Likewise, if :city and :state are populated, :zip is optional. If possible, it is the
76
+ best practice to pass all three values if possible, because Address Object will use
77
+ the values to validate each other.
78
+
79
+ ```ruby
80
+ #create AddrObj
81
+ valid_addr_obj = ::Melissa.addr_obj(
82
+ :address => '9802 Brompton Dr',
83
+ :city => 'Tampa',
84
+ :state => 'Fl',
85
+ :zip => '33626'
86
+ )
87
+ #use it to get deliverypoint
88
+ deliverypoint = valid_addr_obj.delivery_point
89
+
90
+ #create GeoPoint Object
91
+ geo_point_obj = ::Melissa.geo_point(valid_addr_obj)
92
+ #use it
93
+ latitude = geo_point_obj.latitude
94
+ longitude= geo_point_obj.longitude
95
+ #or
96
+ geo_point_obj = ::Melissa.geo_point(:zip => 'zip', :plus4 => 'plus4', :delivery_point_code => 'delivery_point_code')
97
+
98
+ ```
99
+
100
+ The calls to Melissa Data library will be attempted only if Melissa Data library is loaded.
101
+ Otherwise mock objects will be used. This way there is no need to install Melissa Data library on development machine.
102
+ The following rules are used in mocking AddrObj Library:
103
+ 1. if zip_code is present, addres object is valid.
104
+ 2. to mock delivery point: "#{zip_code}1234#{last 2 digits of zip code}".
105
+ For example, zip_code = 33613 => delivery_point = 33613123413
106
+
107
+ Mocked GeoPoint object will return following values:
108
+
109
+ ```ruby
110
+ @latitude = 36.20687
111
+ @longitude = -115.27857
112
+ @time_zone_code = '08'
113
+ @resultcodes = ['AS01']
114
+ @is_valid = true
115
+ ```
116
+
117
+ ## Meta
118
+
119
+ * Code: `git clone git://github.com/smarinskaya/melissa.git`
120
+ * Home: <https://github.com/smarinskaya/Melissa>
121
+ * Bugs: <http://github.com/smarinskaya/Melissa/issues>
122
+ * Gems: TODO
123
+
124
+
125
+ ## Authors
126
+
127
+ 1. [Brad Pardee](https://github.com/bpardee)
128
+ 2. [Svetlana Marinskaya](https://github.com/smarinskaya)
129
+
130
+
131
+ ##Aknowlegments
132
+
133
+ Configuration pattern is developed based on Brandon Hilkert blog
134
+ http://brandonhilkert.com/blog/ruby-gem-configuration-patterns/
135
+
136
+ ## Contributing
137
+
138
+ 1. Fork it
139
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
140
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
141
+ 4. Push to the branch (`git push origin my-new-feature`)
142
+ 5. Create new Pull Request
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'test'
7
+ t.pattern = "test/*_test.rb"
8
+ end
@@ -0,0 +1,2 @@
1
+ HOME = path_to_home_directory
2
+ LICENSE = valid_license_key
@@ -0,0 +1,57 @@
1
+ module Melissa
2
+
3
+ class << self
4
+ attr_writer :config
5
+ end
6
+
7
+ def self.addr_obj(attrs)
8
+ if config.mode == :live
9
+ raise LoadError, "Melissa AddrObj was not loaded!" unless config.addr_obj_lib_loaded
10
+ AddrObjLive.new(attrs)
11
+ else
12
+ AddrObjMock.new(attrs)
13
+ end
14
+ end
15
+
16
+ def self.geo_point(attrs)
17
+ if config.mode == :live
18
+ raise LoadError, "Melissa GeoPoint object was not loaded!" unless config.geo_point_lib_loaded
19
+ GeoPointLive.new(attrs)
20
+ else
21
+ GeoPointMock.new(attrs)
22
+ end
23
+ end
24
+
25
+ def self.config
26
+ @config ||= Config.new
27
+ end
28
+
29
+ def self.reset
30
+ @config = Config.new
31
+ end
32
+
33
+ def self.configure
34
+ yield(config)
35
+ end
36
+ end
37
+
38
+ require 'melissa/railtie' if defined?(Rails)
39
+
40
+ require "melissa/version"
41
+ require "melissa/config"
42
+ require 'melissa/addr_obj'
43
+ require 'melissa/geo_point'
44
+ require 'melissa/addr_obj_live'
45
+ require 'melissa/geo_point_live'
46
+ require 'melissa/addr_obj_mock'
47
+ require 'melissa/geo_point_mock'
48
+
49
+
50
+ #valid_address_obj = ::Melissa.adrr_obj(:address => 'valid street', :city => 'Tampa', :state => 'FL', :zip => '33626')
51
+ #puts "addr=#{valid_address_obj.address}"
52
+ #puts "deliverypoint=#{valid_address_obj.delivery_point}"
53
+
54
+ #g = ::Melissa.geo_point(valid_address_obj)
55
+ #puts "lat,long=#{g.latitude},#{g.longitude}"
56
+ #or
57
+ #g = ::Melissa.geo_point(:zip => 'zip', :plus4 => 'plus4', :delivery_point_code => 'delivery_point_code')
@@ -0,0 +1,92 @@
1
+ require 'active_support/all' #TODO I can narrow down this
2
+
3
+ module Melissa
4
+ class AddrObj
5
+ AddressStruct = Struct.new(:number, :pre_directional, :name, :suffix, :post_directional)
6
+
7
+ @@melissa_attributes = %w(
8
+ Company
9
+ LastName
10
+ Address
11
+ Address2
12
+ Suite
13
+ City
14
+ CityAbbreviation
15
+ State
16
+ Zip
17
+ Plus4
18
+ CarrierRoute
19
+ DeliveryPointCode
20
+ DeliveryPointCheckDigit
21
+ CountyFips
22
+ CountyName
23
+ AddressTypeCode
24
+ AddressTypeString
25
+ Urbanization
26
+ CongressionalDistrict
27
+ LACS
28
+ LACSLinkIndicator
29
+ RBDI
30
+ PrivateMailbox
31
+ TimeZoneCode
32
+ TimeZone
33
+ Msa
34
+ Pmsa
35
+ DefaultFlagIndicator
36
+ SuiteStatus
37
+ EWSFlag
38
+ CMRA
39
+ DsfNoStats
40
+ DsfVacant
41
+ CountryCode
42
+ ZipType
43
+ FalseTable
44
+ DPVFootnotes
45
+ LACSLinkReturnCode
46
+ SuiteLinkReturnCode
47
+ ELotNumber
48
+ ELotOrder
49
+ )
50
+
51
+ # See http://www.melissadata.com/lookups/resultcodes.asp
52
+ @@good_codes = ['AS01', 'AS02']
53
+ @@bad_codes = ['AC02', 'AC03']
54
+
55
+ def delivery_point
56
+ "#{zip}#{plus4}#{delivery_point_code}"
57
+ end
58
+
59
+ def time_zone_offset
60
+ GeoPoint.time_zone_offset(self.time_zone_code, self.state)
61
+ end
62
+
63
+ def address_struct
64
+ @address_struct = begin
65
+ if valid?
66
+ if address_type_string == 'Street' || address_type_string == 'Highrise'
67
+ match = self.address.match /^(\S+)\s?(N|NE|E|SE|S|SW|W|NW|) (\S.*?)\s?(N|NE|E|SE|S|SW|W|NW|)$/
68
+ end
69
+ elsif self.address
70
+ match = self.address.match /^(\d\S*)\s?(N|NE|E|SE|S|SW|W|NW|) (\S.*?)\s?(N|NE|E|SE|S|SW|W|NW|)$/
71
+ end
72
+ if match
73
+ # Parse out the optional suffix
74
+ street_match = match[3].match /(\S.*?)( [A-Za-z]{2,4}|)$/
75
+ if street_match
76
+ name, suffix = street_match[1], street_match[2].strip
77
+ else
78
+ name, suffix = match[3], ''
79
+ end
80
+ AddressStruct.new(match[1], match[2], name, suffix, match[4])
81
+ elsif self.address
82
+ AddressStruct.new('', '', self.address, '', '')
83
+ else
84
+ AddressStruct.new
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+
92
+
@@ -0,0 +1,117 @@
1
+ require 'ffi'
2
+
3
+ module Melissa
4
+ class AddrObjLive < AddrObj
5
+ begin
6
+ extend FFI::Library
7
+
8
+ ffi_lib Melissa.config.addr_obj_lib if defined?(FFI)
9
+ attr_functions = @@melissa_attributes.map { |name| ["mdAddrGet#{name}".to_sym, [:pointer], :string] }
10
+
11
+ functions = attr_functions + [
12
+ # method # parameters # return
13
+ [:mdAddrCreate, [], :pointer],
14
+ [:mdAddrSetLicenseString, [:pointer, :string], :int],
15
+ [:mdAddrSetPathToUSFiles, [:pointer, :string], :void],
16
+ [:mdAddrInitializeDataFiles, [:pointer], :int],
17
+ [:mdAddrClearProperties, [:pointer], :void],
18
+ [:mdAddrSetCompany, [:pointer, :string], :void],
19
+ [:mdAddrSetAddress, [:pointer, :string], :void],
20
+ [:mdAddrSetAddress2, [:pointer, :string], :void],
21
+ [:mdAddrSetSuite, [:pointer, :string], :void],
22
+ [:mdAddrSetCity, [:pointer, :string], :void],
23
+ [:mdAddrSetState, [:pointer, :string], :void],
24
+ [:mdAddrSetZip, [:pointer, :string], :void],
25
+ [:mdAddrSetUrbanization, [:pointer, :string], :void],
26
+ [:mdAddrSetCountryCode, [:pointer, :string], :void],
27
+ [:mdAddrVerifyAddress, [:pointer], :int],
28
+ [:mdAddrGetResults, [:pointer], :string],
29
+ [:mdAddrDestroy, [:pointer], :void],
30
+ [:mdAddrGetLicenseExpirationDate, [:pointer], :string],
31
+ [:mdAddrGetExpirationDate, [:pointer], :string],
32
+ ]
33
+
34
+ functions.each do |func|
35
+ begin
36
+ attach_function(*func)
37
+ rescue Object => e
38
+ raise "Could not attach #{func}, #{e.message}"
39
+ end
40
+ end
41
+
42
+ attr_reader *@@melissa_attributes.map { |name| name.underscore.to_sym }
43
+
44
+ # Get all the attributes out up-front so we can destroy the h_addr_lib object
45
+ class_eval <<-EOS
46
+ define_method(:fill_attributes) do |h_addr_lib|
47
+ #{@@melissa_attributes.map { |name| "@#{name.underscore} = mdAddrGet#{name}(h_addr_lib)" }.join("\n")}
48
+ end
49
+ EOS
50
+
51
+ def self.with_mdaddr
52
+ h_addr_lib = mdAddrCreate
53
+ mdAddrSetLicenseString(h_addr_lib, Melissa.config.license)
54
+ mdAddrSetPathToUSFiles(h_addr_lib, Melissa.config.data_path)
55
+ mdAddrInitializeDataFiles(h_addr_lib)
56
+ yield h_addr_lib
57
+ ensure
58
+ mdAddrDestroy(h_addr_lib)
59
+ end
60
+
61
+ #This function returns a date value corresponding to the date when the current license
62
+ #string expires.
63
+
64
+ def self.license_expiration_date
65
+ Date.parse(with_mdaddr { |h_addr_lib| mdAddrGetLicenseExpirationDate(h_addr_lib) })
66
+ end
67
+
68
+ def self.days_until_license_expiration
69
+ #I compare Date objects. I think it is more accurate.
70
+ #self.license_expiration_date returns string in format: "YYYY-MM-DD"
71
+ (self.license_expiration_date - Date.today).to_i
72
+ end
73
+
74
+ # U.S. Only — This function returns a date value representing the
75
+ # date when the current U.S. data files expire. This date enables you to confirm that the
76
+ # data files you are using are the latest available.
77
+
78
+ def self.data_expiration_date
79
+ Date.strptime(with_mdaddr { |h_addr_lib| mdAddrGetExpirationDate(h_addr_lib) }, '%m-%d-%Y')
80
+ end
81
+
82
+ def self.days_until_data_expiration
83
+ (self.data_expiration_date - Date.today).to_i
84
+ end
85
+
86
+ def initialize(opts)
87
+ self.class.with_mdaddr do |h_addr_lib|
88
+ # clear any properties from a previous call
89
+ mdAddrClearProperties(h_addr_lib)
90
+
91
+ mdAddrSetCompany(h_addr_lib, opts[:company] || '');
92
+ mdAddrSetAddress(h_addr_lib, opts[:address] || '');
93
+ mdAddrSetAddress2(h_addr_lib, opts[:address2] || '');
94
+ mdAddrSetSuite(h_addr_lib, opts[:suite] || '');
95
+ mdAddrSetCity(h_addr_lib, opts[:city] || '');
96
+ mdAddrSetState(h_addr_lib, opts[:state] || '');
97
+ mdAddrSetZip(h_addr_lib, opts[:zip] || '');
98
+ mdAddrSetUrbanization(h_addr_lib, opts[:urbanization] || '');
99
+ mdAddrSetCountryCode(h_addr_lib, opts[:country_code] || '');
100
+ mdAddrVerifyAddress(h_addr_lib);
101
+
102
+ @resultcodes = mdAddrGetResults(h_addr_lib).split(',')
103
+ fill_attributes(h_addr_lib)
104
+ end
105
+ end
106
+
107
+ def valid?
108
+ # Make sure there is at least 1 good code and no bad codes
109
+ (@resultcodes & @@good_codes).present? && (@resultcodes & @@bad_codes).empty?
110
+ end
111
+ rescue LoadError => e
112
+ Melissa.config.addr_obj_lib_loaded = false
113
+ else
114
+ Melissa.config.addr_obj_lib_loaded = true
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,46 @@
1
+ # Fake out Melissa data in Dev and Test environments. For local tests, and for Release and Hotfix
2
+ module Melissa
3
+ class AddrObjMock < AddrObj
4
+
5
+ # Since we're faking it, create accessors that just return the corresponding opts value except the ones we dummy in the ctor
6
+ @@melissa_attributes.each do |name|
7
+ name = name.underscore
8
+ class_eval <<-EOS
9
+ define_method(:#{name}) do
10
+ @#{name} ||= (@opts[:#{name}] || nil)
11
+ end
12
+ EOS
13
+ end
14
+
15
+ #Mock
16
+ def initialize(opts)
17
+ @opts = opts
18
+ #@urbanization = opts[:urbanization] || ''
19
+ @resultcodes = ['AS01']
20
+ @address_type_string = 'Street'
21
+ end
22
+
23
+ #Mock
24
+ def delivery_point_code
25
+ point_code = nil
26
+ point_code = self.zip[3..5] if self.zip.present?
27
+ return point_code
28
+ end
29
+
30
+ #Mock
31
+ def delivery_point_check_digit
32
+ self.city && (self.city.sum % 10).to_s
33
+ end
34
+
35
+ #Mock
36
+ def plus4
37
+ return '1234'
38
+ end
39
+
40
+ #Mock
41
+ def valid?
42
+ #we will mock delivery point if zip code is present.
43
+ return self.zip.present?
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,63 @@
1
+ require 'yaml'
2
+
3
+ module Melissa
4
+
5
+ MODES = [:mock, :live]
6
+
7
+ class Config
8
+
9
+ attr_accessor :mode, :license, :data_path, :addr_obj_lib, :addr_obj_lib_loaded
10
+ attr_accessor :geo_point_lib, :geo_point_lib_loaded
11
+
12
+ def initialize
13
+ #It is recommended to read the following config options from environment variables
14
+ #From Melissa Data documentation:
15
+ #The license string should be entered as an environment variable named
16
+ #MD_LICENSE. This allows you to update your license string without editing
17
+ #and recompiling your code
18
+
19
+ self.config_path = ENV['MELISSA_CONFIG_PATH'] if ENV['MELISSA_CONFIG_PATH']
20
+ self.home = ENV['MELISSA_HOME'] if ENV['MELISSA_HOME']
21
+ @data_path = ENV['MELISSA_DATA_PATH'] if ENV['MELISSA_DATA_PATH']
22
+ @addr_obj_lib = ENV['MELISSA_ADDR_OBJ_LIB'] if ENV['MELISSA_ADDR_OBJ_LIB']
23
+ @geo_point_lib = ENV['MELISSA_GEO_POINT_LIB'] if ENV['MELISSA_GEO_POINT_LIB']
24
+ @license = ENV['MD_LICENSE'] if ENV['MD_LICENSE']
25
+ end
26
+
27
+ #you can configure config_path from your code using:
28
+ # Melissa.configure do |config|
29
+ # config.config_path = "/etc/config/melissa"
30
+ # end
31
+ def config_path=(config_path)
32
+ File.open(config_path, 'r') do |fin|
33
+ fin.each do |line|
34
+ line.strip!
35
+ next if line.empty? || line[0] == '#'
36
+ equal_index = line.index('=')
37
+ key = line[0, equal_index].strip.downcase
38
+ value = line[(equal_index+1)..-1].strip
39
+ send("#{key}=", value)
40
+ end
41
+ end
42
+ rescue Errno::ENOENT
43
+ raise "Configuration file couldn't be found. We need #{config_path}"
44
+ end
45
+
46
+ def home=(home)
47
+ @addr_obj_lib = "#{home}/AddrObj/libmdAddr.so"
48
+ @geo_point_lib = "#{home}/GeoObj/libmdGeo.so"
49
+ @data_path = "#{home}/data"
50
+ end
51
+
52
+ def addr_obj_lib_loaded=(value)
53
+ @addr_obj_lib_loaded = value
54
+ @mode ||= :live if value
55
+ end
56
+
57
+ def geo_point_library_loaded=(value)
58
+ @geo_point_lib_loaded = value
59
+ @mode ||= :live if value
60
+ end
61
+ end
62
+ end
63
+
@@ -0,0 +1,75 @@
1
+ require "melissa/config"
2
+
3
+ module Melissa
4
+ class GeoPoint
5
+ @@melissa_attributes = %w(
6
+ Latitude
7
+ Longitude
8
+ CensusTract
9
+ CensusBlock
10
+ CountyFips
11
+ CountyName
12
+ PlaceCode
13
+ PlaceName
14
+ TimeZoneCode
15
+ TimeZone
16
+ CBSACode
17
+ CBSATitle
18
+ CBSALevel
19
+ CBSADivisionCode
20
+ CBSADivisionTitle
21
+ CBSADivisionLevel
22
+ )
23
+
24
+ @@codes = {
25
+ 'GS01' => 'Record was coded to the ZIP + 4 centroid (U.S.) or or the full 6-digit Postal Code level (Canada).',
26
+ 'GS02' => 'Record was coded to the ZIP + 2 centroid.',
27
+ 'GS03' => 'Record was coded to the 5-digit ZIP Code centroid (U.S.) or or the first 3-digit Postal Code level (Canada).',
28
+ 'GS05' => 'Record was coded to rooftop level.(Available On-Premise only)',
29
+ 'GS06' => 'Record was coded to interpolated rooftop level.(Available On-Premise only)*',
30
+ 'GE01' => 'ZIP Code Error. An invalid ZIP Code was entered.',
31
+ 'GE02' => 'ZIP Code not found. The submitted ZIP Code was not found in the database.',
32
+ 'GE03' => 'Demo Mode. GeoCoder Object is in Demo Mode and a ZIP Code outside the demo range was detected.',
33
+ 'GE04' => 'The GeoCoder Object data files are expired. Please update with the latest data files.',
34
+ 'GE05' => 'Geocoding for the country of input record is disabled for your license. Please contact your sales representative to enable.',
35
+ }
36
+
37
+ # See http://www.melissadata.com/lookups/resultcodes.asp
38
+ @@good_codes = ['GS01', 'GS02', 'GS03', 'GS05', 'GS06']
39
+ #@@bad_codes = ['GE01', 'GE02']
40
+ @@fatal_codes = ['GE03', 'GE04', 'GE05']
41
+
42
+ @@time_zones = {
43
+ '04' => 'Atlantic/Bermuda',
44
+ '05' => 'US/Eastern',
45
+ '06' => 'US/Central',
46
+ '07' => 'US/Mountain',
47
+ '08' => 'US/Pacific',
48
+ '09' => 'US/Alaska',
49
+ '10' => 'US/Hawaii',
50
+ '11' => 'US/Samoa',
51
+ '13' => 'Pacific/Majuro',
52
+ '14' => 'Pacific/Guam',
53
+ '15' => 'Pacific/Palau'
54
+ }
55
+
56
+ def valid?
57
+ # Make sure there is at least 1 good code
58
+ @is_valid
59
+ end
60
+
61
+ def time_zone_offset
62
+ GeoPoint.time_zone_offset(self.time_zone_code, @addr_obj.state)
63
+ end
64
+
65
+ # Hack for AddrObj to share code
66
+ def self.time_zone_offset(time_zone_code, state=nil)
67
+ time_zone = @@time_zones[time_zone_code]
68
+ return nil unless time_zone
69
+ time_zone = 'US/Arizona' if state == 'AZ'
70
+ return Time.now.in_time_zone(time_zone).utc_offset / -60
71
+ end
72
+ end
73
+ end
74
+
75
+
@@ -0,0 +1,126 @@
1
+ require 'ffi'
2
+
3
+ module Melissa
4
+ class GeoPointLive < GeoPoint
5
+ extend FFI::Library
6
+
7
+ begin
8
+ ffi_lib Melissa.config.geo_point_lib
9
+ attr_functions = @@melissa_attributes.map { |name| ["mdGeoGet#{name}".to_sym, [:pointer], :string] }
10
+
11
+ functions = attr_functions + [
12
+ # method # parameters # return
13
+ [:mdGeoCreate, [], :pointer],
14
+ [:mdGeoSetLicenseString, [:pointer, :string], :int],
15
+ [:mdGeoSetPathToGeoCodeDataFiles, [:pointer, :string], :void],
16
+ [:mdGeoSetPathToGeoPointDataFiles, [:pointer, :string], :void],
17
+ [:mdGeoInitializeDataFiles, [:pointer], :int],
18
+ [:mdGeoGeoPoint, [:pointer, :string, :string, :string], :int],
19
+ [:mdGeoGetResults, [:pointer], :string],
20
+ [:mdGeoDestroy, [:pointer], :void],
21
+ [:mdGeoGetLicenseExpirationDate, [:pointer], :string],
22
+ [:mdGeoGetExpirationDate, [:pointer], :string],
23
+ ]
24
+
25
+ functions.each do |func|
26
+ begin
27
+ attach_function(*func)
28
+ rescue Object => e
29
+ raise "Could not attach #{func}, #{e.message}"
30
+ end
31
+ end
32
+
33
+ attr_reader *@@melissa_attributes.map { |name| name.underscore.to_sym }
34
+
35
+ # Get all the attributes out up-front so we can destroy the mdGeo object
36
+ class_eval <<-EOS
37
+ define_method(:fill_attributes) do |mdGeo|
38
+ #{@@melissa_attributes.map { |name| "@#{name.underscore} = mdGeoGet#{name}(mdGeo)" }.join("\n")}
39
+ end
40
+ EOS
41
+
42
+ def self.with_mdgeo
43
+ mdGeo = mdGeoCreate
44
+ mdGeoSetLicenseString(mdGeo, Melissa.config.license)
45
+ mdGeoSetPathToGeoCodeDataFiles(mdGeo, Melissa.config.data_path)
46
+ mdGeoSetPathToGeoPointDataFiles(mdGeo, Melissa.config.data_path)
47
+ result = mdGeoInitializeDataFiles(mdGeo)
48
+ if result != 0
49
+ raise mdGeoGetInitializeErrorString(mdGeo)
50
+ end
51
+ yield mdGeo
52
+ ensure
53
+ mdGeoDestroy(mdGeo) if mdGeo
54
+ end
55
+
56
+ #This function returns a date value corresponding to the date when the current license
57
+ #string expires.
58
+ def self.license_expiration_date
59
+ Date.parse(with_mdgeo { |mdGeo| mdGeoGetLicenseExpirationDate(mdGeo) })
60
+ end
61
+
62
+ def self.days_until_license_expiration
63
+ #I compare Date objects. I think it is more accurate.
64
+ #self.license_expiration_date returns string in format: "YYYY-MM-DD"
65
+ (self.license_expiration_date - Date.today).to_i
66
+ end
67
+
68
+ # his function returns a date value representing the
69
+ # date when the current data files expire. This date enables you to confirm that the
70
+ # data files you are using are the latest available.
71
+ def self.expiration_date
72
+ Date.parse(with_mdgeo { |mdGeo| mdGeoGetExpirationDate(mdGeo)})
73
+ end
74
+
75
+ def self.days_until_data_expiration
76
+ #I compare Date objects. I think it is more accurate.
77
+ #self.license_expiration_date returns string in format: "YYYY-MM-DD"
78
+ (self.expiration_date - Date.today).to_i
79
+ end
80
+
81
+ def initialize(opts)
82
+ @is_valid = false
83
+
84
+ self.class.with_mdgeo do |mdGeo|
85
+ if opts.kind_of?(AddrObj)
86
+ mdGeoGeoPoint(mdGeo, opts.zip || '', opts.plus4 || '', opts.delivery_point_code || '')
87
+ elsif opts.kind_of?(Hash)
88
+ mdGeoGeoPoint(mdGeo, opts[:zip] || '', opts[:plus4] || '', opts[:delivery_point_code] || '')
89
+ else
90
+ raise "Invalid call to GeoPoint, unknown object #{opts.inspect}"
91
+ end
92
+ @resultcodes = mdGeoGetResults(mdGeo).split(',')
93
+ fatals = @resultcodes & @@fatal_codes
94
+ @is_valid = fatals.blank?
95
+ if @is_valid
96
+ fill_attributes(mdGeo)
97
+ # Convert from strings to actual types
98
+ if @latitude.blank?
99
+ @latitude = nil
100
+ else
101
+ @latitude = @latitude.to_f
102
+ end
103
+ if @longitude.blank?
104
+ @longitude = nil
105
+ else
106
+ @longitude = @longitude.to_f
107
+ end
108
+ if @latitude == 0.0 && @longitude == 0.0
109
+ @latitude = nil
110
+ @longitude = nil
111
+ @is_valid = false
112
+ end
113
+ else
114
+ fatals.each do |fatal_code|
115
+ raise "FATAL ERROR Melissa GeoPoint returned #{fatal_code}-#{@@codes[fatal_code]}"
116
+ end
117
+ end
118
+ end
119
+ end
120
+ rescue LoadError => e
121
+ Melissa.config.geo_point_library_loaded = false
122
+ else
123
+ Melissa.config.geo_point_library_loaded = true
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,28 @@
1
+ module Melissa
2
+ class GeoPointMock < GeoPoint
3
+ # Since we're faking it, create accessors that just return the corresponding opts value except the ones we dummy in the ctor
4
+ @@melissa_attributes.each do |name|
5
+ name = name.underscore
6
+ class_eval <<-EOS
7
+ define_method(:#{name}) do
8
+ @#{name} ||= (@opts[:#{name}] || '')
9
+ end
10
+ EOS
11
+ end
12
+
13
+ def initialize(addr_obj)
14
+ @is_valid = false
15
+
16
+ if addr_obj.kind_of?(AddrObj)
17
+ @addr_obj = addr_obj
18
+ else
19
+ raise "Invalid call to GeoPoint, unknown object #{addr_obj.inspect}"
20
+ end
21
+ @latitude = 36.20687
22
+ @longitude = -115.27857
23
+ @time_zone_code = '08'
24
+ @resultcodes = ['AS01']
25
+ @is_valid = true
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ module Melissa
2
+ class Railtie < Rails::Railtie #:nodoc:
3
+ # Make the Melissa config available in the Rails application config
4
+ config.before_configuration do
5
+ config_file = Rails.root.join('config', 'melissa.txt')
6
+ if config_file.file?
7
+ Melissa.config.config_path = config_file
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Melissa
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/melissa/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ['Brad Pardee', 'Svetlana Marinskaya']
6
+ gem.email = ['bradpardee@gmail.com', 'svetlana.marinskaya@gmail.com']
7
+ gem.description = %q{Configurable interface to Melissa Data Address and GeoPoint objects}
8
+ gem.summary = %q{Melissa allows you to use ruby wrappers for Melissa Data's AddrObj and GeoPoint objects or use the mock objects depending on configuration.}
9
+ gem.homepage = "https://github.com/smarinskaya/Melissa"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "melissa"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Melissa::VERSION
17
+
18
+ gem.add_dependency 'activesupport' # added to support underscore method.
19
+ gem.add_dependency 'minitest' # added as a dependency of activesupport and for testing.
20
+ gem.add_dependency 'ffi' #used for converting c libraries to ruby
21
+ end
@@ -0,0 +1,109 @@
1
+ require 'test_helper'
2
+
3
+ class AddrObjTest < Minitest::Test
4
+ describe Melissa::AddrObj do
5
+
6
+ describe "live mode" do
7
+ before do
8
+ Melissa.config.mode = :live if Melissa.config.addr_obj_lib_loaded
9
+ end
10
+
11
+ describe "valid?" do
12
+ it 'handles valid data' do
13
+ skip "Not run in mock mode" unless Melissa.config.mode == :live
14
+ valid_address = Melissa.addr_obj(
15
+ :address => '2517 Surfwood Dr',
16
+ :city => 'Las Vegas',
17
+ :state => 'NV',
18
+ :zip => '89128'
19
+ )
20
+ assert valid_address.valid?
21
+ assert_equal '2517 Surfwood Dr', valid_address.address
22
+ assert_equal 'Las Vegas', valid_address.city
23
+ assert_equal '89128718217', valid_address.delivery_point
24
+ end
25
+
26
+ it 'flags invalid data' do
27
+ skip "Not run in mock mode" unless Melissa.config.mode == :live
28
+ # Zip points to Schenectady, NY
29
+ invalid_address = Melissa.addr_obj(
30
+ :address => '123 Who Dr',
31
+ :city => 'WhoVille',
32
+ :state => 'IN',
33
+ :zip => '12345'
34
+ )
35
+ assert !invalid_address.valid?
36
+ end
37
+ end
38
+
39
+ describe "delivery_point" do
40
+ it 'sets delivery point for valid data' do
41
+ skip "Not run in mock mode" unless Melissa.config.mode == :live
42
+ valid_address = Melissa.addr_obj(
43
+ :address => '2517 Surfwood Dr',
44
+ :city => 'Las Vegas',
45
+ :state => 'NV',
46
+ :zip => '89128'
47
+ )
48
+ assert_equal '89128718217', valid_address.delivery_point
49
+ end
50
+ end
51
+
52
+ describe 'number of days till licence expires' do
53
+ it 'checks if we have more than 30 days till license expiration date' do
54
+ skip "Not run in mock mode" unless Melissa.config.mode == :live
55
+ valid_address = Melissa.addr_obj(
56
+ :address => '2517 Surfwood Dr',
57
+ :city => 'Las Vegas',
58
+ :state => 'NV',
59
+ :zip => '89128'
60
+ )
61
+ assert_operator 30, :<, valid_address.class.days_until_license_expiration
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "mock mode" do
67
+ before do
68
+ Melissa.config.mode = :mock
69
+ end
70
+ describe "valid?" do
71
+ it 'handles valid data' do
72
+ valid_address = Melissa.addr_obj(
73
+ :address => '9802 Brompton Dr',
74
+ :city => 'Tampa',
75
+ :state => 'Fl',
76
+ :zip => '33626'
77
+ )
78
+ assert valid_address.valid?
79
+ assert_equal '9802 Brompton Dr', valid_address.address
80
+ assert_equal 'Tampa', valid_address.city
81
+ assert_equal '33626123426', valid_address.delivery_point
82
+ end
83
+
84
+ it 'flags invalid data' do
85
+ # Zip points to Schenectady, NY
86
+ invalid_address = Melissa.addr_obj(
87
+ :address => '123 Who Dr',
88
+ :city => 'WhoVille',
89
+ :state => 'IN',
90
+ :zip => ''
91
+ )
92
+ assert !invalid_address.valid?
93
+ end
94
+ end
95
+
96
+ describe "delivery_point" do
97
+ it 'sets delivery point for valid data' do
98
+ valid_address = Melissa.addr_obj(
99
+ :address => '9802 Brompton Dr',
100
+ :city => 'Tampa',
101
+ :state => 'Fl',
102
+ :zip => '33626'
103
+ )
104
+ assert_equal '33626123426', valid_address.delivery_point
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,65 @@
1
+ #require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+ require 'test_helper'
3
+
4
+ class GeoPointTest < Minitest::Test
5
+
6
+ describe Melissa::GeoPoint do
7
+ before do
8
+ Melissa.config.mode = :live if Melissa.config.addr_obj_lib_loaded
9
+ end
10
+
11
+ describe 'valid?' do
12
+ it 'creates valid GeoPoint object from valid Address Object' do
13
+ skip "Not run in mock mode" unless Melissa.config.mode == :live
14
+ valid_addr_obj = Melissa.addr_obj(
15
+ :address => '2517 SURFWOOD DR',
16
+ :city => 'LAS VEGAS',
17
+ :state => 'NV',
18
+ :zip => '89128'
19
+ )
20
+ geo_point_obj = Melissa.geo_point(valid_addr_obj)
21
+ assert geo_point_obj.valid?
22
+ assert_includes 36.2..36.3, geo_point_obj.latitude
23
+ assert_includes -115.3..-115.2, geo_point_obj.longitude
24
+ # offset = Time.now.in_time_zone('US/Eastern').dst? ? 240 : 300
25
+ # assert_equal offset, geo_point.time_zone_offset
26
+ #For the address above:
27
+ #g.time_zone_offset
28
+ #=> 480
29
+ end
30
+ it 'creates valid GeoPoint object from the Hash' do
31
+ skip "Not run in mock mode" unless Melissa.config.mode == :live
32
+ geo_point_obj= Melissa.geo_point(
33
+ :zip => '89128',
34
+ :plus4 => '7182',
35
+ :delivery_point_code => '17'
36
+ )
37
+
38
+ assert geo_point_obj.valid?
39
+ assert_includes 36.2..36.3, geo_point_obj.latitude
40
+ assert_includes -115.3..-115.2, geo_point_obj.longitude
41
+ # offset = Time.now.in_time_zone('US/Eastern').dst? ? 240 : 300
42
+ # assert_equal offset, geo_point.time_zone_offset
43
+ #For the address above:
44
+ #g.time_zone_offset
45
+ #=> 480
46
+ end
47
+ end
48
+
49
+ describe 'number of days till licence expires' do
50
+ it 'checks if we have more than 30 days till license expiration date' do
51
+ skip "Not run in mock mode" unless Melissa.config.mode == :live
52
+ valid_addr_obj = Melissa.addr_obj(
53
+ :address => '2517 SURFWOOD DR',
54
+ :city => 'LAS VEGAS',
55
+ :state => 'NV',
56
+ :zip => '89128'
57
+ )
58
+ geo_point = Melissa.geo_point(valid_addr_obj)
59
+ assert_operator 30, :<, geo_point.class.days_until_license_expiration
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+
@@ -0,0 +1,76 @@
1
+ require 'test_helper'
2
+
3
+ class MelissaTest < Minitest::Test
4
+
5
+ describe 'Melissa.addr_obj' do
6
+ before do
7
+ Melissa.config.mode = :live if Melissa.config.addr_obj_lib_loaded
8
+ end
9
+
10
+ describe "live mode" do
11
+ it 'initializes AddrObjLive object' do
12
+ skip "Not run in mock mode" unless Melissa.config.mode == :live
13
+ valid_address = Melissa.addr_obj(
14
+ :address => '9802 Brompton Dr',
15
+ :city => 'Tampa',
16
+ :state => 'Fl',
17
+ :zip => '33626'
18
+ )
19
+ assert_kind_of Melissa::AddrObjLive, valid_address
20
+ end
21
+ end
22
+
23
+ describe "mock mode" do
24
+ before do
25
+ Melissa.config.mode = :mock
26
+ end
27
+
28
+ it 'initializes AddrObjMock object' do
29
+ valid_address = Melissa.addr_obj(
30
+ :address => '9802 Brompton Dr',
31
+ :city => 'Tampa',
32
+ :state => 'Fl',
33
+ :zip => '33626'
34
+ )
35
+ assert_kind_of Melissa::AddrObjMock, valid_address
36
+ end
37
+ end
38
+ end
39
+
40
+ describe 'Melissa.geo_point' do
41
+ before do
42
+ Melissa.config.mode = :live if Melissa.config.addr_obj_lib_loaded
43
+ end
44
+
45
+ describe "live mode" do
46
+ it 'initializes GeoPointLive object' do
47
+ skip "Not run in mock mode" unless Melissa.config.mode == :live
48
+ valid_addr_obj = Melissa.addr_obj(
49
+ :address => '9802 Brompton Dr',
50
+ :city => 'Tampa',
51
+ :state => 'Fl',
52
+ :zip => '33626'
53
+ )
54
+ geo_point_obj = Melissa.geo_point(valid_addr_obj)
55
+ assert_kind_of Melissa::GeoPointLive, geo_point_obj
56
+ end
57
+ end
58
+
59
+ describe "mock mode" do
60
+ before do
61
+ Melissa.config.mode = :mock
62
+ end
63
+
64
+ it 'initializes GeoPointMock object' do
65
+ valid_addr_obj = Melissa.addr_obj(
66
+ :address => '9802 Brompton Dr',
67
+ :city => 'Tampa',
68
+ :state => 'Fl',
69
+ :zip => '33626'
70
+ )
71
+ geo_point_obj = Melissa.geo_point(valid_addr_obj)
72
+ assert_kind_of Melissa::GeoPointMock, geo_point_obj
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,3 @@
1
+ require 'melissa'
2
+ require 'minitest/autorun'
3
+ require 'minitest/pride'
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: melissa
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Brad Pardee
8
+ - Svetlana Marinskaya
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-04-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: minitest
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: ffi
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ description: Configurable interface to Melissa Data Address and GeoPoint objects
57
+ email:
58
+ - bradpardee@gmail.com
59
+ - svetlana.marinskaya@gmail.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - ".jruby-version"
66
+ - ".ruby-version"
67
+ - Gemfile
68
+ - Gemfile.lock
69
+ - LICENSE
70
+ - README.md
71
+ - Rakefile
72
+ - config/melissa
73
+ - lib/melissa.rb
74
+ - lib/melissa/addr_obj.rb
75
+ - lib/melissa/addr_obj_live.rb
76
+ - lib/melissa/addr_obj_mock.rb
77
+ - lib/melissa/config.rb
78
+ - lib/melissa/geo_point.rb
79
+ - lib/melissa/geo_point_live.rb
80
+ - lib/melissa/geo_point_mock.rb
81
+ - lib/melissa/railtie.rb
82
+ - lib/melissa/version.rb
83
+ - melissa.gemspec
84
+ - test/addr_obj_test.rb
85
+ - test/geo_point_test.rb
86
+ - test/melissa_test.rb
87
+ - test/test_helper.rb
88
+ homepage: https://github.com/smarinskaya/Melissa
89
+ licenses: []
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.2.2
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Melissa allows you to use ruby wrappers for Melissa Data's AddrObj and GeoPoint
111
+ objects or use the mock objects depending on configuration.
112
+ test_files:
113
+ - test/addr_obj_test.rb
114
+ - test/geo_point_test.rb
115
+ - test/melissa_test.rb
116
+ - test/test_helper.rb