luhnacy 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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