luhn 1.0.3 → 3.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48cccdf14be3fc83b329b2b7407ebd4410c889d62e5fc9e526b5beded1a4f137
4
- data.tar.gz: 31fb9fa178dcfc3068a5e4563fecd2756786334ffcda5dcb1c02831a7c085030
3
+ metadata.gz: bf4e123f559d73199fd452f9f768f7fbf6cfa224995946e4c73492265868d506
4
+ data.tar.gz: a9d036b18565b4f9ddda1d1812f300d9c629a7b5f4ae826caaa6663f1ef309f8
5
5
  SHA512:
6
- metadata.gz: 1ed8c51ba3cf801e1f2ec7eb17b244e7bd0fc06b40899ef7f5d1a230ddd327ff01376fe54d5af9ec15676261ac09844e0f0c747dda0acc8122be805bbcb55482
7
- data.tar.gz: bce0cbb1eb0a0b31e8d77e6794935c01377424139c21252536419376e70a0116e81dbdab0645844a60bbb2c863ae570a738593f576329f37870d79c20eec4582
6
+ metadata.gz: 155f6543bfcf8effc9d5fea6c6319dd162d2f380409f52cdc95462d6d3b6907bc32296b7c3a8006227f6130e1ef7470713e6934c6894c954c4068cfe5a414e0c
7
+ data.tar.gz: 2aa60ea0ea0f5463db677b1486fb7e4693615cfc0c304a22f790b5f9062483ede9ad10442b878cff365d783401f4ac8e934b64c6eb9cf908efb67c6d0a0104ce
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Ruby class for handling basic Luhn number generation and verification
2
2
 
3
- Includes a class to handle Swedish civic numbers (Personnummer).
3
+ Includes a class to handle Swedish personal identity numbers (Personnummer).
4
4
 
5
5
  The interface supports checking validity (length, valid date and satisfies luhn),
6
- returning the sex, the control digit, and generating random civic numbers.
6
+ returning the sex, the control digit, and generating random identity numbers.
7
7
 
8
8
  ## Install
9
9
 
@@ -16,25 +16,19 @@ $ gem install luhn
16
16
  ### Basic Luhn
17
17
 
18
18
  ```ruby
19
- Luhn.valid?('0465827879483596') # true
20
- Luhn.control_digit('046582787948359') # 6
19
+ Luhn.valid?("0465827879483596") # true
20
+ Luhn.control_digit("046582787948359") # 6
21
21
  Luhn.generate(n) # returns a random number of n length that satisfies luhn
22
-
23
- '0465827879483596'.valid_luhn? # true
24
- 0465827879483596.valid_luhn? # true
25
22
  ```
26
23
 
27
- ### Swedish civic numbers
24
+ ### Swedish personal identity numbers
28
25
 
29
26
  ```ruby
30
- civic_number = Luhn::CivicNumber.new('19391030-3183')
31
- civic_number.valid? # true
32
- civic_number.sex # 'male'
33
- civic_number.male? # true
34
- civic_number.control_digit # 3
35
-
36
- '391030-3183'.civic_number? # true
37
- 3910303183.civic_number? # true
27
+ number = Luhn::PersonalIdentityNumber.new("19391030-3183")
28
+ number.valid? # true
29
+ number.sex # "male"
30
+ number.male? # true
31
+ number.control_digit # 3
38
32
  ```
39
33
 
