swissmatch-directories 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ Copyright (c) 2012, Stefan Rusterholz <stefan.rusterholz@gmail.com>
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
+
6
+ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
+ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,58 @@
1
+ README
2
+ ======
3
+
4
+
5
+ Summary
6
+ -------
7
+ Query address data from swiss directory providers.
8
+
9
+
10
+ Installation
11
+ ------------
12
+ Install the gem: `gem install swissmatch-directories`
13
+ Depending on how you installed rubygems, you have to use `sudo`:
14
+ `sudo gem install swissmatch-directories`
15
+ In Ruby: `require 'swissmatch/directories'`
16
+
17
+
18
+ Usage
19
+ -----
20
+ require 'swissmatch/directories'
21
+ directories = SwissMatch::Directories.create(:telsearch, api_token: your_token)
22
+ params = {first_name: 'Stefan', last_name: 'Rusterholz'}
23
+ directories.addresses(params).each do |address|
24
+ puts address,""
25
+ end
26
+
27
+
28
+ Relevant Classes and Modules
29
+ ----------------------------
30
+ * __{SwissMatch::Directories}__
31
+ Convenience methods to create and access directory services
32
+ * __{SwissMatch::Directories::Service}__
33
+ The basic API to use directory services
34
+
35
+
36
+ Links
37
+ -----
38
+
39
+ * [Main Project](https://github.com/apeiros/swissmatch)
40
+ * [Online API Documentation](http://rdoc.info/github/apeiros/swissmatch-directories/)
41
+ * [Public Repository](https://github.com/apeiros/swissmatch-directories)
42
+ * [Bug Reporting](https://github.com/apeiros/swissmatch-directories/issues)
43
+ * [RubyGems Site](https://rubygems.org/gems/swissmatch-directories)
44
+ * [Swiss Posts MAT[CH]](http://www.post.ch/match)
45
+
46
+
47
+ License
48
+ -------
49
+
50
+ You can use this code under the {file:LICENSE.txt BSD-2-Clause License}, free of charge.
51
+ If you need a different license, please ask the author.
52
+
53
+
54
+ Credits
55
+ -------
56
+
57
+ * [Simon Hürlimann](https://github.com/huerlisi) for contributions
58
+ * [AWD Switzerland](http://www.awd.ch/) for donating time to work on this gem.
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift(File.expand_path('../rake/lib', __FILE__))
2
+ Dir.glob(File.expand_path('../rake/tasks/**/*.{rake,task,rb}', __FILE__)) do |task_file|
3
+ begin
4
+ import task_file
5
+ rescue LoadError => e
6
+ warn "Failed to load task file #{task_file}"
7
+ warn " #{e.class} #{e.message}"
8
+ warn " #{e.backtrace.first}"
9
+ end
10
+ end
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+
3
+
4
+
5
+ require 'swissmatch/directories/service'
6
+ require 'swissmatch/directories/version'
7
+
8
+
9
+
10
+ # __{SwissMatch::Directories}__
11
+ # Query address data from swiss online directory providers.
12
+ #
13
+ # @note
14
+ # All strings passed to SwissMatch are expected to be utf-8. All strings
15
+ # returned by SwissMatch are also in utf-8.
16
+ #
17
+ module SwissMatch
18
+
19
+ # Query address data from swiss online directory providers.
20
+ #
21
+ # @example Usage
22
+ # require 'swissmatch/directories'
23
+ # directories = SwissMatch::Directories.create(:telsearch, api_token: your_token)
24
+ # params = {first_name: 'Stefan', last_name: 'Rusterholz'}
25
+ # directories.addresses(params).each do |address|
26
+ # puts address,""
27
+ # end
28
+ module Directories
29
+ @services = Hash.new { |hash, key|
30
+ if key.respond_to?(:from_configuration)
31
+ key
32
+ else
33
+ raise ArgumentError, "Unknown service: #{key.inspect}"
34
+ end
35
+ }.merge(
36
+ telsearch: SwissMatch::Directories::TelSearch
37
+ )
38
+
39
+ class <<self
40
+
41
+ # @return [Hash] The available back-ends.
42
+ attr_reader :services
43
+ end
44
+
45
+ # @return [Class] A SwissMatch::Directories::Service compatible service class.
46
+ def self.service(name)
47
+ services[name]
48
+ end
49
+
50
+ # @return [SwissMatch::Directories::Service] A directory service
51
+ def self.create(name, options)
52
+ Service.new(name, options)
53
+ end
54
+ end
55
+
56
+ @directory_service = nil
57
+
58
+ class <<self
59
+
60
+ # @return [SwissMatch::Directories::Service, nil]
61
+ # The directory service used to search for addresses
62
+ # You have to set this one yourself. It exists to provide a standard way to
63
+ #
64
+ attr_accessor :directory_service
65
+ end
66
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+
3
+
4
+
5
+ module SwissMatch
6
+ module Directories
7
+
8
+ # Represents a swiss address. Used by directory service interfaces to return search
9
+ # results.
10
+ Address = Struct.new(:gender, :first_name, :last_name, :maiden_name, :street_name, :street_number, :zip_code, :city) do
11
+
12
+ # @return [String]
13
+ # The street and street number
14
+ def street
15
+ [street_name, street_number].compact.join(" ")
16
+ end
17
+
18
+ # @return [String]
19
+ # The full name, consisting of first_name and family_name.
20
+ def full_name
21
+ "#{first_name} #{family_name}"
22
+ end
23
+
24
+ # @return [String]
25
+ # The full family name, including the maiden name.
26
+ #
27
+ # @note
28
+ # I (stefan.rusterholz@gmail.com) am not sure whether "last_name (-maiden_name)"
29
+ # is the proper form. The output might be changed in a future version
30
+ # The current output is based on how tel.search.ch displays the name.
31
+ def family_name
32
+ maiden_name ? "#{last_name} (-#{maiden_name})" : last_name
33
+ end
34
+
35
+ # @return [String] A halfway readable textual representation
36
+ def to_s
37
+ "#{full_name}\n#{street}\n#{zip_code} #{city}"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+
4
+
5
+ require 'swissmatch/directories/address'
6
+ require 'swissmatch/directories/telsearch'
7
+
8
+
9
+
10
+ module SwissMatch
11
+ module Directories
12
+
13
+ # Common directory service API.
14
+ #
15
+ # @see SwissMatch::Directories Usage examples
16
+ class Service
17
+
18
+ # @param [Class, Symbol, #from_configuration] back_end
19
+ # A valid back-end. Valid in vanilla swissmatch-directories:
20
+ # * :telsearch
21
+ # * SwissMatch::Directories::TelSearch (same as :telsearch)
22
+ # @param [Object] config
23
+ # A back-end specific configuration object.
24
+ def initialize(back_end, config=nil)
25
+ @service = SwissMatch::Directories.service(back_end).from_config(config)
26
+ end
27
+
28
+ # Query for addresses matching a set of given search parameters
29
+ #
30
+ # Note that not all back-ends will treat these parameters with the same strictness.
31
+ # The tel.search.ch back-end for example will search for a last name anywhere in the name.
32
+ #
33
+ # @param [Hash] params
34
+ # The abstract API search parameters.
35
+ # Valid parameters:
36
+ # * :first_name
37
+ # * :family_name
38
+ # * :last_name
39
+ # * :maiden_name
40
+ # * :name
41
+ # * :phone
42
+ # * :street
43
+ # * :street_name
44
+ # * :street_number
45
+ # * :zip_code
46
+ # * :city
47
+ def addresses(params, options={})
48
+ @service.addresses(params, options)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,105 @@
1
+ # encoding: utf-8
2
+
3
+
4
+
5
+ require 'swissmatch/directories/service'
6
+ require 'uri'
7
+ require 'open-uri'
8
+ require 'nokogiri'
9
+
10
+
11
+
12
+ module SwissMatch
13
+ module Directories
14
+
15
+ # A Directory service, using tel.search.ch's API.
16
+ # Also see http://tel.search.ch/api/help
17
+ #
18
+ # You need an API key in order to use this library. You can get one on
19
+ # http://admin.tel.search.ch/api/getkey
20
+ #
21
+ # @see SwissMatch::Directories Usage examples
22
+ class TelSearch
23
+
24
+ # Create a TelSearch instance from the common interface.
25
+ # TelSearch requires the :api_token option to be set.
26
+ def self.from_config(config)
27
+ new(config.fetch(:api_token))
28
+ end
29
+
30
+ # @private
31
+ # XML Namespaces, used to parse the data returned by tel.search.ch
32
+ NS = {'t' => 'http://tel.search.ch/api/spec/result/1.0/'}
33
+
34
+ # @private
35
+ # The url of the API of tel.search.ch
36
+ API_URI = URI.parse('http://tel.search.ch/api')
37
+
38
+ # @param [String] key
39
+ # The API key for the telsearch service.
40
+ # You can get one on http://admin.tel.search.ch/api/getkey
41
+ def initialize(key)
42
+ @key = key
43
+ @uri = API_URI
44
+ end
45
+
46
+ # @private
47
+ # Convert the abstracted APIs options to tel.search.ch's search params
48
+ #
49
+ # @param [Hash] params
50
+ # The abstract API search parameters
51
+ def search_ch_mapping(params)
52
+ {
53
+ :was => params.values_at(:first_name, :family_name, :last_name, :maiden_name, :phone).compact.join(' '),
54
+ :wo => params.values_at(:street, :street_name, :street_number, :zip_code, :city).compact.join(' '),
55
+ }.reject { |k,v| v.empty? }
56
+ end
57
+
58
+ # @see SwissMatch::Directories#addresses
59
+ def addresses(params, options = {})
60
+ return [] if params.empty? # short-cut
61
+
62
+ # tel.search.ch parameters
63
+ search_params = {'key' => @key}
64
+
65
+ # Handle pagination parameters
66
+ per_page = options[:per_page] || 10
67
+ search_params['maxnum'] = per_page
68
+
69
+ page = options[:page] || 1
70
+ pos = (page - 1) * per_page + 1
71
+ search_params['pos'] = pos
72
+
73
+ # Request
74
+ uri = @uri.dup
75
+ uri.query = URI.encode_www_form(search_ch_mapping(params).merge(search_params))
76
+ feed = Nokogiri.XML(open(uri, &:read))
77
+
78
+ # Parse result
79
+ feed.css('entry').map { |entry|
80
+ Address.new(
81
+ nil,
82
+ extract(entry, 't|firstname'),
83
+ extract(entry, 't|name'),
84
+ extract(entry, 't|maidenname'),
85
+ extract(entry, 't|street'),
86
+ extract(entry, 't|streetno'),
87
+ extract(entry, 't|zip', &:to_i),
88
+ extract(entry, 't|city'),
89
+ )
90
+ }
91
+ end
92
+
93
+ private
94
+
95
+ # @private
96
+ # Get the text from a node with the given selector
97
+ def extract(node, selector)
98
+ subnode = node.at_css(selector, NS)
99
+ text = subnode && subnode.text
100
+
101
+ block_given? ? yield(text) : text
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require 'rubygems/version' # newer rubygems use this
5
+ rescue LoadError
6
+ require 'gem/version' # older rubygems use this
7
+ end
8
+
9
+ module SwissMatch
10
+ module Directories
11
+
12
+ # The version of the swissmatch-directories gem.
13
+ Version = Gem::Version.new("0.0.1")
14
+ end
15
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "swissmatch-directories"
5
+ s.version = "0.0.1"
6
+ s.authors = "Stefan Rusterholz"
7
+ s.email = "stefan.rusterholz@gmail.com"
8
+ s.homepage = "http://github.com/apeiros/swissmatch-directories"
9
+
10
+ s.description = <<-DESCRIPTION.gsub(/^ /, '').chomp
11
+ Query address data from swiss directory providers.
12
+ DESCRIPTION
13
+
14
+ s.summary = <<-SUMMARY.gsub(/^ /, '').chomp
15
+ Query address data from swiss directory providers.
16
+ SUMMARY
17
+
18
+ s.files =
19
+ Dir['bin/**/*'] +
20
+ Dir['data/**/*'] +
21
+ Dir['lib/**/*'] +
22
+ Dir['rake/**/*'] +
23
+ Dir['test/**/*'] +
24
+ Dir['*.gemspec'] +
25
+ %w[
26
+ LICENSE.txt
27
+ Rakefile
28
+ README.markdown
29
+ ]
30
+
31
+ if File.directory?('bin') then
32
+ executables = Dir.chdir('bin') { Dir.glob('**/*').select { |f| File.executable?(f) } }
33
+ s.executables = executables unless executables.empty?
34
+ end
35
+
36
+ s.add_dependency "nokogiri", ">= 1.5.0"
37
+
38
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1")
39
+ s.rubygems_version = "1.3.1"
40
+ s.specification_version = 3
41
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: swissmatch-directories
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Stefan Rusterholz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.5.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.5.0
30
+ description: Query address data from swiss directory providers.
31
+ email: stefan.rusterholz@gmail.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - lib/swissmatch/directories/address.rb
37
+ - lib/swissmatch/directories/service.rb
38
+ - lib/swissmatch/directories/telsearch.rb
39
+ - lib/swissmatch/directories/version.rb
40
+ - lib/swissmatch/directories.rb
41
+ - swissmatch-directories.gemspec
42
+ - LICENSE.txt
43
+ - Rakefile
44
+ - README.markdown
45
+ homepage: http://github.com/apeiros/swissmatch-directories
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>'
61
+ - !ruby/object:Gem::Version
62
+ version: 1.3.1
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.24
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Query address data from swiss directory providers.
69
+ test_files: []
70
+ has_rdoc: