happy_phone_number 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,15 +3,24 @@ Happy Phone Number [![Build Status](https://travis-ci.org/lkdjiin/happy_phone_nu
3
3
 
4
4
  Description
5
5
  ----------------------
6
- A rails plugin to happily format phone numbers.
7
6
 
8
- **Early stage. Work in progress.**
7
+ *Happy Phone Number* provides easy methods to format phone
8
+ numbers from your Rails models. Virtually any country specific
9
+ format or convention could be supported, including national and international
10
+ format. For the not (yet) supported countries, a general method
11
+ using a simple mask is also provided.
9
12
 
10
13
  Overview
11
14
  -----------------------
12
15
 
13
- Let's say you have a `Contact` model with a `phone` attribute. The phone number
14
- **must be save** without spaces, or hyphen, or dots...
16
+ ### Prerequisite
17
+
18
+ * Phone number **must be save** with digits only. So, without spaces, hyphens,
19
+ or dots. Just digits.
20
+
21
+ ### Demonstration
22
+
23
+ Let's say you have a `Contact` model with a `phone` attribute.
15
24
 
16
25
  To display the phone number you could do this:
17
26
 
@@ -30,7 +39,7 @@ Or in uppercase if you prefer:
30
39
 
31
40
  If you want an international format:
32
41
 
33
- <%= @contact.happy_phone(:international) %>
42
+ <%= @contact.happy_inter_phone(:fr) %>
34
43
  #=> "+33 1 23 45 67 89"
35
44
 
36
45
  What if you want dots as separator?
@@ -49,6 +58,29 @@ and `mobile`, or maybe `portable`?
49
58
  #=> "33 33 33 33 33"
50
59
  ...
51
60
 
61
+ Now, imagine you live in Belgium, where phone numbers could have 2 formats:
62
+
63
+ <%= @contact.happy_phone(:be) %>
64
+ #=> "03 111 22 33"
65
+
66
+ <%= @contact.happy_phone2(:be) %>
67
+ #=> "063 11 22 33"
68
+
69
+ <%= @contact.happy_inter_phone(:be) %>
70
+ #=> "+32 3 111 22 33"
71
+
72
+ <%= @contact.happy_inter_phone2(:be) %>
73
+ #=> "+32 63 11 22 33"
74
+
75
+ And if *Happy Phone Number* don't know your country, you could use a
76
+ **mask formatting**:
77
+
78
+ <%= @contact.happy_phone("#### ###-###") %>
79
+ #=> "0123 456-789"
80
+
81
+ ### Caveats
82
+
83
+ *Mask formatting* doesn't work for international phone number format.
52
84
 
53
85
  Install
54
86
  -------------------------
@@ -72,12 +104,80 @@ Now, in your views, you can use:
72
104
 
73
105
  happy_phone(:fr)
74
106
  happy_fax(:fr)
107
+ ...
108
+
109
+ Supported Countries
110
+ --------------------------
111
+
112
+ <table>
113
+ <tr>
114
+ <th>Name</th>
115
+ <th>Symbol</th>
116
+ </tr>
117
+ <tr>
118
+ <td>Belgium</td>
119
+ <td>:be</td>
120
+ </tr>
121
+ <tr>
122
+ <td>Denmark</td>
123
+ <td>:dk</td>
124
+ </tr>
125
+ <tr>
126
+ <td>France</td>
127
+ <td>:fr</td>
128
+ </tr>
129
+ <tr>
130
+ <td>Iceland</td>
131
+ <td>:is</td>
132
+ </tr>
133
+ </table>
75
134
 
76
135
  Dependencies
77
136
  --------------------------
78
137
 
79
- ruby >= 1.9.2
80
- rails >= 3.2
138
+ * ruby >= 1.9.2
139
+ * rails >= 3.2
140
+
141
+ Contributing
142
+ -------------------------
143
+
144
+ *I don't know much about format and convention for every possible country.
145
+ Feel free to send me documentation for the phone number formatting and
146
+ convention for your country. Or contribute to the code by adding any
147
+ missing formatter.*
148
+
149
+ 1. Fork it
150
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
151
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
152
+ 4. Push to the branch (`git push origin my-new-feature`)
153
+ 5. Create new Pull Request
154
+
155
+ ### How to add a formatter for your country
156
+
157
+ Name the file as follow:
158
+
159
+ aa_format.rb
160
+
161
+ where "aa" is the ISO code of the country.
162
+ See [ISO country codes] [1].
163
+
164
+ Put this file in the lib/happy_phone_number/ folder. Then follow the structure of
165
+ an existed formatter:
166
+
167
+ * fr_format.rb is a good starting point
168
+ * dk_format.rb is the simplest one
169
+ * be_format.rb is a little more complex
170
+
171
+ Feel free to ask for help if you have any troubles.
172
+
173
+
174
+ ### There is many other ways to contibute to FIXME
175
+
176
+ 1. Report any bug
177
+ 2. Give me ideas
178
+ 3. Correct my poor english syntax
179
+ 4. Blog about *Happy Phone Number*
180
+ 5. Tell *Happy Phone Number* to your friends and colleagues
81
181
 
82
182
  License
83
183
  --------------------------
@@ -89,4 +189,6 @@ Questions and/or Comments
89
189
  --------------------------
90
190
 
91
191
  Feel free to email [Xavier Nayrac](mailto:xavier.nayrac@gmail.com)
92
- with any questions.
192
+ with any questions, or contact me on [twitter](https://twitter.com/lkdjiin).
193
+
194
+ [1]: http://en.wikipedia.org/wiki/ISO_3166-1 "ISO country codes on wikipedia"
@@ -1,24 +1,69 @@
1
+ require 'happy_phone_number/formatter'
2
+ require 'happy_phone_number/mask'
3
+ require 'happy_phone_number/base_format'
4
+
5
+ # Public: Happy Phone Number provides easy methods to format phone
6
+ # numbers from your Rails models. Virtually any country specific
7
+ # format could be supported, including national and international
8
+ # format. For the not (yet) supported countries, a general method
9
+ # using a simple mask is also provided.
10
+ #
11
+ # Examples
12
+ #
13
+ # class Contact < ActiveRecord::Base
14
+ # attr_accessible :email, :name, :phone, :fax
15
+ # happy_phone_number
16
+ # end
17
+ #
18
+ # <%= @contact.happy_phone(:fr) %>
19
+ # # => "01 23 45 67 89"
20
+ #
21
+ # <%= @contact.happy_inter_phone(:fr) %>
22
+ # # => "+33 1 23 45 67 89"
23
+ #
24
+ # <%= @contact.happy_phone(:be) %>
25
+ # # => "03 111 22 33"
26
+ #
27
+ # <%= @contact.happy_phone("#### ###-###") %>
28
+ # # => "0123 456-789"
1
29
  module HappyPhoneNumber
2
30
  extend ActiveSupport::Concern
3
31
 
4
32
  included do
5
-
6
33
  end
7
34
 
8
35
  module ClassMethods
9
36
  def happy_phone_number(options = {})
10
- # your code will go here
11
37
  end
12
38
  end
13
39
 
40
+ # Public: Format a phone number from a model.
41
+ #
42
+ # args[0] - Either a Symbol country or a String formatting mask.
43
+ # A country symbol must be in ISO 3166-1-alpha-2 format,
44
+ # both lower and upper case are valids.
45
+ # block - Not used.
46
+ #
47
+ # Signature
48
+ #
49
+ # happy_<field>(country_or_mask, separator)
50
+ # happy_inter_<field>(country_or_mask, separator)
51
+ #
52
+ # field - A field name of the model that holds a phone number as a
53
+ # string.
54
+ #
55
+ # Returns the String formatted phone number.
14
56
  def method_missing(meth, *args, &block)
15
- if meth.to_s =~ /^happy_(.+)$/
16
- run_happy($1, *args, &block)
57
+ if meth.to_s =~ /^happy_inter_(.+)$/
58
+ happy_format(:international, $1, *args)
59
+ elsif meth.to_s =~ /^happy_(.+)$/
60
+ happy_format(:national, $1, *args)
17
61
  else
18
62
  super
19
63
  end
20
64
  end
21
65
 
66
+ # Public: Make the happy_* methods respond to respond_to?.
22
67
  def respond_to?(meth, include_private = false)
23
68
  if meth.to_s =~ /^happy_.*$/
24
69
  true
@@ -29,16 +74,16 @@ module HappyPhoneNumber
29
74
 
30
75
  private
31
76
 
32
- def run_happy(meth, *args, &block)
33
- type = args[0]
34
- separator = args[1] || ' '
35
- if (type == :fr) || (type == :FR)
36
- send(meth.to_sym).unpack('A2A2A2A2A2').join(separator)
37
- elsif type == :international
38
- "+33#{send(meth.to_sym)[1, 9]}".unpack('A3A1A2A2A2A2').join(separator)
39
- else
40
- send(meth.to_sym)
41
- end
77
+ # Launch the formatting process.
78
+ #
79
+ # type - Either :national or :international.
80
+ # meth - The String field from the model.
81
+ # args - Argument(s) passed to the formatting method, like a country,
82
+ # a mask string, the separator.
83
+ #
84
+ # Returns the String formatted phone number.
85
+ def happy_format(type, meth, *args)
86
+ Formatter.new(send(meth.to_sym), type, args[0], args[1]).format
42
87
  end
43
88
 
44
89
  end
@@ -0,0 +1,67 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module HappyPhoneNumber
4
+
5
+ # Internal: Base class for specific country formatter.
6
+ class BaseFormat
7
+
8
+ # Internal: Initialize a new base formatter.
9
+ #
10
+ # phone - A String phone number to format.
11
+ # type - Either :national or :international.
12
+ # separator - A String separator to put into each groups of digit.
13
+ def initialize phone, type, separator
14
+ @phone = phone
15
+ @type = type
16
+ @separator = separator
17
+ end
18
+
19
+ private
20
+
21
+ # Internal: Format the phone number using specified grouping.
22
+ #
23
+ # groups - A String set of digits.
24
+ #
25
+ # Examples
26
+ #
27
+ # @phone = "123456"
28
+ # make_happy "222"
29
+ # # => "12 34 56"
30
+ #
31
+ # @phone = "+33123456789"
32
+ # @separator = "."
33
+ # make_happy "312222"
34
+ # # => "+33.1.23.45.67.89"
35
+ #
36
+ # Returns the String formatted phone number.
37
+ def make_happy groups
38
+ unpack_string = "A#{groups.split('').join('A')}"
39
+ @phone.unpack(unpack_string).join(@separator)
40
+ end
41
+
42
+ # Internal: Internationalize a phone number with a given prefix.
43
+ #
44
+ # prefix - A String.
45
+ # block - Optional, a block to call before we add the prefix.
46
+ #
47
+ # Examples
48
+ #
49
+ # puts @phone
50
+ # # => "12345678"
51
+ # internationalize_with("45")
52
+ # # => "+4512345678"
53
+ #
54
+ # puts @phone
55
+ # # => "0123456789"
56
+ # internationalize_with("33") { @phone.slice!(0) }
57
+ # # => "+33123456789"
58
+ #
59
+ # Returns nothing.
60
+ def internationalize_with prefix, &block
61
+ block.call if block
62
+ @phone = "+#{prefix}#{@phone}"
63
+ end
64
+
65
+ end
66
+ end
67
+
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module HappyPhoneNumber
4
+
5
+ # Format for belgian phone numbers.
6
+ class BeFormat < BaseFormat
7
+
8
+ # Format the phone number given belgian convention.
9
+ #
10
+ # Returns the String formatted phone number.
11
+ def format
12
+ case @phone[0, 2]
13
+ when "02", "03", "04", "08", "09"
14
+ if @type == :national
15
+ make_happy '2322'
16
+ else
17
+ internationalize
18
+ make_happy '31322'
19
+ end
20
+ else
21
+ if @type == :national
22
+ make_happy '3222'
23
+ else
24
+ internationalize
25
+ make_happy '32222'
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def internationalize
33
+ internationalize_with('32') { @phone.slice!(0) }
34
+ end
35
+
36
+ end
37
+ end
38
+
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module HappyPhoneNumber
4
+
5
+ # Format phone numbers from Denmark.
6
+ class DkFormat < BaseFormat
7
+
8
+ # Format the phone number given danish convention.
9
+ #
10
+ # Returns the String formatted phone number.
11
+ def format
12
+ if @type == :national
13
+ make_happy '2222'
14
+ else
15
+ internationalize_with '45'
16
+ make_happy '32222'
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,81 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module HappyPhoneNumber
4
+
5
+ # Internal: A simple facade which call the real formatter.
6
+ class Formatter
7
+
8
+ # Internal: Initialize the formatter facade.
9
+ #
10
+ # phone - A String phone number to format.
11
+ # type - Either :national or :international.
12
+ # country_or_mask - If it's a country, must be a two-letters Symbol.
13
+ # If it's a String, it is considered as a mask.
14
+ # separator - Optional, a String to separate groups of digits
15
+ # the final result.
16
+ def initialize phone, type, country_or_mask, separator
17
+ @phone = phone
18
+ @type = type
19
+ @country_or_mask = country_or_mask
20
+ @separator = separator || ' '
21
+ end
22
+
23
+ # Internal: Call the real formatter.
24
+ #
25
+ # Returns the String formatted phone number.
26
+ def format
27
+ if @country_or_mask.class == String
28
+ use_mask
29
+ else
30
+ use_formatter
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ # Format phone using a mask.
37
+ #
38
+ # Returns the String formatted phone number.
39
+ def use_mask
40
+ Mask.new(@phone, @country_or_mask).format
41
+ end
42
+
43
+ # Format phone using a country formatter.
44
+ #
45
+ # Returns the String formatted phone number.
46
+ def use_formatter
47
+ begin
48
+ require "happy_phone_number/#{formatter_filename}"
49
+ HappyPhoneNumber.const_get(formatter_classname).new(
50
+ @phone, @type, @separator).format
51
+ rescue LoadError
52
+ return @phone
53
+ end
54
+ end
55
+
56
+ # Get the formatter classname.
57
+ #
58
+ # Examples
59
+ #
60
+ # @country_or_mask = :fr
61
+ # formatter_classname # => "FrFormat"
62
+ #
63
+ # Returns the String formatter classname.
64
+ def formatter_classname
65
+ "#{@country_or_mask.to_s.capitalize}Format"
66
+ end
67
+
68
+ # Get the formatter filename.
69
+ #
70
+ # Examples
71
+ #
72
+ # @country_or_mask = :fr
73
+ # formatter_classname # => "fr_format"
74
+ #
75
+ # Returns the String formatter filename.
76
+ def formatter_filename
77
+ "#{@country_or_mask.to_s.downcase}_format"
78
+ end
79
+ end
80
+ end
81
+
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module HappyPhoneNumber
4
+
5
+ # Format for french phone numbers.
6
+ class FrFormat < BaseFormat
7
+
8
+ # Format the phone number given french convention.
9
+ #
10
+ # Returns the String formatted phone number.
11
+ def format
12
+ if @type == :national
13
+ make_happy '22222'
14
+ else
15
+ internationalize_with('33') { @phone.slice!(0) }
16
+ make_happy '312222'
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module HappyPhoneNumber
4
+
5
+ # Format phone numbers from Iceland.
6
+ class IsFormat < BaseFormat
7
+
8
+ # Format the phone number given convention for Iceland.
9
+ #
10
+ # Returns the String formatted phone number.
11
+ def format
12
+ if @type == :national
13
+ make_happy '34'
14
+ else
15
+ internationalize_with '354'
16
+ make_happy '434'
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,85 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module HappyPhoneNumber
4
+
5
+ # Internal: Phone number formatting using a mask.
6
+ #
7
+ # Examples
8
+ #
9
+ # Mask.new("123456", "### ###").format
10
+ # # => "123 456"
11
+ #
12
+ # Mask.new("123456", "## ##-##").format
13
+ # # => "12 34-56"
14
+ #
15
+ # Mask.new("123456", "##.####").format
16
+ # # => "12.3456"
17
+ class Mask
18
+
19
+ # Internal: Initialize a new mask formatter.
20
+ #
21
+ # phone - A String phone number.
22
+ # mask - A String mask.
23
+ def initialize phone, mask
24
+ @phone = phone
25
+ @mask = mask
26
+ end
27
+
28
+ # Internal: Format the phone number. If the mask is too long for the
29
+ # phone number, it will be truncated (the mask). If the mask is too
30
+ # short, the returned phone number will be left untouched.
31
+ #
32
+ # Examples
33
+ #
34
+ # Mask.new("1234", "### ###").format
35
+ # # => "123 4"
36
+ #
37
+ # Mask.new("1234", "#").format
38
+ # # => "1234"
39
+ #
40
+ # Returns the String formatted phone number.
41
+ def format
42
+ return @phone if mask_too_short?
43
+ mask_array.map do |item|
44
+ if item == "#"
45
+ next_digit
46
+ else
47
+ item
48
+ end
49
+ end.join
50
+ end
51
+
52
+ private
53
+
54
+ # Check if the mask is too short for the phone number.
55
+ #
56
+ # Returns true or false.
57
+ def mask_too_short?
58
+ @mask.split('').select {|i| i == "#" }.size < @phone.size
59
+ end
60
+
61
+ # Split the mask into single characters.
62
+ #
63
+ # Returns an Array.
64
+ def mask_array
65
+ @mask.split('')
66
+ end
67
+
68
+ # Get the next digit of the phone number.
69
+ #
70
+ # Examples
71
+ #
72
+ # @phone = "123"
73
+ # next_digit
74
+ # # => "1"
75
+ # next_digit
76
+ # # => "2"
77
+ #
78
+ # Returns a String.
79
+ def next_digit
80
+ @phone.slice!(0)
81
+ end
82
+
83
+ end
84
+ end
85
+
@@ -1,3 +1,3 @@
1
1
  module HappyPhoneNumber
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: happy_phone_number
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-03 00:00:00.000000000 Z
12
+ date: 2013-05-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -59,14 +59,31 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
- description: Rails plugin to format phone number.
62
+ description: ! 'Happy Phone Number provides easy methods to format phone
63
+
64
+ numbers from your Rails models. Virtually any country specific
65
+
66
+ format could be supported, including national and international
67
+
68
+ format. For the not (yet) supported countries, a general method
69
+
70
+ using a simple mask is also provided.
71
+
72
+ '
63
73
  email:
64
74
  - xavier.nayrac@gmail.com
65
75
  executables: []
66
76
  extensions: []
67
77
  extra_rdoc_files: []
68
78
  files:
79
+ - lib/happy_phone_number/dk_format.rb
69
80
  - lib/happy_phone_number/version.rb
81
+ - lib/happy_phone_number/fr_format.rb
82
+ - lib/happy_phone_number/mask.rb
83
+ - lib/happy_phone_number/is_format.rb
84
+ - lib/happy_phone_number/be_format.rb
85
+ - lib/happy_phone_number/base_format.rb
86
+ - lib/happy_phone_number/formatter.rb
70
87
  - lib/tasks/happy_phone_number_tasks.rake
71
88
  - lib/happy_phone_number.rb
72
89
  - MIT-LICENSE