luhnacy 0.1.0 → 0.2.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.
data/README.rdoc CHANGED
@@ -8,6 +8,8 @@ To require:
8
8
 
9
9
  require 'luhnacy'
10
10
 
11
+ === Generic Validation\Generation
12
+
11
13
  To validate:
12
14
 
13
15
  Luhnacy.valid?('49927398716')
@@ -20,6 +22,40 @@ To generate a string of 10 digits that does not satisfy Luhn algorithm:
20
22
 
21
23
  invalid_string = Luhnacy.generate(10, :invalid => true)
22
24
 
25
+ To generate a string of 10 digits that satisfies Luhn and starts with predefined characters:
26
+
27
+ Luhnacy.generate(10, :prefix => '12345') #=> "1234597480"
28
+
29
+ === Named Generators/Validators
30
+
31
+ There are named validators and generators for Visa, Mastercard and American Express credit cards. Note: Visa validation/generation only works for 16-digit credit card numbers.
32
+
33
+ Example usage (mastercard)
34
+
35
+ To validate a mastercard:
36
+
37
+ Luhnacy.mastercard?("5176290135048779")
38
+
39
+ To generate a mastercard number that satisfies Luhn:
40
+
41
+ Luhnacy.mastercard #=> "5151199732615386"
42
+
43
+ To generate a master card number that does not satisfy Luhn:
44
+
45
+ Luhnacy.mastercard(:invalid => true)
46
+
47
+ Similar usage exists for Visa and American Express:
48
+
49
+ Luhnacy.visa
50
+ Luhnacy.visa?
51
+
52
+ Luhnacy.amex
53
+ Luhnacy.amex?
54
+
55
+ == Planned changes
56
+
57
+ At some point it may make sense to store the patterns for the named generator in a seperate class/module or even in a YAML file. This will be driven by the need for additional named generators. If a YAML file is used, then the very next release may also include the ability to pass Luhnacy a custom YAML file for generating/validating strings.
58
+
23
59
  == Note on Patches/Pull Requests
24
60
 
25
61
  * Fork the project.
@@ -35,6 +71,8 @@ To generate a string of 10 digits that does not satisfy Luhn algorithm:
35
71
  * http://blog.flame.org/2008/3/24/checking-credit-card-numbers-in-ruby
36
72
  * http://www.missiondata.com/blog/web-development/25/credit-card-type-and-luhn-check-in-ruby/
37
73
  * http://en.wikipedia.org/wiki/Luhn
74
+ * http://www.darkcoding.net/credit-card-numbers/
75
+ * http://en.wikipedia.org/wiki/Credit_card_number
38
76
 
39
77
  == Copyright
40
78
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/lib/luhnacy.rb CHANGED
@@ -1,11 +1,18 @@
1
1
  class Luhnacy
2
+ @cards = {
3
+ :mastercard => { :prefixes => [ '51', '52', '53', '54', '55' ], :size => 16 },
4
+ :visa => { :prefixes => ['4'], :size => 16 },
5
+ :amex => { :prefixes => ['34','37'], :size => 15 }
6
+ }
2
7
  def self.valid?(candidate)
3
8
  calc_modulus(candidate) == 0
4
9
  end
5
10
 
6
11
  def self.generate(string_size, options={})
7
- output = ''
8
- (string_size-1).times do |n|
12
+ raise ArgumentError, "prefix must be numeric" if options[:prefix] && !(options[:prefix] =~ /^\d*$/)
13
+
14
+ output = options[:prefix] || ''
15
+ (string_size-output.size-1).times do |n|
9
16
  output += rand(10).to_s
10
17
  end
11
18
  output += '0'
@@ -28,6 +35,14 @@ class Luhnacy
28
35
  output
29
36
  end
30
37
 
38
+ def self.method_missing(type, *args)
39
+ card_type, method_type = parse_method_name(type)
40
+
41
+ raise NoMethodError unless @cards[card_type] && @cards[card_type][:prefixes] && @cards[card_type][:size]
42
+
43
+ send(method_type, *(args.unshift(card_type)))
44
+ end
45
+
31
46
  private
32
47
  def self.double_and_fix(number)
33
48
  2 * number > 9 ? ( (2 * number) % 10 + 1 ) : 2 * number
@@ -46,4 +61,29 @@ class Luhnacy
46
61
 
47
62
  sum % 10
48
63
  end
