melissa 0.0.1

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