40
34
  ## About the Luhn algorithm
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Luhn
4
+ class PersonalIdentityNumber
5
+ attr_reader :value
6
+
7
+ BirthDate = Data.define(:year, :month, :day)
8
+
9
+ def initialize string
10
+ self.value = string
11
+ end
12
+
13
+ def valid?
14
+ @valid ||= value.length == 10 && valid_date? && Luhn.valid?(value)
15
+ end
16
+
17
+ def valid_date?
18
+ (1..12).cover?(birth_date.month) && (1..31).cover?(birth_date.day)
19
+ end
20
+
21
+ def control_digit
22
+ @control_digit ||= Luhn.control_digit(value[0...9])
23
+ end
24
+
25
+ def sex
26
+ return "unknown" unless valid?
27
+ (value[8...9].to_i.even? ? "female" : "male")
28
+ end
29
+
30
+ def female?
31
+ sex == "female"
32
+ end
33
+
34
+ def male?
35
+ sex == "male"
36
+ end
37
+
38
+ def birth_date
39
+ BirthDate.new(
40
+ value[0...2].to_i,
41
+ value[2...4].to_i,
42
+ value[4...6].to_i
43
+ )
44
+ end
45
+
46
+ def formatted
47
+ return value if value.length < 10
48
+
49
+ value.insert(value.length - 4, "-")
50
+ end
51
+
52
+ def to_s
53
+ value
54
+ end
55
+
56
+ def self.generate
57
+ date = Time.local(Time.now.year - rand(1..99), rand(1..12), rand(1..31))
58
+ Luhn.generate(10, prefix: date.strftime("%y%m%d"))
59
+ end
60
+
61
+ private
62
+
63
+ def value= string
64
+ val = string.to_s.gsub(/\D/, "")
65
+ @value = ((val.length == 12) ? val[2...12] : val)
66
+ end
67
+ end
68
+ end
data/lib/luhn/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Luhn
2
- Version = "1.0.3"
4
+ VERSION = "3.0.0"
3
5
  end
data/lib/luhn.rb CHANGED
@@ -1,5 +1,4 @@
1
- # encoding: UTF-8
2
- require "luhn/extensions"
1
+ # frozen_string_literal: true
3
2
 
4
3
  module Luhn
5
4
  def self.valid? value
@@ -22,10 +21,10 @@ module Luhn
22
21
  end
23
22
 
24
23
  def self.generate size, options = {}
25
- generated = options[:prefix] || ''
24
+ generated = options[:prefix] || ""
26
25
  (size - generated.size - 1).times { |i| generated += rand(10).to_s }
27
26
 
28
- generated + self.new(generated).control_digit.to_s
27
+ generated + new(generated).control_digit.to_s
29
28
  end
30
29
 
31
30
  def valid?
@@ -46,14 +45,14 @@ module Luhn
46
45
  def checksum(operation)
47
46
  i = 0
48
47
  compare_method = (operation == :even) ? :== : :>
49
- self.number.reverse.split("").inject(0) do |sum, c|
48
+ number.reverse.chars.inject(0) do |sum, c|
50
49
  n = c.to_i
51
50
  weight = (i % 2).send(compare_method, 0) ? n * 2 : n
52
51
  i += 1
53
- sum += weight < 10 ? weight : weight - 9
52
+ sum + ((weight < 10) ? weight : (weight - 9))
54
53
  end
55
54
  end
56
55
  end
57
56
  end
58
57
 
59
- require "luhn/civic_number"
58
+ require "luhn/personal_identity_number"
data/spec/helper.rb CHANGED
@@ -1,7 +1,9 @@
1
- $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
2
- require 'rubygems'
3
- gem 'minitest'
4
- require 'luhn'
5
- require 'minitest/benchmark' if ENV["BENCH"]
6
- require 'minitest/spec'
7
- require 'minitest/autorun'
1
+ # frozen_string_literal: true
2
+
3
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
4
+ require "rubygems"
5
+ gem "minitest"
6
+ require "luhn"
7
+ require "minitest/benchmark" if ENV["BENCH"]
8
+ require "minitest/spec"
9
+ require "minitest/autorun"
data/spec/spec_luhn.rb CHANGED
@@ -1,35 +1,37 @@
1
- require 'helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "helper"
2
4
 
3
5
  describe Luhn do
4
6
  it "identifies if the number is valid" do
5
- Luhn.valid?('1111111116').must_equal true
7
+ Luhn.valid?("1111111116").must_equal true
6
8
  end
7
9
 
8
- it 'identifies if the number is invalid' do
9
- Luhn.valid?('1111111111').must_equal false
10
+ it "identifies if the number is invalid" do
11
+ Luhn.valid?("1111111111").must_equal false
10
12
  end
11
13
 
