torasup 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,2 @@
1
+ rvm:
2
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in torasup.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 David Wilkie
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.
data/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # Torasup
2
+
3
+ Retuns metadata about a phone number such as operator info, area code and more.
4
+
5
+ [![Build Status](https://travis-ci.org/dwilkie/torasup.png)](https://travis-ci.org/dwilkie/torasup)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'torasup'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install torasup
20
+
21
+ ## Usage
22
+
23
+ ### Examples
24
+
25
+ $ irb
26
+
27
+ > require 'torasup'
28
+ > pn = Torasup::PhoneNumber.new("+855 (0) 62 451 234")
29
+
30
+ > pn.number
31
+ => "85562451234"
32
+
33
+ > pn.country_code
34
+ => "855"
35
+
36
+ > pn.country_id
37
+ => "kh"
38
+
39
+ > pn.area_code
40
+ => "62"
41
+
42
+ > pn.prefix
43
+ => "45"
44
+
45
+ > pn.local_number
46
+ => "1234"
47
+
48
+ > loc = pn.location
49
+ > loc.area
50
+ => "Kampong Thom"
51
+
52
+ > op = pn.operator
53
+
54
+ > op.id
55
+ => "smart"
56
+
57
+ > op.name
58
+ => "Smart"
59
+
60
+ ## Configuration
61
+
62
+ ### Overriding Data
63
+
64
+ Sometimes it maybe necessary to override the data that Torasup provides. For example you may want to provide custom attributes for different operators. In order to achieve this you can provide a custom [psdn](http://en.wikipedia.org/wiki/Public_switched_telephone_network) data file. See the format of the [pstn data files](https://github.com/dwilkie/torasup/tree/master/lib/torasup/data) for more info. e.g.
65
+
66
+ # my_pstn_data.yaml
67
+ ---
68
+ kh:
69
+ area_codes:
70
+ "45": "New Province"
71
+ operators:
72
+ hello:
73
+ metadata:
74
+ name: Hello
75
+ my_custom_property: hello-foo
76
+ prefixes:
77
+ - '15'
78
+ - '16'
79
+ - '81'
80
+ - '87'
81
+ area_code_prefixes:
82
+ - '45'
83
+
84
+ > Torasup.configure do |config|
85
+ > custom_pstn_data_file = "my_pstn_data.yaml"
86
+ > end
87
+
88
+ > pn = Torasup::PhoneNumber.new("+855 (0) 62 451 234")
89
+ > op = pn.operator
90
+
91
+ > op.id
92
+ => "hello"
93
+
94
+ > op.name
95
+ => "Hello"
96
+
97
+ > op.my_custom_property
98
+ => "hello-foo"
99
+
100
+ ### Registering Operators
101
+
102
+ Sometimes you may only be interested in certain prefixes. For example let's say you want to match phone numbers from a certain operator from the database. You can register operators for this purpose. e.g.
103
+
104
+ > Torasup.configure do |config|
105
+ > register_operators("kh", "metfone")
106
+ > end
107
+
108
+ > Torasup::Operator.registered_prefixes
109
+ => ["85597", "85588"]
110
+
111
+ ### Default Operators
112
+
113
+ By default the following counties will take precedence: `["US", "GB", "AU", "IT", "RU", "NO"]`. This means that `Torasup::PhoneNumber.new(+1 415-234 567).country_id` will return `"us"` and not `ca`. To override use the following configuration setting.
114
+
115
+ > Torasup.configure do |config|
116
+ > config.default_countries = ["CA"]
117
+ > end
118
+
119
+ Now `Torasup::PhoneNumber.new(+1 415-234 567).country_id` will return `"ca"`
120
+
121
+ ## Contributing
122
+
123
+ 1. Fork it
124
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
125
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
126
+ 4. Push to the branch (`git push origin my-new-feature`)
127
+ 5. Create new Pull Request
128
+
129
+ ### Data
130
+
131
+ When contributing data please ensure that you create or edit an entry in the [pstn spec](https://github.com/dwilkie/torasup/tree/master/spec/torasup/spec/support_pstn_spec.rb). This ensures the integrity of the data.
132
+
133
+ Please also include a link to Wikipedia article which verifies your data. See the [current psdn spec](https://github.com/dwilkie/torasup/blob/master/spec/support/pstn_spec.yaml) for an example that links to [Wikipedia](http://en.wikipedia.org/wiki/Telecommunications_in_Cambodia#Mobile_networks).
134
+
135
+ If you obtained operator prefixes from another source please clearly add these prefixes to the appropriate Wikipedia article and reference it if necessary. This helps ensure the accuracy of the gem.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake'
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc "Run all examples"
7
+ RSpec::Core::RakeTask.new(:spec) do |t|
8
+ t.rspec_opts = %w[--color]
9
+ end
10
+
11
+ task :default => [:spec]
@@ -0,0 +1,32 @@
1
+ class Configuration
2
+ DEFAULT_COUNTRIES = ["US", "GB", "AU", "IT", "RU", "NO"]
3
+ attr_accessor :registered_operators, :default_countries, :custom_pstn_data_file
4
+
5
+ def initialize
6
+ @default_countries = DEFAULT_COUNTRIES
7
+ end
8
+
9
+ def default_countries=(value)
10
+ @default_countries = value
11
+ Torasup.load_international_dialing_codes!
12
+ end
13
+
14
+ def custom_pstn_data_file=(value)
15
+ @custom_pstn_data_file = value
16
+ Torasup.load_pstn_data!
17
+ end
18
+
19
+ def register_operators(country_code, *operators)
20
+ registered_operators[country_code] = operators
21
+ Torasup.load_pstn_data!
22
+ end
23
+
24
+ def registered_operators=(value)
25
+ @registered_operators = value
26
+ Torasup.load_pstn_data!
27
+ end
28
+
29
+ def registered_operators
30
+ @registered_operators ||= {}
31
+ end
32
+ end
@@ -0,0 +1,89 @@
1
+ ---
2
+ kh:
3
+ # http://en.wikipedia.org/wiki/Telephone_numbers_in_Cambodia
4
+ international_dialing_code: "855"
5
+ area_codes:
6
+ "23": "Phnom Penh"
7
+ "24": "Kandal"
8
+ "25": "Kampong Speu"
9
+ "26": "Kampong Chhnang"
10
+ "32": "Takeo"
11
+ "33": "Kampot"
12
+ "34": "Sihanoukville"
13
+ "35": "Koh Kong"
14
+ "36": "Kep"
15
+ "42": "Kampong Cham"
16
+ "43": "Prey Veng"
17
+ "44": "Svay Rieng"
18
+ "52": "Pursat"
19
+ "53": "Battambang"
20
+ "54": "Banteay Meanchey"
21
+ "55": "Pailin"
22
+ "62": "Kampong Thom"
23
+ "63": "Siem Reap"
24
+ "64": "Preah Vihear"
25
+ "65": "Oddar Meanchey"
26
+ "72": "Kratie"
27
+ "73": "Mondulkiri"
28
+ "74": "Stung Treng"
29
+ "75": "Ratanakiri"
30
+ operators:
31
+ # http://en.wikipedia.org/wiki/Telecommunications_in_Cambodia#Mobile_networks
32
+ smart:
33
+ metadata:
34
+ name: "Smart"
35
+ prefixes:
36
+ - "10"
37
+ - "15"
38
+ - "16"
39
+ - "69"
40
+ - "70"
41
+ - "81"
42
+ - "86"
43
+ - "87"
44
+ - "93"
45
+ - "96"
46
+ - "98"
47
+ area_code_prefixes:
48
+ - "45"
49
+ beeline:
50
+ metadata:
51
+ name: "Beeline"
52
+ prefixes:
53
+ - "60"
54
+ - "66"
55
+ - "67"
56
+ - "68"
57
+ - "90"
58
+ area_code_prefixes:
59
+ - "46"
60
+ mobitel:
61
+ metadata:
62
+ name: "Mobitel"
63
+ prefixes:
64
+ - '12'
65
+ - '17'
66
+ - '77'
67
+ - '78'
68
+ - '89'
69
+ - '92'
70
+ - '95'
71
+ - '11'
72
+ - '61'
73
+ - '76'
74
+ - '85'
75
+ - '99'
76
+ metfone:
77
+ metadata:
78
+ name: "Metfone"
79
+ prefixes:
80
+ - '97'
81
+ - '88'
82
+ qb:
83
+ metadata:
84
+ name: "Qb"
85
+ prefixes:
86
+ - '13'
87
+ - '80'
88
+ - '83'
89
+ - '84'
@@ -0,0 +1,11 @@
1
+ module Torasup
2
+ class Location
3
+ attr_accessor :country_id, :area_code, :area
4
+
5
+ def initialize(country_id, area_code)
6
+ @country_id = country_id
7
+ @area = Torasup.area_code(country_id, area_code)
8
+ @area_code = area_code if @area
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,42 @@
1
+ module Torasup
2
+ class Operator
3
+ attr_accessor :prefix, :local_number, :area_code, :country_code
4
+
5
+ def initialize(country_code, area_code_or_prefix, unresolved_local_number)
6
+ @country_code = country_code
7
+ parse_phone_number(area_code_or_prefix, unresolved_local_number)
8
+ end
9
+
10
+ def method_missing(method)
11
+ Torasup.prefix_data(full_prefix)[method.to_s]
12
+ end
13
+
14
+ def self.registered_prefixes
15
+ Torasup.registered_prefixes
16
+ end
17
+
18
+ private
19
+
20
+ def parse_phone_number(area_code_or_prefix, unresolved_local_number)
21
+ if Torasup.prefix_data(full_prefix(area_code_or_prefix, local_number_parts(unresolved_local_number)[0])).any?
22
+ @area_code = area_code_or_prefix
23
+ @prefix = local_number_parts(unresolved_local_number)[0]
24
+ @local_number = local_number_parts(unresolved_local_number)[1]
25
+ elsif Torasup.prefix_data(full_prefix(area_code_or_prefix)).any?
26
+ @prefix = area_code_or_prefix
27
+ @local_number = unresolved_local_number
28
+ else
29
+ @local_number = area_code_or_prefix + unresolved_local_number
30
+ end
31
+ end
32
+
33
+ def local_number_parts(number)
34
+ [number[0..1], number[2..-1]]
35
+ end
36
+
37
+ def full_prefix(*parts)
38
+ parts = [@area_code, @prefix] if parts.empty?
39
+ @country_code + parts.join
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,29 @@
1
+ module Torasup
2
+ class PhoneNumber
3
+ attr_reader :number, :country_code, :country_id, :area_code, :prefix, :local_number, :location, :operator
4
+
5
+ def initialize(phone_number)
6
+ parse_phone_number(phone_number)
7
+ end
8
+
9
+ private
10
+
11
+ def parse_phone_number(number)
12
+ @number = Phony.normalize(number)
13
+ number_parts = split_number
14
+ @country_code = number_parts.shift
15
+ @country_id = Torasup.country_id(@country_code)
16
+ area_code_or_prefix = number_parts.shift
17
+ local_number = number_parts.join
18
+ @location = Location.new(@country_id, area_code_or_prefix)
19
+ @area_code = @location.area_code
20
+ @operator = Operator.new(@country_code, area_code_or_prefix, local_number)
21
+ @prefix = @operator.prefix
22
+ @local_number = operator.local_number
23
+ end
24
+
25
+ def split_number
26
+ Phony.split(@number).reject { |part| part == false }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module Torasup
2
+ VERSION = "0.0.1"
3
+ end
data/lib/torasup.rb ADDED
@@ -0,0 +1,131 @@
1
+ require "torasup/version"
2
+ require "torasup/configuration"
3
+ require "torasup/phone_number"
4
+ require "torasup/operator"
5
+ require "torasup/location"
6
+
7
+ module Torasup
8
+ require 'yaml'
9
+ require 'phony'
10
+ require 'countries'
11
+ require 'deep_merge/rails_compat'
12
+
13
+ class << self
14
+ def configure(&block)
15
+ yield(configuration)
16
+ end
17
+
18
+ def load_international_dialing_codes!
19
+ @international_dialing_codes = {}
20
+ ISO3166::Country.all.each do |name, country_id|
21
+ dialing_code = ISO3166::Country[country_id].country_code
22
+ @international_dialing_codes[dialing_code] = country_id unless @international_dialing_codes[dialing_code] && !configuration.default_countries.include?(country_id)
23
+ end
24
+ end
25
+
26
+ def load_pstn_data!
27
+ @pstn_data = load_yaml_file(File.join(File.dirname(__FILE__), 'torasup/data/pstn.yaml')).deeper_merge(
28
+ load_yaml_file(configuration.custom_pstn_data_file)
29
+ )
30
+ load_pstn_prefixes!
31
+ end
32
+
33
+ def country_id(country_code)
34
+ @international_dialing_codes[country_code].downcase if @international_dialing_codes[country_code]
35
+ end
36
+
37
+ def area_code(country_id, code)
38
+ area_codes(country_id)[code]
39
+ end
40
+
41
+ def prefix_data(prefix)
42
+ @pstn_prefixes[prefix] || {}
43
+ end
44
+
45
+ def registered_prefixes
46
+ @registered_pstn_prefixes.keys
47
+ end
48
+
49
+ private
50
+
51
+ def load_pstn_prefixes!
52
+ @pstn_prefixes = {}
53
+ @registered_pstn_prefixes = {}
54
+ @pstn_data.each do |country_id, country_properties|
55
+ operators(country_id).each do |operator, operator_properties|
56
+ operator_prefixes(country_id, operator).each do |operator_prefix, prefix_data|
57
+ prefix_properties = operator_metadata(country_id, operator).merge(prefix_data)
58
+ @pstn_prefixes[operator_prefix] = prefix_properties
59
+ @registered_pstn_prefixes[operator_prefix] = prefix_properties if operator_registered?(country_id, operator)
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def configuration
66
+ @configuration ||= Configuration.new
67
+ end
68
+
69
+ def load_yaml_file(file_to_load)
70
+ file_to_load ? YAML.load_file(file_to_load) : {}
71
+ end
72
+
73
+ def operator_registered?(country_id, operator)
74
+ (configuration.registered_operators[country_id] || []).include?(operator)
75
+ end
76
+
77
+ def country_data(country_id)
78
+ @pstn_data[country_id] || {}
79
+ end
80
+
81
+ def international_dialing_code(country_id)
82
+ country_data(country_id)["international_dialing_code"]
83
+ end
84
+
85
+ def area_codes(country_id)
86
+ country_data(country_id)["area_codes"] || {}
87
+ end
88
+
89
+ def operators(country_id)
90
+ country_data(country_id)["operators"] || {}
91
+ end
92
+
93
+ def operator_data(country_id, operator)
94
+ operators(country_id)[operator] || {}
95
+ end
96
+
97
+ def operator_metadata(country_id, operator)
98
+ {"id" => operator}.merge(operator_data(country_id, operator)["metadata"] || {})
99
+ end
100
+
101
+ def operator_area_code_prefixes(country_id, operator)
102
+ operator_data(country_id, operator)["area_code_prefixes"] || {}
103
+ end
104
+
105
+ def operator_mobile_prefixes(country_id, operator)
106
+ full_prefixes = {}
107
+ mobile_prefixes = operator_data(country_id, operator)["prefixes"] || {}
108
+ mobile_prefixes.each do |mobile_prefix|
109
+ full_prefixes[operator_full_prefix(country_id, mobile_prefix)] = {"prefix" => mobile_prefix}
110
+ end
111
+ full_prefixes
112
+ end
113
+
114
+ def operator_full_prefix(country_id, *prefixes)
115
+ international_dialing_code(country_id) + prefixes.join
116
+ end
117
+
118
+ def operator_prefixes(country_id, operator)
119
+ operator_prefixes = operator_mobile_prefixes(country_id, operator)
120
+ operator_area_code_prefixes(country_id, operator).each do |operator_area_code_prefix|
121
+ area_codes(country_id).each do |area_code, area|
122
+ operator_prefixes[operator_full_prefix(country_id, area_code, operator_area_code_prefix)] = {"prefix" => operator_area_code_prefix}
123
+ end
124
+ end
125
+ operator_prefixes
126
+ end
127
+ end
128
+
129
+ load_international_dialing_codes!
130
+ load_pstn_data!
131
+ end
@@ -0,0 +1,6 @@
1
+ require 'torasup'
2
+
3
+ RSpec.configure do |config|
4
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
5
+ config.treat_symbols_as_metadata_keys_with_true_values = true
6
+ end
@@ -0,0 +1,17 @@
1
+ # this file is a sample file which can be used to override the standard pstn data
2
+ ---
3
+ kh:
4
+ area_codes:
5
+ "45": "New Province"
6
+ operators:
7
+ hello:
8
+ metadata:
9
+ name: Hello
10
+ my_custom_property: hello-foo
11
+ prefixes:
12
+ - '15'
13
+ - '16'
14
+ - '81'
15
+ - '87'
16
+ area_code_prefixes:
17
+ - '45'
@@ -0,0 +1,19 @@
1
+ # this file is used to test the functionality of overriding the standard pstn data
2
+ # with the data in spec/support/custom_pstn.data
3
+
4
+ ---
5
+ kh:
6
+ area_codes:
7
+ '45': New Province
8
+ operators:
9
+ hello:
10
+ assertions:
11
+ name: Hello
12
+ my_custom_property: hello-foo
13
+ prefixes:
14
+ - '15'
15
+ - '16'
16
+ - '81'
17
+ - '87'
18
+ area_code_prefixes:
19
+ - '45'
@@ -0,0 +1,142 @@
1
+ module PstnHelpers
2
+ private
3
+
4
+ def load_yaml_file(file_to_load)
5
+ file_to_load ? YAML.load_file(File.join(File.dirname(__FILE__), "/#{file_to_load}")) : {}
6
+ end
7
+
8
+ def pstn_data(with_custom_pstn_data = false)
9
+ data = load_yaml_file("pstn_spec.yaml")
10
+ with_custom_pstn_data ? data.deeper_merge(load_yaml_file("custom_pstn_spec.yaml")) : data
11
+ end
12
+
13
+ def with_phone_numbers(options = {}, &block)
14
+ phone_number_assertions = {}
15
+ with_pstn_data(options) do |country_id, country_data, country_prefix|
16
+ area_code_or_prefix = (10 + rand(100 - 10)).to_s
17
+ local_number = [(100 + rand(1000 - 100)).to_s, (100 + rand(1000 - 100)).to_s]
18
+ sample_number = "+#{country_prefix} (0) #{area_code_or_prefix}-#{local_number[0]}-#{local_number[1]}"
19
+ normalized_number = country_prefix + area_code_or_prefix + local_number[0] + local_number[1]
20
+ phone_number_assertions[sample_number] = {
21
+ "number" => normalized_number, "country_id" => country_id, "country_code" => country_prefix,
22
+ "area_code_or_prefix" => area_code_or_prefix, "local_number" => local_number.join
23
+ }
24
+ end
25
+ phone_number_assertions.each do |sample_number, assertions|
26
+ yield sample_number, assertions
27
+ end
28
+ end
29
+
30
+ def with_locations(options = {}, &block)
31
+ location_assertions = {}
32
+ with_pstn_data(options) do |country_id, country_data|
33
+ default_assertions = {"country_id" => country_id}
34
+ location_assertions[country_id] = {}
35
+ country_data["area_codes"].each do |area_code, area|
36
+ location_assertions[country_id][area_code] = default_assertions.merge("area_code" => area_code, "area" => area)
37
+ end
38
+ end
39
+ location_assertions.each do |country_id, area_code_assertions|
40
+ area_code_assertions.each do |area_code, assertions|
41
+ yield country_id, area_code, assertions
42
+ end
43
+ end
44
+ end
45
+
46
+ def with_operators(options = {}, &block)
47
+ operator_assertions = {}
48
+ with_pstn_data(options) do |country_id, country_data, country_prefix|
49
+ operator_assertions[country_prefix] = {}
50
+ default_assertions = {"country_code" => country_prefix}
51
+ with_operator_data(country_data) do |operator, operator_data|
52
+ default_assertions.merge!("id" => operator).merge!(operator_data["assertions"])
53
+ with_operator_area_codes(country_data, operator_data) do |area_code_prefix, area_code, area|
54
+ operator_assertions[country_prefix][area_code] = {}
55
+ local_number = ("0" * (6 - area_code_prefix.length))
56
+ unresolved_number = area_code_prefix + local_number
57
+ operator_assertions[country_prefix][area_code][unresolved_number] = default_assertions.merge(
58
+ "area_code" => area_code, "prefix" => area_code_prefix, "local_number" => local_number
59
+ )
60
+ end
61
+ with_operator_prefixes(operator_data) do |prefix|
62
+ operator_assertions[country_prefix][prefix] = {}
63
+ local_number = ("0" * 6)
64
+ operator_assertions[country_prefix][prefix][local_number] = default_assertions.merge(
65
+ "prefix" => prefix, "area_code" => nil
66
+ )
67
+ end
68
+ end
69
+ end
70
+ operator_assertions.each do |country_prefix, country_assertions|
71
+ country_assertions.each do |area_code_or_prefix, area_code_or_prefix_assertions|
72
+ area_code_or_prefix_assertions.each do |unresolved_local_number, assertions|
73
+ yield country_prefix, area_code_or_prefix, unresolved_local_number, assertions
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ def sample_operator
80
+ country = pstn_data.first
81
+ [country.first, country.last["operators"].first.first]
82
+ end
83
+
84
+ def prefixes(country_id, operator)
85
+ prefix_data = []
86
+ country_data = pstn_data[country_id]
87
+ country_prefix = country_data["prefix"]
88
+ operator_data = country_data["operators"][operator]
89
+ with_operator_area_codes(country_data, operator_data) do |area_code_prefix, area_code|
90
+ prefix_data << (country_prefix + area_code + area_code_prefix)
91
+ end
92
+ with_operator_prefixes(operator_data) do |prefix|
93
+ prefix_data << (country_prefix + prefix)
94
+ end
95
+ prefix_data
96
+ end
97
+
98
+ def with_pstn_data(options = {}, &block)
99
+ pstn_data(options[:with_custom_pstn_data]).each do |country_id, country_data|
100
+ yield country_id, country_data, country_data["prefix"]
101
+ end
102
+ end
103
+
104
+ def with_operator_data(country_data, &block)
105
+ country_data["operators"].each do |operator, operator_data|
106
+ yield operator, operator_data
107
+ end
108
+ end
109
+
110
+ def with_operator_prefixes(operator_data, &block)
111
+ operator_data["prefixes"].each do |prefix|
112
+ yield prefix
113
+ end
114
+ end
115
+
116
+ def with_operator_area_codes(country_data, operator_data, &block)
117
+ (operator_data["area_code_prefixes"] || {}).each do |area_code_prefix|
118
+ country_data["area_codes"].each do |area_code, area|
119
+ yield area_code_prefix, area_code, area
120
+ end
121
+ end
122
+ end
123
+
124
+ def configure_with_custom_data(custom_data = true)
125
+ custom_data_file = File.join(File.dirname(__FILE__), "../support", "/custom_pstn.yaml") if custom_data
126
+ Torasup.configure do |config|
127
+ config.custom_pstn_data_file = custom_data_file
128
+ end
129
+ end
130
+
131
+ def configure_registered_operators(country_id, *operators)
132
+ Torasup.configure do |config|
133
+ config.register_operators(country_id, *operators)
134
+ end
135
+ end
136
+
137
+ def clear_registered_operators
138
+ Torasup.configure do |config|
139
+ config.registered_operators = {}
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,91 @@
1
+ # this file is used to test the gem against the data in lib/torasup/data/pstn.yaml
2
+ # add examples to this file in order to test the integrity of the data
3
+ ---
4
+ kh:
5
+ # http://en.wikipedia.org/wiki/Telephone_numbers_in_Cambodia
6
+ prefix: '855'
7
+ area_codes:
8
+ '23': Phnom Penh
9
+ '24': Kandal
10
+ '25': Kampong Speu
11
+ '26': Kampong Chhnang
12
+ '32': Takeo
13
+ '33': Kampot
14
+ '34': Sihanoukville
15
+ '35': Koh Kong
16
+ '36': Kep
17
+ '42': Kampong Cham
18
+ '43': Prey Veng
19
+ '44': Svay Rieng
20
+ '52': Pursat
21
+ '53': Battambang
22
+ '54': Banteay Meanchey
23
+ '55': Pailin
24
+ '62': Kampong Thom
25
+ '63': Siem Reap
26
+ '64': Preah Vihear
27
+ '65': Oddar Meanchey
28
+ '72': Kratie
29
+ '73': Mondulkiri
30
+ '74': Stung Treng
31
+ '75': Ratanakiri
32
+ operators:
33
+ # http://en.wikipedia.org/wiki/Telecommunications_in_Cambodia#Mobile_networks
34
+ smart:
35
+ assertions:
36
+ name: Smart
37
+ prefixes:
38
+ - '10'
39
+ - '15'
40
+ - '16'
41
+ - '69'
42
+ - '70'
43
+ - '81'
44
+ - '86'
45
+ - '87'
46
+ - '93'
47
+ - '96'
48
+ - '98'
49
+ area_code_prefixes:
50
+ - '45'
51
+ beeline:
52
+ assertions:
53
+ name: Beeline
54
+ prefixes:
55
+ - '60'
56
+ - '66'
57
+ - '67'
58
+ - '68'
59
+ - '90'
60
+ area_code_prefixes:
61
+ - '46'
62
+ mobitel:
63
+ assertions:
64
+ name: Mobitel
65
+ prefixes:
66
+ - '12'
67
+ - '17'
68
+ - '77'
69
+ - '78'
70
+ - '89'
71
+ - '92'
72
+ - '95'
73
+ - '11'
74
+ - '61'
75
+ - '76'
76
+ - '85'
77
+ - '99'
78
+ metfone:
79
+ assertions:
80
+ name: Metfone
81
+ prefixes:
82
+ - '97'
83
+ - '88'
84
+ qb:
85
+ assertions:
86
+ name: Qb
87
+ prefixes:
88
+ - '13'
89
+ - '80'
90
+ - '83'
91
+ - '84'
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe Torasup do
4
+ describe ".configure" do
5
+ describe "#registered_operators=" do
6
+ before do
7
+ Torasup.stub(:load_pstn_data!)
8
+ end
9
+
10
+ it "should set the registered operators and clear" do
11
+ Torasup.configure do |config|
12
+ Torasup.should_receive(:load_pstn_data!)
13
+ config.registered_operators.should == {}
14
+ config.registered_operators = {"foo" => "bar"}
15
+ config.registered_operators.should == {"foo" => "bar"}
16
+ end
17
+ end
18
+ end
19
+
20
+ describe "#register_operators(country_id, *operators)" do
21
+ before do
22
+ Torasup.stub(:load_pstn_data!)
23
+ end
24
+
25
+ it "should set the registered operators" do
26
+ Torasup.configure do |config|
27
+ Torasup.should_receive(:load_pstn_data!)
28
+ config.registered_operators = {}
29
+ config.register_operators("kh", "smart", "beeline")
30
+ config.registered_operators.should == {"kh" => ["smart", "beeline"]}
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "#default_countries=('['US', 'AU']')" do
36
+ before do
37
+ Torasup.stub(:load_international_dialing_codes!)
38
+ end
39
+
40
+ it "should set the default countries and reload the data" do
41
+ Torasup.configure do |config|
42
+ Torasup.should_receive(:load_international_dialing_codes!)
43
+ config.default_countries.should == ["US", "GB", "AU", "IT", "RU", "NO"]
44
+ config.default_countries = ["US", "GB"]
45
+ config.default_countries.should == ["US", "GB"]
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "#custom_pstn_data_file=('path_to_yaml_file.yaml')" do
51
+ before do
52
+ Torasup.stub(:load_pstn_data!)
53
+ end
54
+
55
+ it "should set a custom pstn data file and reload the data" do
56
+ Torasup.configure do |config|
57
+ Torasup.should_receive(:load_pstn_data!)
58
+ config.custom_pstn_data_file.should be_nil
59
+ config.custom_pstn_data_file = "foo.yaml"
60
+ config.custom_pstn_data_file.should == "foo.yaml"
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ module Torasup
4
+ describe Location do
5
+ include PstnHelpers
6
+
7
+ shared_examples_for "a location" do
8
+ it "should return all the location attributes" do
9
+ with_locations(options) do |country_id, area_code, assertions|
10
+ subject = Location.new(country_id, area_code)
11
+ assertions.each do |method, assertion|
12
+ result = subject.send(method)
13
+ result_error = result.nil? ? "nil" : "'#{result}'"
14
+ result.should(eq(assertion), "expected Location.new('#{country_id}', '#{area_code}').#{method} to return '#{assertion}' but got #{result_error}")
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ context "using the standard data" do
21
+ before do
22
+ configure_with_custom_data(false)
23
+ end
24
+
25
+ it_should_behave_like "a location" do
26
+ let(:options) { {} }
27
+ end
28
+ end
29
+
30
+ context "using overridden data" do
31
+ before do
32
+ configure_with_custom_data
33
+ end
34
+
35
+ it_should_behave_like "a location" do
36
+ let(:options) { { :with_custom_pstn_data => true } }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ module Torasup
4
+ describe Operator do
5
+ include PstnHelpers
6
+
7
+ describe ".registered_prefixes" do
8
+ context "given no operators have been registered" do
9
+ before do
10
+ clear_registered_operators
11
+ end
12
+
13
+ it "should return an empty array" do
14
+ Operator.registered_prefixes.should == []
15
+ end
16
+ end
17
+
18
+ context "given one operator has been registered" do
19
+ let(:operator) { sample_operator }
20
+
21
+ before do
22
+ configure_registered_operators(operator[0], operator[1])
23
+ configure_with_custom_data(false)
24
+ end
25
+
26
+ it "should the prefixes for that operator" do
27
+ Operator.registered_prefixes.should =~ prefixes(operator[0], operator[1])
28
+ end
29
+ end
30
+ end
31
+
32
+ shared_examples_for "an operator" do
33
+ it "should return all the operator metadata" do
34
+ with_operators(options) do |country_code, area_code_or_prefix, unresolved_local_number, assertions|
35
+ subject = Operator.new(country_code, area_code_or_prefix, unresolved_local_number)
36
+ assertions.each do |method, assertion|
37
+ result = subject.send(method)
38
+ result_error = result.nil? ? "nil" : "'#{result}'"
39
+ result.should(eq(assertion), "expected Operator.new('#{country_code}', '#{area_code_or_prefix}', '#{unresolved_local_number}').#{method} to return '#{assertion}' but got #{result_error}")
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ context "using the standard data" do
46
+ before do
47
+ configure_with_custom_data(false)
48
+ end
49
+
50
+ it_should_behave_like "an operator" do
51
+ let(:options) { {} }
52
+ end
53
+ end
54
+
55
+ context "using overridden data" do
56
+ before do
57
+ configure_with_custom_data
58
+ end
59
+
60
+ it_should_behave_like "an operator" do
61
+ let(:options) { { :with_custom_pstn_data => true } }
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ module Torasup
4
+ describe PhoneNumber do
5
+ include PstnHelpers
6
+
7
+ subject { PhoneNumber.new("123456789") }
8
+ let(:location) { mock(Torasup::Location).as_null_object }
9
+ let(:operator) { mock(Torasup::Operator).as_null_object }
10
+
11
+ describe "#location" do
12
+ it "should return an instance of Torasup::Location" do
13
+ subject.location.should be_a(Torasup::Location)
14
+ end
15
+ end
16
+
17
+ describe "#operator" do
18
+ it "should return an instance of Torasup::Operator" do
19
+ subject.operator.should be_a(Torasup::Operator)
20
+ end
21
+ end
22
+
23
+ describe "#area_code" do
24
+ before do
25
+ location.stub(:area_code).and_return("123")
26
+ Torasup::Location.stub(:new).and_return(location)
27
+ end
28
+
29
+ it "should delegate to location" do
30
+ subject.area_code.should == "123"
31
+ end
32
+ end
33
+
34
+ describe "#prefix" do
35
+ before do
36
+ operator.stub(:prefix).and_return("12")
37
+ Torasup::Operator.stub(:new).and_return(operator)
38
+ end
39
+
40
+ it "should delegate to operator" do
41
+ subject.prefix.should == "12"
42
+ end
43
+ end
44
+
45
+ describe "#local_number" do
46
+ before do
47
+ operator.stub(:local_number).and_return("234567")
48
+ Torasup::Operator.stub(:new).and_return(operator)
49
+ end
50
+
51
+ it "should delegate to operator" do
52
+ subject.local_number.should == "234567"
53
+ end
54
+ end
55
+
56
+ shared_examples_for "a phone number" do
57
+
58
+ before do
59
+ Torasup::Location.stub(:new).and_return(location)
60
+ Torasup::Operator.stub(:new).and_return(operator)
61
+ end
62
+
63
+ it "should return all the phone number attributes" do
64
+ with_phone_numbers(options) do |sample_number, assertions|
65
+ area_code_or_prefix = assertions.delete("area_code_or_prefix")
66
+ local_number = assertions.delete("local_number")
67
+
68
+ Torasup::Location.should_receive(:new).with(assertions["country_id"], area_code_or_prefix)
69
+ Torasup::Operator.should_receive(:new).with(assertions["country_code"], area_code_or_prefix, local_number)
70
+
71
+ subject = PhoneNumber.new(sample_number)
72
+
73
+ assertions.each do |method, assertion|
74
+ result = subject.send(method)
75
+ result_error = result.nil? ? "nil" : "'#{result}'"
76
+ result.should(eq(assertion), "expected PhoneNumber.new('#{sample_number}').#{method} to return '#{assertion}' but got #{result_error}")
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ context "using the standard data" do
83
+ before do
84
+ configure_with_custom_data(false)
85
+ end
86
+
87
+ it_should_behave_like "a phone number" do
88
+ let(:options) { {} }
89
+ end
90
+ end
91
+
92
+ context "using overridden data" do
93
+ before do
94
+ configure_with_custom_data
95
+ end
96
+
97
+ it_should_behave_like "a phone number" do
98
+ let(:options) { { :with_custom_pstn_data => true } }
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Torasup do
4
+ end
data/torasup.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'torasup/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "torasup"
8
+ gem.version = Torasup::VERSION
9
+ gem.authors = ["David Wilkie"]
10
+ gem.email = ["dwilkie@gmail.com"]
11
+ gem.description = %q{"Retuns metadata about a phone number such as operator, area code and more"}
12
+ gem.summary = %q{"Retuns metadata about a phone number such as operator, area code and more"}
13
+ gem.homepage = "https://github.com/dwilkie/torasup/"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_runtime_dependency "countries"
21
+ gem.add_runtime_dependency "phony"
22
+ gem.add_runtime_dependency "deep_merge"
23
+
24
+ gem.add_development_dependency "rspec"
25
+ gem.add_development_dependency "rake"
26
+ end
metadata ADDED
@@ -0,0 +1,167 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: torasup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Wilkie
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: countries
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '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: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: phony
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: deep_merge
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: ! '"Retuns metadata about a phone number such as operator, area code
95
+ and more"'
96
+ email:
97
+ - dwilkie@gmail.com
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - .gitignore
103
+ - .travis.yml
104
+ - Gemfile
105
+ - LICENSE.txt
106
+ - README.md
107
+ - Rakefile
108
+ - lib/torasup.rb
109
+ - lib/torasup/configuration.rb
110
+ - lib/torasup/data/pstn.yaml
111
+ - lib/torasup/location.rb
112
+ - lib/torasup/operator.rb
113
+ - lib/torasup/phone_number.rb
114
+ - lib/torasup/version.rb
115
+ - spec/spec_helper.rb
116
+ - spec/support/custom_pstn.yaml
117
+ - spec/support/custom_pstn_spec.yaml
118
+ - spec/support/pstn_helpers.rb
119
+ - spec/support/pstn_spec.yaml
120
+ - spec/torasup/configuration_spec.rb
121
+ - spec/torasup/location_spec.rb
122
+ - spec/torasup/operator_spec.rb
123
+ - spec/torasup/phone_number_spec.rb
124
+ - spec/torasup_spec.rb
125
+ - torasup.gemspec
126
+ homepage: https://github.com/dwilkie/torasup/
127
+ licenses: []
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ! '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ segments:
139
+ - 0
140
+ hash: -1036375537
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ none: false
143
+ requirements:
144
+ - - ! '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ segments:
148
+ - 0
149
+ hash: -1036375537
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 1.8.25
153
+ signing_key:
154
+ specification_version: 3
155
+ summary: ! '"Retuns metadata about a phone number such as operator, area code and
156
+ more"'
157
+ test_files:
158
+ - spec/spec_helper.rb
159
+ - spec/support/custom_pstn.yaml
160
+ - spec/support/custom_pstn_spec.yaml
161
+ - spec/support/pstn_helpers.rb
162
+ - spec/support/pstn_spec.yaml
163
+ - spec/torasup/configuration_spec.rb
164
+ - spec/torasup/location_spec.rb
165
+ - spec/torasup/operator_spec.rb
166
+ - spec/torasup/phone_number_spec.rb
167
+ - spec/torasup_spec.rb