64
+
65
+ def self.parse_method_name(method_name)
66
+ method_name = method_name.to_s
67
+ case method_name
68
+ when /(.*)\?$/
69
+ [ $~[1].to_sym, :valid_card? ]
70
+ else
71
+ [ method_name.to_sym, :generate_card ]
72
+ end
73
+ end
74
+
75
+ def self.valid_card?(card_type, card_number)
76
+ valid?(card_number) && valid_pattern?(card_type, card_number)
77
+ end
78
+
79
+ def self.generate_card(card_type, options={})
80
+ generate(@cards[card_type][:size], options.merge({:prefix => @cards[card_type][:prefixes][rand(@cards[card_type][:prefixes].size)]}))
81
+ end
82
+
83
+ def self.valid_pattern?(card_type, card_number)
84
+ @cards[card_type][:prefixes].each do |prefix|
85
+ return true if card_number =~ /^#{prefix}\d{#{@cards[card_type][:size] - prefix.size}}$/
86
+ end
87
+ false
88
+ end
49
89
  end
data/luhnacy.gemspec ADDED
@@ -0,0 +1,55 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{luhnacy}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Rory McKinley"]
12
+ s.date = %q{2010-08-07}
13
+ s.description = %q{luhnacy can be used to validate strings for Luhn compliance as well as generating valid or invalid strings for the purposes of testing }
14
+ s.email = %q{rorymckinley@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/luhnacy.rb",
27
+ "luhnacy.gemspec",
28
+ "spec/luhnacy_spec.rb",
29
+ "spec/spec.opts",
30
+ "spec/spec_helper.rb"
31
+ ]
32
+ s.homepage = %q{http://github.com/rorymckinley/luhnacy}
33
+ s.rdoc_options = ["--charset=UTF-8"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.7}
36
+ s.summary = %q{A gem tohelp with the tedium of validating Luhn-compliant strings}
37
+ s.test_files = [
38
+ "spec/luhnacy_spec.rb",
39
+ "spec/spec_helper.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
47
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
48
+ else
49
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
50
+ end
51
+ else
52
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
53
+ end
54
+ end
55
+
data/spec/luhnacy_spec.rb CHANGED
@@ -23,4 +23,51 @@ describe "Luhnacy" do
23
23
  candidate = Luhnacy.generate(string_size, :invalid => true)
24
24
  Luhnacy.valid?(candidate).should be_false
25
25
  end
26
+
27
+ it "should return a string that satisfies luhn and includes a given prefix" do
28
+ prefix = '12345'
29
+ string_size = 15
30
+ candidate = Luhnacy.generate(string_size, :prefix => prefix)
31
+ candidate.should match /^#{prefix}\d{#{string_size - prefix.size}}$/
32
+ end
33
+
34
+ it "should return an error if the prefix contains any non-numeric characters" do
35
+ prefix = 'AB123'
36
+ string_size = 15
37
+ lambda { Luhnacy.generate(string_size, :prefix => prefix) }.should raise_error ArgumentError
38
+ end
39
+
40
+ context "Named generators and validators" do
41
+ it "should validate a correct number" do
42
+ number = '5354334446769063'
43
+ Luhnacy.mastercard?(number).should be_true
44
+ end
45
+
46
+ it "should not validate a number if it does not satisfy Luhn" do
47
+ number = '5354334446769064'
48
+ Luhnacy.mastercard?(number).should be_false
49
+ end
50
+
51
+ it "should not validate a number if it does not have the correct prefix" do
52
+ number = Luhnacy.generate(16, :prefix => '49')
53
+ Luhnacy.mastercard?(number).should be_false
54
+ end
55
+
56
+ it "should not validate a number if it does not have the correct length" do
57
+ number = Luhnacy.generate(12, :prefix => '52')
58
+ Luhnacy.mastercard?(number).should be_false
59
+ end
60
+
61
+ it "should generate a valid number" do
62
+ Luhnacy.mastercard?(Luhnacy.mastercard).should be_true
63
+ end
64
+
65
+ it "should generate an invalid number" do
66
+ Luhnacy.mastercard?(Luhnacy.mastercard(:invalid => true)).should be_false
67
+ end
68
+
69
+ it "should raise an error if there is no matcher or validator with a given name" do
70
+ lambda { Luhnacy.superawesomecard?('123') }.should raise_error NoMethodError
71
+ end
72
+ end
26
73
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: luhnacy
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Rory McKinley
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-07-19 00:00:00 +02:00
18
+ date: 2010-08-07 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -51,6 +51,7 @@ files:
51
51
  - Rakefile
52
52
  - VERSION
53
53
  - lib/luhnacy.rb
54
+ - luhnacy.gemspec
54
55
  - spec/luhnacy_spec.rb
55
56
  - spec/spec.opts
56
57
  - spec/spec_helper.rb