opencnam 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2013 Nysa Vann
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # ruby-opencnam
2
+
3
+ A Ruby wrapper for the [OpenCNAM](http://www.opencnam.com/) API service.
4
+
5
+ ruby-opencnam v1.0.0 only supports OpenCNAM API v2. For more information see:
6
+ https://www.opencnam.com/docs/v2
7
+
8
+ ## Installation
9
+
10
+ Install from [RubyGems](http://rubygems.org/):
11
+
12
+ $ gem install opencnam
13
+
14
+ Or include it in your `Gemfile` and install via Bundler's `bundle install`:
15
+
16
+ gem 'opencnam'
17
+
18
+ ## Usage
19
+
20
+ Simplest example:
21
+
22
+ require 'opencnam'
23
+
24
+ client = Opencnam::Client.new
25
+
26
+ client.phone('7731234567')
27
+ # => 'VANN,NYSA'
28
+
29
+ client.phone('7731234567', :format => :json)
30
+ # => {:number=>"+17731234567", :uri=>"/v2/phone/%2B17731234567",
31
+ # :price=>0, :name=>"VANN,NYSA", :created=>2012-10-05 19:36:33 -0500,
32
+ # :updated=>2012-10-05 19:36:33 -0500}
33
+
34
+ ## Notes
35
+
36
+ ### Hobbyist Plan
37
+ Sending more than 60 requests within an hour without specifying a `account_sid` and `auth_token` will result in a 403 status code and raise an `Opencnam::OpencnamError`.
38
+
39
+ ### Professional Plan
40
+ You can configure `ruby-opencnam` to use your `account_sid` and `auth_token`:
41
+
42
+ client = Opencnam::Client.new(
43
+ :account_sid => 'your_account_sid',
44
+ :auth_token => 'your_auth_token',
45
+ )
46
+
47
+ or
48
+
49
+ client = Opencnam::Client.new
50
+ client.account_sid = 'your_account_sid'
51
+ client.auth_token = 'your_auth_token'
52
+
53
+ ### SSL
54
+ You can send configure `ruby-opencnam` to send requests over SSL:
55
+
56
+ client = Opencnam::Client.new(:use_ssl => true)
57
+
58
+ # or
59
+
60
+ client = Opencnam::Client.new
61
+ client.use_ssl = true
62
+
63
+ # Check if SSL is set
64
+ client.use_ssl?
65
+ # => true
66
+
67
+ ### Opencnam::OpencnamError
68
+ Calling the `phone` method can raise an `Opencnam::OpencnamError` for a variety of reasons (not found, bad request, payment required, etc.). For a full list of things that can go wrong, see:
69
+ https://www.opencnam.com/docs/v2/apiref#cnam-status-codes
70
+
71
+ ### Returned name formats
72
+ The name returned from OpenCNAM varies. Sometimes not providing a name at all and instead providing just a city and state such as `'SACRAMENTO CA'`. Sometimes names can get cut off, like `'VANN,NYS'`. Take caution if you plan on parsing names!
73
+
74
+ ## License
75
+
76
+ Copyright &copy; 2013 Nysa Vann <<nysa@nysavann.com>>
77
+
78
+ ruby-opencnam is distributed under an MIT-style license. See LICENSE for details.
data/lib/opencnam.rb CHANGED
@@ -1,79 +1,7 @@
1
- require "net/http"
1
+ require 'date'
2
+ require 'json'
3
+ require 'net/http'
2
4
 
3
- require "opencnam/version"
4
- require "opencnam/util"
5
- require "opencnam/errors/opencnam_error"
6
- require "opencnam/errors/bad_request_error"
7
- require "opencnam/errors/invalid_phone_number_error"
8
- require "opencnam/errors/no_info_error"
9
- require "opencnam/errors/running_lookup_error"
10
- require "opencnam/errors/throttled_error"
11
-
12
- module OpenCNAM
13
- @@api_base = 'https://api.opencnam.com'
14
- @@api_user = nil
15
- @@api_key = nil
16
-
17
- def self.api_user=(api_user)
18
- @@api_user = api_user
19
- end
20
-
21
- def self.api_key=(api_key)
22
- @@api_key = api_key
23
- end
24
-
25
- def self.lookup(number)
26
- # Clean phone number
27
- clean_number = OpenCNAM::Util.clean_phone_number(number)
28
-
29
- # Build query
30
- query = URI.encode_www_form(
31
- :format => 'text',
32
- :username => @@api_user,
33
- :api_key => @@api_key,
34
- )
35
-
36
- # Send request
37
- uri = URI.parse(@@api_base)
38
- http = Net::HTTP.new(uri.host, uri.port)
39
- http.use_ssl = true
40
-
41
- res = http.request_get("/v1/phone/#{clean_number}?#{query}")
42
-
43
- # 200 - OK
44
- if res.kind_of?(Net::HTTPOK)
45
- return {
46
- :name => res.body,
47
- :number => clean_number,
48
- }
49
- end
50
-
51
- error_attrs = {
52
- :http_status => res.code,
53
- :message => res.message,
54
- }
55
-
56
- # 202 - Currently running a lookup for phone number
57
- if res.kind_of?(Net::HTTPAccepted)
58
- raise RunningLookupError.new(error_attrs)
59
- end
60
-
61
- # 403 - Forbidden, requests throttled
62
- if res.kind_of?(Net::HTTPForbidden)
63
- raise ThrottledError.new(error_attrs)
64
- end
65
-
66
- # 400 - Bad request
67
- if res.kind_of?(Net::HTTPBadRequest)
68
- raise BadRequestError.new(error_attrs)
69
- end
70
-
71
- # 404 - No caller ID name information
72
- if res.kind_of?(Net::HTTPNotFound)
73
- raise NoInfoError.new(error_attrs)
74
- end
75
-
76
- # Unkown response
77
- raise OpenCNAMError.new(error_attrs)
78
- end
79
- end
5
+ require 'opencnam/client'
6
+ require 'opencnam/opencnam_error'
7
+ require 'opencnam/parsers'
@@ -0,0 +1,78 @@
1
+ require 'opencnam/parsers'
2
+
3
+ module Opencnam #:nodoc:
4
+ # :nodoc:
5
+ # @!attribute [rw] account_sid
6
+ # @return [String] the account_sid
7
+ # @!attribute [rw] auth_token
8
+ # @return [String] the auth_token
9
+ # @!attribute [w] use_ssl
10
+ # @return [Boolean]
11
+ class Client
12
+ # The OpenCNAM API hostname
13
+ API_HOST = 'api.opencnam.com'
14
+ include Parsers
15
+
16
+ attr_writer :use_ssl
17
+ attr_accessor :account_sid, :auth_token
18
+
19
+ # @param [Hash] options
20
+ # @option options [String] :account_sid (nil)
21
+ # @option options [String] :auth_token (nil)
22
+ # @option options [Boolean] :use_ssl (false)
23
+ def initialize(options = {})
24
+ @account_sid = options[:account_sid].strip if options[:account_sid]
25
+ @auth_token = options[:auth_token].strip if options[:auth_token]
26
+ @use_ssl = options[:use_ssl]
27
+ end
28
+
29
+ # Returns true if this client instance is configured to use SSL by
30
+ # default.
31
+ #
32
+ # @return [Boolean]
33
+ def use_ssl?
34
+ @use_ssl
35
+ end
36
+
37
+ # Look up a phone number and return the caller's name.
38
+ #
39
+ # @param [String] phone_number The phone number to look up
40
+ # @param [Hash] options Described below
41
+ # @option options [String] :account_sid Specify a different OpenCNAM
42
+ # account_sid
43
+ # @option options [String] :auth_token Specify a different OpenCNAM
44
+ # auth_token
45
+ # @option options [String, Symbol] :format (:text) The format to retrieve,
46
+ # can be :text or :json
47
+ # @return [String, Hash] the phone number owner's name if :format is
48
+ # :string, or a Hash of additional fields from OpenCNAM if :format
49
+ # is :json (:created, :updated, :name, :price, :uri, and
50
+ # :number)
51
+ def phone(phone_number, options = {})
52
+ # Build query string
53
+ options = {
54
+ :account_sid => account_sid,
55
+ :auth_token => auth_token,
56
+ :format => 'text',
57
+ }.merge(options)
58
+ options[:format] = options[:format].to_s.strip.downcase
59
+
60
+ # Check for supported format
61
+ unless %w(text json).include? options[:format]
62
+ raise ArgumentError.new "Unsupported format: #{options[:format]}"
63
+ end
64
+
65
+ # Send request
66
+ http = Net::HTTP.new(API_HOST, (use_ssl? ? '443' : '80'))
67
+ http.use_ssl = true if use_ssl?
68
+ query = URI.encode_www_form(options)
69
+ res = http.request_get("/v2/phone/#{phone_number.strip}?#{query}")
70
+
71
+ # Look up was unsuccessful
72
+ raise OpencnamError.new res.message unless res.kind_of? Net::HTTPOK
73
+
74
+ return res.body if options[:format] == 'text'
75
+ return parse_json(res.body) if options[:format] == 'json'
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,4 @@
1
+ module Opencnam #:nodoc:
2
+ class OpencnamError < StandardError #:nodoc:
3
+ end
4
+ end
@@ -0,0 +1,33 @@
1
+ module Opencnam #:nodoc:
2
+ # Contains utility methods for parsing responses from OpenCNAM.
3
+ module Parsers
4
+ private
5
+
6
+ # Parses an ISO 8601 formatted date string.
7
+ # @param [String] date_string
8
+ # @return [Time]
9
+ def parse_iso_date_string(date_string)
10
+ DateTime.iso8601(date_string).to_time
11
+ rescue ArgumentError
12
+ nil
13
+ end
14
+
15
+ # Parses a JSON string.
16
+ # @param [String] json the JSON formatted string
17
+ # @return [Hash]
18
+ def parse_json(json)
19
+ hash = JSON.parse(json, :symbolize_names => true)
20
+
21
+ # Convert hash[:created] and hash[:updated] to Time objects
22
+ if hash[:created]
23
+ hash.merge!({ :created => parse_iso_date_string(hash[:created]) })
24
+ end
25
+
26
+ if hash[:updated]
27
+ hash.merge!({ :updated => parse_iso_date_string(hash[:updated]) })
28
+ end
29
+
30
+ hash
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
- module OpenCNAM
2
- VERSION = '0.0.1'
1
+ module Opencnam #:nodoc:
2
+ VERSION = '1.0.0' #:nodoc:
3
3
  end
@@ -0,0 +1,12 @@
1
+ class OpencnamBadResponse < Net::HTTPBadRequest
2
+ def body
3
+ ''
4
+ end
5
+
6
+ def initialize
7
+ end
8
+
9
+ def message
10
+ 'Bad request'
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ class OpencnamOkResponse < Net::HTTPOK
2
+ def body
3
+ '{ "uri": "/v2/phone/%2B16502530000", "price": 0, "updated": "2013-02-17T01:34:22.501327", "name": "GOOGLE INC", "created": "2012-10-12T06:53:05.194858", "number": "+16502530000"}'
4
+ end
5
+
6
+ def initialize
7
+ end
8
+
9
+ def message
10
+ 'OK'
11
+ end
12
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ describe Opencnam::Client do
4
+ let(:client) { Opencnam::Client.new }
5
+
6
+ describe '#initialize' do
7
+ context 'when options is not given' do
8
+ it 'should set @use_ssl to false' do
9
+ client.use_ssl?.should be_false
10
+ end
11
+
12
+ it 'should set @account_sid to nil' do
13
+ client.account_sid.should be_nil
14
+ end
15
+
16
+ it 'should set @auth_token to nil' do
17
+ client.auth_token.should be_nil
18
+ end
19
+ end
20
+
21
+ context 'when options is given' do
22
+ let(:options) { {
23
+ :account_sid => 'example-account-sid ',
24
+ :auth_token => 'example-auth-token',
25
+ :use_ssl => true,
26
+ } }
27
+ let(:client) { Opencnam::Client.new(options) }
28
+
29
+ it 'should set @use_ssl' do
30
+ client.use_ssl?.should be_true
31
+ end
32
+
33
+ it 'should set @account_sid' do
34
+ client.account_sid.should_not be_nil
35
+ end
36
+
37
+ it 'should set @auth_token' do
38
+ client.auth_token.should_not be_nil
39
+ end
40
+ end
41
+ end
42
+
43
+ describe '#use_ssl?' do
44
+ context 'when @use_ssl is true' do
45
+ it 'should return true' do
46
+ client.use_ssl = true
47
+ client.use_ssl?.should be_true
48
+ end
49
+ end
50
+
51
+ context 'when @use_ssl is false' do
52
+ it 'should return false' do
53
+ client.use_ssl = false
54
+ client.use_ssl?.should be_false
55
+ end
56
+ end
57
+ end
58
+
59
+ describe '#phone' do
60
+ it 'should return a String' do
61
+ client.phone('+16502530000')
62
+ end
63
+
64
+ context 'when given a bad phone number' do
65
+ it 'should raise OpencnamError' do
66
+ expect { client.phone('+abcdefgh') }.to(
67
+ raise_error Opencnam::OpencnamError
68
+ )
69
+ end
70
+ end
71
+
72
+ context 'when given :format => :text' do
73
+ it 'should return a String' do
74
+ client.phone('+16502530000', :format => :text).should be_a String
75
+ end
76
+ end
77
+
78
+ context 'when given :format => :json' do
79
+ it 'should return a Hash' do
80
+ client.phone('+16502530000', :format => :json).should be_a Hash
81
+ end
82
+ end
83
+
84
+ context 'when given an unsupported :format' do
85
+ it 'should raise ArgumentError' do
86
+ expect { client.phone('+16502530000', :format => :xml) }.to(
87
+ raise_error ArgumentError
88
+ )
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ class DummyExtender
4
+ extend Opencnam::Parsers
5
+ end
6
+
7
+ describe Opencnam::Parsers do
8
+ describe '#parse_iso_date_string' do
9
+ context 'when given a valid ISO date string' do
10
+ it 'should return a Time object' do
11
+ string = '2013-02-17T01:34:22.501327'
12
+ DummyExtender.send(:parse_iso_date_string, string).should be_a Time
13
+ end
14
+ end
15
+
16
+ context 'when given an invalid string' do
17
+ it 'should return nil' do
18
+ DummyExtender.send(:parse_iso_date_string, 'abcdef').should eq nil
19
+ end
20
+ end
21
+
22
+ context 'when given nil' do
23
+ it 'should return nil' do
24
+ DummyExtender.send(:parse_iso_date_string, nil).should be_nil
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '#parse_json' do
30
+ it 'should return a Hash' do
31
+ DummyExtender.send(:parse_json, '{"name":"Nysa"}').should be_a Hash
32
+ end
33
+
34
+ it 'should not receive #parse_iso_date_string' do
35
+ DummyExtender.should_not_receive(:parse_iso_date_string)
36
+ DummyExtender.send(:parse_json, '{"name":"Nysa"}')
37
+ end
38
+
39
+ context 'when given a JSON string with key created' do
40
+ it 'should receive #parse_iso_date_string' do
41
+ DummyExtender.should_receive(:parse_iso_date_string)
42
+ DummyExtender.send(:parse_json, '{"created":"ISO"}')
43
+ end
44
+ end
45
+
46
+ context 'when given a JSON string with key updated' do
47
+ it 'should receive #parse_iso_date_string' do
48
+ DummyExtender.should_receive(:parse_iso_date_string)
49
+ DummyExtender.send(:parse_json, '{"updated":"ISO"}')
50
+ end
51
+ end
52
+
53
+ context 'when given a JSON string with keys updated and created' do
54
+ it 'should receive #parse_iso_date_string twice' do
55
+ DummyExtender.should_receive(:parse_iso_date_string).twice
56
+ DummyExtender.send(:parse_json, '{"created":"ISO","updated":"ISO"}')
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,11 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'opencnam'
3
+ require 'rspec'
4
+
5
+ # Load fixtures
6
+ load File.join(File.dirname(__FILE__), 'fixtures', 'opencnam_ok_response.rb')
7
+ load File.join(File.dirname(__FILE__), 'fixtures', 'opencnam_bad_response.rb')
8
+
9
+ RSpec.configure do |config|
10
+ config.mock_with :rspec
11
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opencnam
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,56 +9,56 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-21 00:00:00.000000000 Z
12
+ date: 2013-03-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: fakeweb
15
+ name: json
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '1.3'
22
- type: :development
21
+ version: 1.7.7
22
+ type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: '1.3'
29
+ version: 1.7.7
30
30
  - !ruby/object:Gem::Dependency
31
- name: minitest
31
+ name: rake
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
- - - ~>
35
+ - - ! '>='
36
36
  - !ruby/object:Gem::Version
37
- version: 3.1.0
37
+ version: '0'
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - ~>
43
+ - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
- version: 3.1.0
45
+ version: '0'
46
46
  - !ruby/object:Gem::Dependency
47
- name: rake
47
+ name: rspec
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
- - - ! '>='
51
+ - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: '0'
53
+ version: 2.12.0
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  none: false
58
58
  requirements:
59
- - - ! '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 2.12.0
62
62
  description: OpenCNAM provides a simple, elegant, and RESTful API to get Caller ID
63
63
  data.
64
64
  email: nysa@nysavann.com
@@ -66,17 +66,21 @@ executables: []
66
66
  extensions: []
67
67
  extra_rdoc_files: []
68
68
  files:
69
- - lib/opencnam/errors/bad_request_error.rb
70
- - lib/opencnam/errors/invalid_phone_number_error.rb
71
- - lib/opencnam/errors/no_info_error.rb
72
- - lib/opencnam/errors/opencnam_error.rb
73
- - lib/opencnam/errors/running_lookup_error.rb
74
- - lib/opencnam/errors/throttled_error.rb
75
- - lib/opencnam/util.rb
69
+ - LICENSE
70
+ - README.md
71
+ - lib/opencnam/client.rb
72
+ - lib/opencnam/opencnam_error.rb
73
+ - lib/opencnam/parsers.rb
76
74
  - lib/opencnam/version.rb
77
75
  - lib/opencnam.rb
76
+ - spec/fixtures/opencnam_bad_response.rb
77
+ - spec/fixtures/opencnam_ok_response.rb
78
+ - spec/lib/opencnam/client_spec.rb
79
+ - spec/lib/opencnam/parsers_spec.rb
80
+ - spec/spec_helper.rb
78
81
  homepage: http://github.com/nysa/ruby-opencnam
79
- licenses: []
82
+ licenses:
83
+ - MIT
80
84
  post_install_message:
81
85
  rdoc_options: []
82
86
  require_paths:
@@ -95,8 +99,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
99
  version: '0'
96
100
  requirements: []
97
101
  rubyforge_project:
98
- rubygems_version: 1.8.22
102
+ rubygems_version: 1.8.23
99
103
  signing_key:
100
104
  specification_version: 3
101
105
  summary: Ruby bindings for the OpenCNAM API
102
- test_files: []
106
+ test_files:
107
+ - spec/fixtures/opencnam_bad_response.rb
108
+ - spec/fixtures/opencnam_ok_response.rb
109
+ - spec/lib/opencnam/client_spec.rb
110
+ - spec/lib/opencnam/parsers_spec.rb
111
+ - spec/spec_helper.rb
@@ -1,4 +0,0 @@
1
- module OpenCNAM
2
- class BadRequestError < OpenCNAMError
3
- end
4
- end
@@ -1,7 +0,0 @@
1
- module OpenCNAM
2
- class InvalidPhoneNumberError < OpenCNAMError
3
- def initialize(phone_number)
4
- super(:message => "#{phone_number} could not be parsed as a valid US phone number")
5
- end
6
- end
7
- end
@@ -1,4 +0,0 @@
1
- module OpenCNAM
2
- class NoInfoError < OpenCNAMError
3
- end
4
- end
@@ -1,18 +0,0 @@
1
- module OpenCNAM
2
- class OpenCNAMError < StandardError
3
- attr_reader :message
4
- attr_reader :http_status
5
- attr_reader :http_body
6
-
7
- def initialize(opts = {})
8
- @message = opts[:message] || nil
9
- @http_status = opts[:http_status] || nil
10
- @http_body = opts[:http_body] || nil
11
- end
12
-
13
- def to_s
14
- status = @http_status.nil? ? "" : "(Status #{@http_status}) "
15
- "#{status}#{@message}"
16
- end
17
- end
18
- end
@@ -1,4 +0,0 @@
1
- module OpenCNAM
2
- class RunningLookupError < OpenCNAMError
3
- end
4
- end
@@ -1,4 +0,0 @@
1
- module OpenCNAM
2
- class ThrottledError < OpenCNAMError
3
- end
4
- end
data/lib/opencnam/util.rb DELETED
@@ -1,14 +0,0 @@
1
- module OpenCNAM
2
- module Util
3
- def self.clean_phone_number(number)
4
- # Drop all characters except integers
5
- clean_number = number.to_s
6
- clean_number.tr!('^0-9', '')
7
- clean_number = clean_number[-10..-1]
8
-
9
- raise InvalidPhoneNumberError.new(number) if !clean_number || clean_number.length < 10
10
-
11
- clean_number
12
- end
13
- end
14
- end