├── .travis.yml ├── lib ├── kangal │ ├── version.rb │ ├── ip.rb │ ├── phone.rb │ ├── email.rb │ ├── subdomain.rb │ ├── tckn.rb │ ├── tcvkn.rb │ ├── tax_number.rb │ └── identity_number.rb └── kangal.rb ├── Gemfile ├── Rakefile ├── .gitignore ├── SECURITY.md ├── spec ├── spec_helper.rb ├── email_spec.rb ├── tcvkn_spec.rb ├── tckn_spec.rb ├── tax_number_spec.rb ├── identity_number_spec.rb ├── ip_spec.rb ├── subdomain_spec.rb └── phone_spec.rb ├── config └── locales │ ├── en.yml │ ├── tr.yml │ └── fr.yml ├── kangal.gemspec ├── LICENSE.txt ├── CHANGELOG.md └── README.md /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.0.0 -------------------------------------------------------------------------------- /lib/kangal/version.rb: -------------------------------------------------------------------------------- 1 | module Kangal 2 | VERSION = '1.2.3'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in kangal.gemspec 4 | gemspec 5 | 6 | gem 'rspec' 7 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rspec/core/rake_task' 3 | 4 | RSpec::Core::RakeTask.new 5 | 6 | task :default => :spec 7 | task :test => :spec 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | .idea 19 | .swp 20 | .rvmrc 21 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting Security Issues 2 | 3 | If you discover a security issue in Kangel, please report it by sending an email to info@lab2023.com 4 | 5 | This will allow us to assess the risk, and make a fix available before we add a bug report to the Github repo. 6 | 7 | Thanks for helping make Kangal safe for everyone. -------------------------------------------------------------------------------- /lib/kangal.rb: -------------------------------------------------------------------------------- 1 | require 'kangal/version' 2 | require 'kangal/email' 3 | require 'kangal/subdomain' 4 | require 'kangal/identity_number' 5 | require 'kangal/tckn' 6 | require 'kangal/tax_number' 7 | require 'kangal/tcvkn' 8 | require 'kangal/ip' 9 | require 'kangal/phone' 10 | 11 | I18n.load_path += Dir.glob(File.expand_path('../../config/locales/**/*',__FILE__)) 12 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler/setup' 3 | require 'active_model' 4 | require 'kangal' 5 | 6 | class SpecModel 7 | 8 | include ActiveModel::Validations 9 | 10 | def initialize(attributes = {}) 11 | @attributes = attributes 12 | end 13 | 14 | def read_attribute_for_validation(key) 15 | @attributes[key] 16 | end 17 | 18 | end -------------------------------------------------------------------------------- /lib/kangal/ip.rb: -------------------------------------------------------------------------------- 1 | require 'active_model' 2 | require 'active_model/validations' 3 | 4 | class IpValidator < ActiveModel::EachValidator 5 | def validate_each(object, attribute, value) 6 | 7 | return if options[:allow_nil] && value.nil? 8 | return if options[:allow_blank] && value.blank? 9 | 10 | object.errors[attribute] << I18n.t(:invalid, scope: 'kangal.validations.ip') unless value =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/i 11 | end 12 | end -------------------------------------------------------------------------------- /spec/email_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | class User < SpecModel 4 | validates :email, email: true 5 | end 6 | 7 | describe 'Email format' do 8 | 9 | let(:invalid_emails) { %w(invalid email) } 10 | let(:valid_emails) { %w(info@lab2023.com abc@ab.com) } 11 | 12 | it 'should be invalid' do 13 | invalid_emails.each { |email| User.new(email: email).valid?.should be_false } 14 | end 15 | 16 | it 'should be valid' do 17 | valid_emails.each { |email| User.new(email: email).valid?.should be_true } 18 | end 19 | 20 | end -------------------------------------------------------------------------------- /spec/tcvkn_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | class CompanyDetail < SpecModel 4 | validates :tax, tcvkn: true 5 | end 6 | 7 | describe 'tax number format' do 8 | 9 | let(:invalid_tcvkn) { %w(1 3 434542345678 43454234567) } 10 | let(:valid_tcvkn) { %w(2640020928 6120069217) } 11 | 12 | it 'should be invalid' do 13 | invalid_tcvkn.each { |tax| CompanyDetail.new(tax: tax).valid?.should be_false } 14 | end 15 | 16 | it 'should be valid' do 17 | valid_tcvkn.each { |tax| CompanyDetail.new(tax: tax).valid?.should be_true } 18 | end 19 | end -------------------------------------------------------------------------------- /spec/tckn_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | class Profile < SpecModel 4 | validates :identity, tckn: true 5 | end 6 | 7 | describe 'Tckn number format' do 8 | 9 | let(:invalid_tckn) { %w(1 3 434542345678) } 10 | let(:valid_tckn) { %w(21432692144 55679901158 83317527040) } 11 | 12 | it 'should be invalid' do 13 | invalid_tckn.each { |identity| Profile.new(identity: identity).valid?.should be_false } 14 | end 15 | 16 | it 'should be valid' do 17 | valid_tckn.each { |identity| Profile.new(identity: identity).valid?.should be_true } 18 | end 19 | end -------------------------------------------------------------------------------- /spec/tax_number_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | class CompanyDetail < SpecModel 4 | validates :tax, tax_number: true 5 | end 6 | 7 | describe 'tax number format' do 8 | 9 | let(:invalid_tax_numbers) { %w(1 3 434542345678 43454234567) } 10 | let('valid_tax_numbers') { %w(2640020928 6120069217) } 11 | 12 | it 'should be invalid' do 13 | invalid_tax_numbers.each { |tax| CompanyDetail.new(tax: tax).valid?.should be_false } 14 | end 15 | 16 | it 'should be valid' do 17 | valid_tax_numbers.each { |tax| CompanyDetail.new(tax: tax).valid?.should be_true } 18 | end 19 | end -------------------------------------------------------------------------------- /lib/kangal/phone.rb: -------------------------------------------------------------------------------- 1 | require 'active_model' 2 | require 'active_model/validations' 3 | 4 | # All phones number should be store e.164 format standard 5 | class PhoneValidator < ActiveModel::EachValidator 6 | def validate_each(object, attribute, value) 7 | 8 | return if options[:allow_nil] && value.nil? 9 | return if options[:allow_blank] && value.blank? 10 | 11 | if options[:tr] 12 | object.errors[attribute] << I18n.t('kangal.validations.common.invalid') unless value =~ /^(90)+\d{10}$/i 13 | end 14 | 15 | object.errors[attribute] << I18n.t('kangal.validations.phone.tr') unless value =~ /^\d{11,14}$/i 16 | end 17 | end -------------------------------------------------------------------------------- /spec/identity_number_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | class Profile < SpecModel 4 | validates :identity, identity_number: true 5 | end 6 | 7 | describe 'Identity number format' do 8 | 9 | let(:invalid_identity_numbers) { %w(1 3 434542345678) } 10 | let(:valid_identity_numbers) { %w(21432692144 55679901158 83317527040) } 11 | 12 | it 'should be invalid' do 13 | invalid_identity_numbers.each { |identity| Profile.new(identity: identity).valid?.should be_false } 14 | end 15 | 16 | it 'should be valid' do 17 | valid_identity_numbers.each { |identity| Profile.new(identity: identity).valid?.should be_true } 18 | end 19 | end -------------------------------------------------------------------------------- /lib/kangal/email.rb: -------------------------------------------------------------------------------- 1 | require 'active_model' 2 | require 'active_model/validations' 3 | require 'mail' 4 | 5 | class EmailValidator < ActiveModel::EachValidator 6 | 7 | def validate_each(object, attribute, value) 8 | 9 | return if options[:allow_nil] && value.nil? 10 | return if options[:allow_blank] && value.blank? 11 | 12 | begin 13 | m = Mail::Address.new(value) 14 | r = m.domain && m.address == value 15 | t = m.__send__(:tree) 16 | r &&= (t.domain.dot_atom_text.elements.size > 1) 17 | rescue Exception => e 18 | r = false 19 | end 20 | object.errors.add attribute, (options[:message] || I18n.t(:invalid, :scope => 'kangal.validations.email')) unless r 21 | end 22 | 23 | end -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | kangal: 3 | validations: 4 | common: 5 | invalid: 'is invalid' 6 | email: 7 | invalid: 'is invalid' 8 | subdomain: 9 | reserved: 'cannot be a reserved name' 10 | character: 'must have between 3 and 63 letters' 11 | hyphen: 'cannot start or end with a hyphen' 12 | alphanumeric: 'must be alphanumeric; A-Z, 0-9 or hyphen' 13 | identity_number: 14 | invalid: 'is invalid.' 15 | tckn: 16 | invalid: 'is invalid.' 17 | tax_number: 18 | invalid: 'is invalid.' 19 | tcvkn: 20 | invalid: 'is invalid.' 21 | ip: 22 | invalid: 'is invalid.' 23 | phone: 24 | tr: 'should be start with 90' -------------------------------------------------------------------------------- /config/locales/tr.yml: -------------------------------------------------------------------------------- 1 | tr: 2 | kangal: 3 | validations: 4 | common: 5 | invalid: 'geçersizdir.' 6 | email: 7 | invalid: 'geçersizdir.' 8 | subdomain: 9 | reserved: 'bu isim alınamaz' 10 | character: '3 ile 63 karakter arasında olmalıdır' 11 | hyphen: 'tire ile başalayamaz veya bitemez' 12 | alphanumeric: 'alfanümerik olmalıdır; A-Z, 0-9 veya tire' 13 | identity_number: 14 | invalid: 'geçersizdir.' 15 | tckn: 16 | invalid: 'geçersizdir.' 17 | tax_number: 18 | invalid: 'geçersizdir.' 19 | tcvkn: 20 | invalid: 'geçersizdir.' 21 | ip: 22 | invalid: 'geçersizdir.' 23 | phone: 24 | tr: '90 ile başlaması lazım.' 25 | -------------------------------------------------------------------------------- /config/locales/fr.yml: -------------------------------------------------------------------------------- 1 | en: 2 | kangal: 3 | validations: 4 | common: 5 | invalid: 'est invalide' 6 | email: 7 | invalid: 'est invalide' 8 | subdomain: 9 | reserved: 'ce nom ne peut pas être réservé' 10 | character: 'il faut que ce soit entre 3 et 63 lettres' 11 | hyphen: 'il peut pas commencer ou finir avec un trait' 12 | alphanumeric: 'il faut être alphanumérique; A-Z, 0-9 ou trait' 13 | identity_number: 14 | invalid: 'est invalide.' 15 | tckn: 16 | invalid: 'est invalide.' 17 | tax_number: 18 | invalid: 'est invalide.' 19 | tcvkn: 20 | invalid: 'est invalide.' 21 | ip: 22 | invalid: 'est invalide.' 23 | phone: 24 | tr: '90 ile başlaması lazım.' 25 | -------------------------------------------------------------------------------- /spec/ip_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | class Server < SpecModel 4 | validates :ip, ip: true 5 | end 6 | 7 | describe 'Ip format' do 8 | 9 | let(:invalid_ips) do 10 | %w( 11 | 10.10.10 12 | 10.10 13 | 10 14 | a.a.a.a 15 | 10.0.0.a 16 | 10.10.10.256 17 | 10.10.10.256 18 | 999.10.10.20 19 | 2222.22.22.22 20 | 22.2222.22.2 21 | ) 22 | end 23 | 24 | let(:valid_ips) do 25 | %w( 26 | 1.1.1.1 27 | 255.255.255.255 28 | 192.168.1.1 29 | 10.10.1.1 30 | 132.254.111.10 31 | 26.10.2.10 32 | 127.0.0.1 33 | ) 34 | end 35 | 36 | it 'should be invalid' do 37 | invalid_ips.each { |ip| Server.new(ip: ip).valid?.should be_false } 38 | end 39 | 40 | it 'should be valid' do 41 | valid_ips.each { |ip| Server.new(ip: ip).valid?.should be_true } 42 | end 43 | 44 | end -------------------------------------------------------------------------------- /lib/kangal/subdomain.rb: -------------------------------------------------------------------------------- 1 | require 'active_model' 2 | require 'active_model/validations' 3 | 4 | class SubdomainValidator < ActiveModel::EachValidator 5 | def validate_each(object, attribute, value) 6 | 7 | return if options[:allow_nil] && value.nil? 8 | return if options[:allow_blank] && value.blank? 9 | return unless value.present? 10 | 11 | reserved_names = %w(www ftp mail pop smtp admin ssl sftp http https) 12 | reserved_names = options[:reserved] if options[:reserved] 13 | 14 | if reserved_names.include?(value) 15 | object.errors[attribute] << I18n.t(:reserved, scope: 'kangal.validations.subdomain') 16 | end 17 | 18 | object.errors[attribute] << I18n.t(:character, scope: 'kangal.validations.subdomain') unless (3..63) === value.length 19 | object.errors[attribute] << I18n.t(:hyphen, scope: 'kangal.validations.subdomain') unless value =~ /^[^-].*[^-]$/i 20 | object.errors[attribute] << I18n.t(:alphanumeric, scope: 'kangal.validations.subdomain') unless value =~ /^[a-z0-9\-]*$/i 21 | end 22 | end -------------------------------------------------------------------------------- /kangal.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'kangal/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = 'kangal' 8 | spec.version = Kangal::VERSION 9 | spec.authors = ['lab2023', 'Onur Özgür ÖZKAN'] 10 | spec.email = %w(info@lab2023.com onur.ozgur.ozkan@lab2023.com) 11 | spec.description = %q{Kangal brings you a nice set of custom validators for Rails 4.} 12 | spec.summary = %q{Kangal brings you a nice set of custom validators for Rails 4.} 13 | spec.homepage = 'https://github.com/kebab-project/kangal' 14 | spec.license = 'MIT' 15 | 16 | spec.files = `git ls-files`.split($/) 17 | spec.require_paths = %w(lib) 18 | 19 | spec.add_development_dependency 'bundler', '~> 1.3' 20 | spec.add_development_dependency 'rspec' 21 | spec.add_development_dependency 'rake' 22 | 23 | spec.add_runtime_dependency 'mail' 24 | spec.add_runtime_dependency 'activemodel', '>= 0' 25 | end 26 | -------------------------------------------------------------------------------- /lib/kangal/tckn.rb: -------------------------------------------------------------------------------- 1 | require 'active_model' 2 | require 'active_model/validations' 3 | 4 | class TcknValidator < ActiveModel::EachValidator 5 | def validate_each(record, attribute, value) 6 | 7 | return if options[:allow_nil] && value.nil? 8 | return if options[:allow_blank] && value.blank? 9 | 10 | digits = value[0..-3].each_char.map(&:to_i).each_with_index 11 | first, last = 12 | digits.reduce([0, 0]) do |memo, (digit, idx)| 13 | add = digit * (idx.even? ? 7 : -1) 14 | [ 15 | (memo.first + add) % 10, 16 | (memo.last + digit + add) % 10 17 | ] 18 | end 19 | 20 | valid = (!invalid_value?(value, 11) && value[-2] == first.to_s && value[-1] == last.to_s) 21 | record.errors.add attribute, (options[:message] || I18n.t(:invalid, :scope => 'kangal.validations.tckn')) unless valid 22 | end 23 | 24 | private 25 | 26 | def invalid_value?(str, length) 27 | str.nil? || str.length != length || !numeric?(str) 28 | end 29 | 30 | def numeric?(str) 31 | !!(str =~ /\A[[:digit:]]+\Z/) 32 | end 33 | end -------------------------------------------------------------------------------- /spec/subdomain_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | class Company < SpecModel 4 | validates :subdomain, subdomain: true 5 | end 6 | 7 | class Account < SpecModel 8 | validates :subdomain, subdomain: {reserved: %w{help reserved_word}} 9 | end 10 | 11 | describe 'Subdomain format' do 12 | 13 | let(:invalid_subdomains) { %w(-lab2023 https ab) } 14 | let(:valid_subdomains) { %w(lab2023 lab2023-internet) } 15 | 16 | it 'should be invalid' do 17 | invalid_subdomains.each { |subdomain| Company.new(subdomain: subdomain).valid?.should be_false } 18 | end 19 | 20 | it 'should be valid' do 21 | valid_subdomains.each { |subdomain| Company.new(subdomain: subdomain).valid?.should be_true } 22 | end 23 | 24 | it 'should be invalid because of reserved' do 25 | account = Account.new(subdomain: 'reserved_word') 26 | account.valid? 27 | account.errors.messages[:subdomain].should include(I18n.t(:reserved, scope: 'kangal.validations.subdomain')) 28 | end 29 | 30 | it 'should be valid because of reserved' do 31 | Account.new(subdomain: 'unreservedword').valid?.should be_true 32 | end 33 | 34 | end -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 lab2023 - information technologies 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /lib/kangal/tcvkn.rb: -------------------------------------------------------------------------------- 1 | require 'active_model' 2 | require 'active_model/validations' 3 | 4 | class TcvknValidator < ActiveModel::EachValidator 5 | def validate_each(object, attribute, value) 6 | 7 | return if options[:allow_nil] && value.nil? 8 | return if options[:allow_blank] && value.blank? 9 | 10 | 11 | digits = value[0..-2].each_char.map(&:to_i).each_with_index 12 | 13 | checksum = 14 | digits.reduce(0) do |memo, (digit, idx)| 15 | rev_idx = 9 - idx 16 | coeff = [1, 2, 4, 8, 7, 5][rev_idx % 6] 17 | result = (digit + rev_idx) % 10 18 | 19 | if result.nonzero? 20 | result = (coeff * result) % 9 21 | result = 9 if result.zero? 22 | end 23 | memo += result 24 | end 25 | 26 | valid = !invalid_value?(value, 10) && ((checksum + value[-1].to_i) % 10 == 0) 27 | 28 | object.errors.add attribute, (options[:message] || I18n.t(:invalid, :scope => 'kangal.validations.tax_number')) unless valid 29 | end 30 | 31 | private 32 | 33 | def invalid_value?(str, length) 34 | str.nil? || str.length != length || !numeric?(str) 35 | end 36 | 37 | def numeric?(str) 38 | !!(str =~ /\A[[:digit:]]+\Z/) 39 | end 40 | end -------------------------------------------------------------------------------- /lib/kangal/tax_number.rb: -------------------------------------------------------------------------------- 1 | require 'active_model' 2 | require 'active_model/validations' 3 | 4 | class TaxNumberValidator < ActiveModel::EachValidator 5 | def validate_each(object, attribute, value) 6 | 7 | ActiveSupport::Deprecation.warn "`tax_number: :true` is deprecated and may be removed from future releases, use `tcvkn: true` instead.", caller 8 | 9 | return if options[:allow_nil] && value.nil? 10 | return if options[:allow_blank] && value.blank? 11 | 12 | valid = false 13 | val = value.to_s 14 | if val.size == 10 15 | val1 = Array.new 16 | val2 = Array.new 17 | last_digit = val[9].to_i 18 | 19 | (0..8).each do |index| 20 | val1 << ((val[index].to_i + (9 - index)) % 10).to_i 21 | end 22 | 23 | (0..8).each do |index| 24 | val2 << ((val1[index].to_i * (2 ** (9 - index))) % 9).to_i 25 | end 26 | 27 | (0..8).each do |index| 28 | val2[index] = 9 if (val1[index] != 0 && val2[index] == 0) 29 | end 30 | 31 | sum = 0 32 | 33 | (0..8).each do |index| 34 | sum += val2[index] 35 | end 36 | 37 | if (sum % 10) == 0 38 | sum = 0 39 | else 40 | sum = 10 - (sum % 10) 41 | end 42 | 43 | valid = (sum == last_digit) 44 | 45 | end 46 | 47 | object.errors.add attribute, (options[:message] || I18n.t(:invalid, :scope => 'kangal.validations.tax_number')) unless valid 48 | end 49 | end -------------------------------------------------------------------------------- /lib/kangal/identity_number.rb: -------------------------------------------------------------------------------- 1 | require 'active_model' 2 | require 'active_model/validations' 3 | 4 | class IdentityNumberValidator < ActiveModel::EachValidator 5 | def validate_each(record, attribute, value) 6 | 7 | ActiveSupport::Deprecation.warn "`identity_number: :true` is deprecated and may be removed from future releases, use `tckn: true` instead.", caller 8 | 9 | return if options[:allow_nil] && value.nil? 10 | return if options[:allow_blank] && value.blank? 11 | 12 | valid = false 13 | val = value.to_s 14 | 15 | if val.size == 11 && val[0].to_i != 0 16 | valid = check_tenth_character(val) 17 | valid = check_eleventh_character(val) 18 | valid = double_check_eleventh_character(val) 19 | end 20 | 21 | record.errors.add attribute, (options[:message] || I18n.t(:invalid, :scope => 'kangal.validations.identity_number')) unless valid 22 | end 23 | 24 | private 25 | 26 | def check_eleventh_character(val) 27 | sum = 0 28 | (0..9).each do |counter| 29 | sum += val[counter].to_i 30 | end 31 | 32 | val[10].to_i == sum % 10 33 | end 34 | 35 | def check_tenth_character(val) 36 | odd_sum = 0 37 | even_sum = 0 38 | (0..8).each do |counter| 39 | if counter.even? 40 | odd_sum += val[counter].to_i 41 | else 42 | even_sum += val[counter].to_i 43 | end 44 | end 45 | val[9].to_i == ((odd_sum*7 + even_sum*9)%10) 46 | end 47 | 48 | def double_check_eleventh_character(val) 49 | sum = 0 50 | (0..8).each do |counter| 51 | if counter.even? 52 | sum += val[counter].to_i 53 | end 54 | end 55 | val[10].to_i == ((sum*8)%10) 56 | end 57 | 58 | end -------------------------------------------------------------------------------- /spec/phone_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | class Phone < SpecModel 4 | validates :number, phone: true 5 | end 6 | 7 | class PhoneTr < SpecModel 8 | validates :number, phone: {tr: true} 9 | end 10 | 11 | class PhoneTrMobile < SpecModel 12 | validates :number, phone: {tr_and_mobile: true} 13 | end 14 | 15 | class PhoneTrNormal < SpecModel 16 | validates :number, phone: {tr_and_normal: true} 17 | end 18 | 19 | describe 'Phone format' do 20 | 21 | let(:valid_phone) do 22 | %w( 23 | 905532620000 24 | 902122120000 25 | ) 26 | end 27 | 28 | let(:invalid_phone) do 29 | %w( 30 | abde 31 | 1234 32 | 12341234123443434 33 | ) 34 | end 35 | 36 | it 'should be valid' do 37 | valid_phone.each { |number| Phone.new(number: number).valid?.should be_true } 38 | end 39 | 40 | it 'should be invalid' do 41 | invalid_phone.each { |number| Phone.new(number: number).valid?.should be_false } 42 | end 43 | 44 | let(:valid_tr) do 45 | %w( 46 | 905326200000 47 | 908508850000 48 | ) 49 | end 50 | 51 | let(:invalid_tr) do 52 | %w( 53 | +1231231233200 54 | 00100000000000 55 | ) 56 | end 57 | 58 | it 'should be valid with tr option' do 59 | valid_tr.each { |tr_phone| PhoneTr.new(number: tr_phone).valid?.should be_true } 60 | end 61 | 62 | it 'should be invalid with tr option' do 63 | invalid_tr.each { |tr_phone| PhoneTr.new(number: tr_phone).valid?.should be_false } 64 | end 65 | 66 | it 'should be valid with tr and mobile option' do 67 | 68 | end 69 | 70 | it 'should be invalid with tr and mobile option' do 71 | 72 | end 73 | 74 | it 'should be valid with tr and normal option' do 75 | 76 | end 77 | 78 | it 'should be invalid with tr and normal option' do 79 | 80 | end 81 | 82 | end -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | #### [Current] 3 | * [3b644b2](../../commit/3b644b2) - __(Onur Özgür ÖZKAN)__ typo fixed. 4 | * [a7c1f82](../../commit/a7c1f82) - __(hamitturkukaya)__ [#11](../../issues/11) Turkish Government Tax Number for company validation implemented 5 | 6 | - Changelog and Readme Updated 7 | 8 | * [b34a9df](../../commit/b34a9df) - __(hamitturkukaya)__ [#11](../../issues/11) Turkish Government Tax Number for company validation implemented 9 | * [22f50ed](../../commit/22f50ed) - __(hamitturkukaya)__ [#12](../../issues/12) Turkish Government Identity Number validation 10 | 11 | - Readme.md an Changelog.md updated 12 | 13 | * [a194920](../../commit/a194920) - __(hamitturkukaya)__ [#12](../../issues/12) Turkish Government Identity Number validation 14 | 15 | - New validation method added 16 | - Rspec fails fixed 17 | 18 | * [4e89b77](../../commit/4e89b77) - __(hamitturkukaya)__ [#12](../../issues/12) Turkish Government Identity Number checked 19 | * [afc8352](../../commit/afc8352) - __(Muhammet DİLEK)__ readme updated 20 | * [dc23c13](../../commit/dc23c13) - __(Muhammet DİLEK)__ readme updated 21 | * [0be7a3c](../../commit/0be7a3c) - __(Muhammet DİLEK)__ typo fixed 22 | * [aacb1e0](../../commit/aacb1e0) - __(Onur Özgür ÖZKAN)__ Add fr.yml 23 | * [c776763](../../commit/c776763) - __(Onur Ozgur OZKAN)__ bump version 1.0.0 24 | * [2b6753e](../../commit/2b6753e) - __(Muhammet DİLEK)__ [#3](../../issues/3) subdomain validator added 25 | 26 | #### 0.1.2 27 | * [965d580](../../commit/965d580) - __(Onur Ozgur OZKAN)__ bump version 0.1.2 28 | * [eacf477](../../commit/eacf477) - __(Onur Ozgur OZKAN)__ [#8](../../issues/8) rename gem cerberus to kangal 29 | * [ca1bc8f](../../commit/ca1bc8f) - __(Onur Ozgur OZKAN)__ bump version 30 | * [d7a0d8e](../../commit/d7a0d8e) - __(Onur Ozgur OZKAN)__ add summary and description to gemspec file. 31 | 32 | #### 1.0.0 33 | * [41e3589](../../commit/41e3589) - __(Onur Ozgur OZKAN)__ add CHANGELOG.md 34 | * [bca3a4c](../../commit/bca3a4c) - __(Onur Ozgur OZKAN)__ add CHANGELOG.md 35 | * [8a5dd69](../../commit/8a5dd69) - __(Onur Ozgur OZKAN)__ [#7](../../issues/7) add travis-ci flag to README.md 36 | * [5a48bab](../../commit/5a48bab) - __(Onur Ozgur OZKAN)__ [#2](../../issues/2) fixed email format for spec 37 | * [382d3d1](../../commit/382d3d1) - __(Onur Ozgur OZKAN)__ [#7](../../issues/7) add travis-ci service 38 | * [85ad341](../../commit/85ad341) - __(Onur Ozgur OZKAN)__ Improve README.md 39 | * [4a986b9](../../commit/4a986b9) - __(Onur Ozgur OZKAN)__ [#5](../../issues/5) add locale system and files 40 | * [80f0aea](../../commit/80f0aea) - __(Onur Ozgur OZKAN)__ [#2](../../issues/2) add email validation 41 | * [189bbba](../../commit/189bbba) - __(Onur Ozgur OZKAN)__ [#2](../../issues/2) add spec for email 42 | * [42b68b5](../../commit/42b68b5) - __(Onur Ozgur OZKAN)__ [#4](../../issues/4) setup rspec and rake 43 | * [34cc03a](../../commit/34cc03a) - __(Onur Ozgur OZKAN)__ [#4](../../issues/4) set rspec and rake 44 | * [3d0b486](../../commit/3d0b486) - __(Onur Ozgur OZKAN)__ [#1](../../issues/1) fix license.txt 45 | * [cd9ed2e](../../commit/cd9ed2e) - __(Onur Ozgur OZKAN)__ [#1](../../issues/1) convert double quotes to single quotes 46 | * [c9896cb](../../commit/c9896cb) - __(Onur Ozgur OZKAN)__ [#1](../../issues/1) setup Code Climate and Gemnasium 47 | * [8ef9ff8](../../commit/8ef9ff8) - __(Onur Ozgur OZKAN)__ [#1](../../issues/1) setup gem 48 | * [29e3e1e](../../commit/29e3e1e) - __(Onur Ozgur OZKAN)__ [#1](../../issues/1) setup gem 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kangal 2 | 3 | [![Code Climate](https://codeclimate.com/github/kebab-project/kangal.png)](https://codeclimate.com/github/kebab-project/kangal) 4 | [![Dependency Status](https://gemnasium.com/kebab-project/kangal.png)](https://gemnasium.com/kebab-project/kangal) 5 | [![Build Status](https://travis-ci.org/lab2023/kangal.png?branch=develop)](https://travis-ci.org/lab2023/kangal) 6 | 7 | 8 | ## Requirements 9 | 10 | Before generating your application, you will need: 11 | 12 | * Ruby ~> 2.0 13 | * Rails ~> 4.0 14 | 15 | ## Usage 16 | 17 | In your Gemfile 18 | 19 | ```ruby 20 | gem 'kangal' 21 | ``` 22 | 23 | ### Email Validator 24 | ```ruby 25 | require 'kangal' 26 | class User 27 | include ActiveModel::Validations 28 | attr_accessor :email 29 | 30 | # Email validator 31 | validates :email, presence: :true, email: :true 32 | end 33 | 34 | 35 | p = User.new 36 | p.email = "info@lab2023.com" 37 | p.valid? # => true 38 | 39 | p.email = "info@lab" 40 | p.valid? # => false 41 | 42 | p.email = "Onur Ozgur " 43 | p.valid? # => false 44 | ``` 45 | 46 | ### Subdomain Validator 47 | ```ruby 48 | require 'kangal' 49 | class User 50 | include ActiveModel::Validations 51 | attr_accessor :subdomain 52 | 53 | # Subdomain validator 54 | validates :subdomain, subdomain: true 55 | 56 | # Or 57 | validates :subdomain, subdomain: { :reserved => %w(foo bar) } 58 | end 59 | 60 | 61 | p = User.new 62 | p.subdomain = "www" 63 | p.valid? # => false 64 | 65 | p.subdomain = "https" 66 | p.valid? # => false 67 | 68 | p.subdomain = "-lab2023" 69 | p.valid? # => false 70 | 71 | p.subdomain = "-lab2023-" 72 | p.valid? # => false 73 | 74 | p.subdomain = "foo" 75 | p.valid? # => false 76 | 77 | p.subdomain = "lab2023" 78 | p.valid? # => true 79 | ``` 80 | 81 | **Default reserved names:** www, ftp, mail, pop, smtp, admin, ssl, sftp, http, https 82 | 83 | ### Turkish Government Identity Number Validator 84 | ```ruby 85 | require 'kangal' 86 | class User 87 | include ActiveModel::Validations 88 | attr_accessor :identity 89 | 90 | # Identity Number validator 91 | validates :identity, presence: :true, identity_number: :true 92 | end 93 | 94 | p = User.new 95 | p.identity = "44234234" 96 | p.valid? # => false 97 | 98 | p = User.new 99 | p.identity = "02343214582" 100 | p.valid? # => false 101 | 102 | p = User.new 103 | p.identity = "83317527040" # (this isn't a real identity number) 104 | p.valid? # => true 105 | ``` 106 | 107 | ### Turkish Government Tax Number Validator 108 | ```ruby 109 | require 'kangal' 110 | class User 111 | include ActiveModel::Validations 112 | attr_accessor :tax_number 113 | 114 | # Identity Number validator 115 | validates :tax_number, presence: :true, tcvkn: :true 116 | end 117 | 118 | p = User.new 119 | p.tax_number = "44234234" 120 | p.valid? # => false 121 | 122 | p = User.new 123 | p.tax_number = "02343214582" 124 | p.valid? # => false 125 | 126 | p = User.new 127 | p.tax_number = "6120069217" # (this isn't a real tax number) 128 | p.valid? # => true 129 | ``` 130 | 131 | ### IP Validator 132 | ```ruby 133 | require 'kangal' 134 | class Server 135 | include ActiveModel::Validations 136 | attr_accessor :ip 137 | 138 | # Ip validator 139 | validates :ip, presence: :true, ip: :true 140 | end 141 | 142 | p = Server.new 143 | p.ip = "10.10.10.256" 144 | p.valid? # => false 145 | 146 | p = Server.new 147 | p.ip = "2222.22.22.22" 148 | p.valid? # => false 149 | 150 | p = Server.new 151 | p.ip = "255.255.255.255" 152 | p.valid? # => true 153 | 154 | p = Server.new 155 | p.ip = "132.254.111.10" 156 | p.valid? # => true 157 | ``` 158 | 159 | ## Bugs and Feedback 160 | 161 | If you discover any bugs or want to drop a line, feel free to create an issue on GitHub. 162 | 163 | http://github.com/lab2023/kangal 164 | 165 | ## Contributing 166 | 167 | Kangal uses [TomDoc](http://tomdoc.org/), [rDoc](http://rubydoc.info/gems/kangal) and [SemVer](http://semver.org/), and takes it seriously. 168 | 169 | Once you've made your great commits: 170 | 171 | 1. Fork Template 172 | 2. Create a topic branch - `git checkout -b my_branch` 173 | 3. Push to your branch - `git push origin my_branch` 174 | 4. Create a Pull Request from your branch 175 | 5. That's it! 176 | 177 | ## Credits 178 | 179 | ![lab2023](http://lab2023.com/assets/images/named-logo.png) 180 | 181 | - Kangal is maintained and funded by [lab2023 - information technologies](http://lab2023.com/) 182 | - Thank you to all the [contributors!](../../graphs/contributors) 183 | - The names and logos for lab2023 are trademarks of lab2023, inc. 184 | 185 | ## License 186 | 187 | Copyright 2014 lab2023 - information technologies 188 | --------------------------------------------------------------------------------