12
- it 'requires numbers' do
13
- Luhn.valid?('frefre').must_equal false
14
+ it "requires numbers" do
15
+ Luhn.valid?("frefre").must_equal false
14
16
  end
15
17
 
16
- it 'generates a number string that satisfies luhn' do
17
- luhn_string = Luhn.generate(rand(32)+1)
18
+ it "generates a number string that satisfies luhn" do
19
+ luhn_string = Luhn.generate(rand(1..32))
18
20
  Luhn.valid?(luhn_string).must_equal true
19
21
  end
20
22
 
21
- it 'generate a number string with the size of the argument' do
23
+ it "generate a number string with the size of the argument" do
22
24
  luhn_string = Luhn.generate(5)
23
25
  luhn_string.size.must_equal 5
24
26
  end
25
27
 
26
- it 'generate a a valid luhn with a given prefix' do
27
- luhn_string = Luhn.generate(10, :prefix => '00001')
28
- luhn_string.must_match /^00001/
28
+ it "generate a a valid luhn with a given prefix" do
29
+ luhn_string = Luhn.generate(10, prefix: "00001")
30
+ luhn_string.must_match(/^00001/)
29
31
  Luhn.valid?(luhn_string).must_equal true
30
32
  end
31
33
 
32
- it 'calculates the control digit' do
33
- Luhn.control_digit('111111111').must_equal 6
34
+ it "calculates the control digit" do
35
+ Luhn.control_digit("111111111").must_equal 6
34
36
  end
35
37
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "helper"
4
+
5
+ describe Luhn::PersonalIdentityNumber do
6
+ it "identifies if the personal identity number is valid" do
7
+ Luhn::PersonalIdentityNumber.new("3910304298").valid?.must_equal true
8
+
9
+ Luhn::PersonalIdentityNumber.new("193910304298").valid?.must_equal true
10
+ end
11
+
12
+ it "identifies if the personal identity number is invalid" do
13
+ Luhn::PersonalIdentityNumber.new("3910304290").valid?.must_equal false
14
+ end
15
+
16
+ it "requires a length of 10 to be valid" do
17
+ luhn_string = Luhn.generate(8, prefix: "391030")
18
+ Luhn::PersonalIdentityNumber.new(luhn_string).valid?.must_equal false
19
+ end
20
+
21
+ it "requires the personal identity number to be a valid date" do
22
+ luhn_string = Luhn.generate(10, prefix: "3999")
23
+ Luhn::PersonalIdentityNumber.new(luhn_string).valid?.must_equal false
24
+ end
25
+
26
+ it "calculates the control digit for a valid personal identity number" do
27
+ Luhn::PersonalIdentityNumber.new("3910304298").control_digit.must_equal 8
28
+ end
29
+
30
+ it "calculates the correct control digit for an invalid personal identity number" do
31
+ Luhn::PersonalIdentityNumber.new("3910304290").control_digit.must_equal 8
32
+ end
33
+
34
+ it "identifies if the personal identity number belongs to a male" do
35
+ Luhn::PersonalIdentityNumber.new("3910304298").sex.must_equal "male"
36
+ end
37
+
38
+ it "identifies if the personal identity number belongs to a female" do
39
+ Luhn::PersonalIdentityNumber.new("3910303183").sex.must_equal "female"
40
+ end
41
+
42
+ it "cleans up personal identity number with the full year supplied" do
43
+ Luhn::PersonalIdentityNumber.new("19391030-3183").to_s.must_equal "3910303183"
44
+ end
45
+
46
+ it "knows the date of birth" do
47
+ personal_identity_number = Luhn::PersonalIdentityNumber.new("3001018194")
48
+ personal_identity_number.birth_date.year.must_equal 30
49
+ personal_identity_number.birth_date.month.must_equal 1
50
+ personal_identity_number.birth_date.day.must_equal 1
51
+ end
52
+
53
+ describe "#formatted" do
54
+ it "formats the personal identity number" do
55
+ personal_identity_number = Luhn::PersonalIdentityNumber.new("3001018194")
56
+
57
+ personal_identity_number.formatted.must_equal "300101-8194"
58
+ end
59
+
60
+ it "returns the origial if the personal identity number is to short" do
61
+ personal_identity_number = Luhn::PersonalIdentityNumber.new("300101819")
62
+
63
+ personal_identity_number.formatted.must_equal "300101819"
64
+ end
65
+ end
66
+
67
+ it "generates a valid random personal identity number" do
68
+ personal_identity_number = Luhn::PersonalIdentityNumber.generate
69
+ Luhn::PersonalIdentityNumber.new(personal_identity_number).valid?.must_equal true
70
+ end
71
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: luhn
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Junström
@@ -9,20 +9,6 @@ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
- - !ruby/object:Gem::Dependency
13
- name: ostruct
14
- requirement: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - "~>"
17
- - !ruby/object:Gem::Version
18
- version: '0'
19
- type: :runtime
20
- prerelease: false
21
- version_requirements: !ruby/object:Gem::Requirement
22
- requirements:
23
- - - "~>"
24
- - !ruby/object:Gem::Version
25
- version: '0'
26
12
  - !ruby/object:Gem::Dependency
27
13
  name: minitest
28
14
  requirement: !ruby/object:Gem::Requirement
@@ -46,15 +32,11 @@ files:
46
32
  - LICENSE
47
33
  - README.md
48
34
  - lib/luhn.rb
49
- - lib/luhn/civic_number.rb
50
- - lib/luhn/extensions.rb
51
- - lib/luhn/extensions/numeric.rb
52
- - lib/luhn/extensions/string.rb
35
+ - lib/luhn/personal_identity_number.rb
53
36
  - lib/luhn/version.rb
54
37
  - spec/helper.rb
55
- - spec/spec_civic_number.rb
56
- - spec/spec_extensions.rb
57
38
  - spec/spec_luhn.rb
39
+ - spec/spec_personal_identity_number.rb
58
40
  homepage: http://github.com/joeljunstrom/ruby_luhn
59
41
  licenses: []
60
42
  metadata: {}
@@ -65,7 +47,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
65
47
  requirements:
66
48
  - - ">="
67
49
  - !ruby/object:Gem::Version
68
- version: '0'
50
+ version: '3.2'
69
51
  required_rubygems_version: !ruby/object:Gem::Requirement
70
52
  requirements:
71
53
  - - ">="
@@ -1,70 +0,0 @@
1
- # encoding: UTF-8
2
- require 'ostruct'
3
- module Luhn
4
- class CivicNumber
5
- attr_reader :value
6
-
7
- def initialize string
8
- self.value = string
9
- end
10
-
11
- def valid?
12
- @valid ||= value.length == 10 && valid_date? && Luhn.valid?(value)
13
- end
14
-
15
- def valid_date?
16
- (1..12).include?(birth_date.month) && (1..31).include?(birth_date.day)
17
- end
18
-
19
- def control_digit
20
- @control_digit ||= Luhn.control_digit(value[0...9])
21
- end
22
-
23
- def sex
24
- valid? ? (value[8...9].to_i.even? ? 'female' : 'male') : 'unknown'
25
- end
26
-
27
- def female?
28
- sex == 'female'
29
- end
30
-
31
- def male?
32
- sex == 'male'
33
- end
34
-
35
- def birth_date
36
- OpenStruct.new({
37
- :year => value[0...2].to_i,
38
- :month => value[2...4].to_i,
39
- :day => value[4...6].to_i
40
- })
41
- end
42
-
43
- def formatted
44
- return value if value.length < 10
45
-
46
- value.insert(value.length - 4, "-")
47
- end
48
-
49
- def to_s
50
- value
51
- end
52
-
53
- # For backwards compability
54
- def civic_number
55
- value
56
- end
57
-
58
- def self.generate
59
- date = Time.local(Time.now.year - rand(100) - 1, rand(12) + 1, rand(31) + 1)
60
- Luhn.generate(10, :prefix => date.strftime("%y%m%d"))
61
- end
62
-
63
- private
64
-
65
- def value= string
66
- val = string.to_s.gsub(/\D/, '')
67
- @value = val.length == 12 ? val[2...12] : val
68
- end
69
- end
70
- end
@@ -1,11 +0,0 @@
1
- # encoding: UTF-8
2
- class Numeric
3
-
4
- def valid_luhn?
5
- self.to_s.valid_luhn?
6
- end
7
-
8
- def civic_number?
9
- self.to_s.civic_number?
10
- end
11
- end
@@ -1,10 +0,0 @@
1
- # encoding: UTF-8
2
- class String
3
- def valid_luhn?
4
- Luhn.valid?(self)
5
- end
6
-
7
- def civic_number?
8
- Luhn::CivicNumber.new(self).valid?
9
- end
10
- end
@@ -1,3 +0,0 @@
1
- # encoding: UTF-8
2
- require 'luhn/extensions/string'
3
- require 'luhn/extensions/numeric'
@@ -1,67 +0,0 @@
1
- require 'helper'
2
-
3
- describe Luhn::CivicNumber do
4
- it 'identifies if the civic number is valid' do
5
- Luhn::CivicNumber.new('3910304298').valid?.must_equal true
6
- end
7
-
8
- it 'identifies if the civic number is invalid' do
9
- Luhn::CivicNumber.new('3910304290').valid?.must_equal false
10
- end
11
-
12
- it 'requires a length of 10 to be valid' do
13
- luhn_string = Luhn.generate(8, :prefix => '391030')
14
- Luhn::CivicNumber.new(luhn_string).valid?.must_equal false
15
- end
16
-
17
- it 'requires the civic number to be a valid date' do
18
- luhn_string = Luhn.generate(10, :prefix => '3999')
19
- Luhn::CivicNumber.new(luhn_string).valid?.must_equal false
20
- end
21
-
22
- it 'calculates the control digit for a valid civic number' do
23
- Luhn::CivicNumber.new('3910304298').control_digit.must_equal 8
24
- end
25
-
26
- it 'calculates the correct control digit for an invalid civic number' do
27
- Luhn::CivicNumber.new('3910304290').control_digit.must_equal 8
28
- end
29
-
30
- it 'identifies if the civic number belongs to a male' do
31
- Luhn::CivicNumber.new('3910304298').sex.must_equal 'male'
32
- end
33
-
34
- it 'identifies if the civic number belongs to a female' do
35
- Luhn::CivicNumber.new('3910303183').sex.must_equal 'female'
36
- end
37
-
38
- it 'cleans up civic number with the full year supplied' do
39
- Luhn::CivicNumber.new('19391030-3183').civic_number.must_equal '3910303183'
40
- end
41
-
42
- it 'knows the date of birth' do
43
- civic_number = Luhn::CivicNumber.new('3001018194')
44
- civic_number.birth_date.year.must_equal 30
45
- civic_number.birth_date.month.must_equal 1
46
- civic_number.birth_date.day.must_equal 1
47
- end
48
-
49
- describe "#formatted" do
50
- it "formats the civic number" do
51
- civic_number = Luhn::CivicNumber.new('3001018194')
52
-
53
- civic_number.formatted.must_equal "300101-8194"
54
- end
55
-
56
- it "returns the origial if the civic number is to short" do
57
- civic_number = Luhn::CivicNumber.new('300101819')
58
-
59
- civic_number.formatted.must_equal "300101819"
60
- end
61
- end
62
-
63
- it 'generates a valid random civic number' do
64
- civic_number = Luhn::CivicNumber.generate
65
- Luhn::CivicNumber.new(civic_number).valid?.must_equal true
66
- end
67
- end
@@ -1,21 +0,0 @@
1
- require 'helper'
2
-
3
- describe String do
4
- it 'knows if it is a valid luhn' do
5
- '3910304298'.valid_luhn?.must_equal true
6
- end
7
-
8
- it 'knows if it is an civic number' do
9
- '3910304298'.civic_number?.must_equal true
10
- end
11
- end
12
-
13
- describe Numeric do
14
- it 'knows if it is a valid luhn' do
15
- 3910304298.valid_luhn?.must_equal true
16
- end
17
-
18
- it 'knows if it is an civic number' do
19
- 3910304298.civic_number?.must_equal true
20
- end
21
- end