-2

I want to check if the variable which is basically a user input is a 10 digit phone number or not.

There are 2 sets of validations: - If num is less than 10 digit then prompt a msg - if num is a string instead rather than integer

@phone = params[:phone_num]
    puts "phone_num: #{@phone}"
    if @phone.is_a? Integer 
      puts "phone_num is int"
      if @phone.to_s.length == 10
        puts "10 digit"
        perform(@phone)
        @output = "Valid Number, will receive a call"
      end
    else 
      puts "Wont be calling"
      @output = "The number is invalid"
    end

The output that I get is always The number is invalid no matter what I enter in text box. There are many stack overflow answering dealing with different questions but wondering why my code didn't work.

Pavan
  • 33,316
  • 7
  • 50
  • 76
fscore
  • 2,567
  • 7
  • 40
  • 74
  • 1
    Possible duplicate of [How can I check if a value is a number?](http://stackoverflow.com/questions/2095493/how-can-i-check-if-a-value-is-a-number) – Brad Werth Oct 28 '15 at 05:53
  • @BradWerth I want to learn why my program is not working rather than copying others code – fscore Oct 28 '15 at 05:53
  • 1
    FWIW, params all come in as stings. They are coerced into integers when inserted into the database. – Brad Werth Oct 28 '15 at 05:54
  • 1
    So learn from the existing question, it's already been asked (and answered)... – Brad Werth Oct 28 '15 at 05:54
  • Or http://stackoverflow.com/questions/5661466/test-if-string-is-a-number-in-ruby-on-rails – Brad Werth Oct 28 '15 at 05:55
  • Or http://stackoverflow.com/questions/26061584/how-do-i-determine-if-a-string-is-numeric or http://stackoverflow.com/questions/4589968/ruby-rails-how-to-check-if-a-var-is-an-integer or http://stackoverflow.com/questions/8616360/how-to-check-if-a-variable-is-a-number-or-a-string or http://stackoverflow.com/questions/1235863/test-if-a-string-is-basically-an-integer-in-quotes-using-ruby or... – Brad Werth Oct 28 '15 at 05:56
  • @Pavan's answer is my solution. – fscore Oct 28 '15 at 05:57

3 Answers3

2

There is standard validation (length) & (numericality) for this:

#app/models/user.rb
class User < ActiveRecord::Base
   validates :phone_num, length: { is: 10 }, numericality: { only_integer: true }
end

This type of validation belongs in the model.


Notes

Your controller will look as follows:

#app/controllers/users_controller.rb
class UsersController < ApplicationController
   def create
      @user = User.new user_params
      @user.save #-> validations handled by model
   end
end

There's a principle called fat model, skinny controller - you should put "data" logic in your model.

The reason for this is to remove inefficient code from the controller.

It gives you the ability to delegate much of your logic to the Rails core helpers (validations for example), instead of calling your own mass of code in the front-end (like you're doing).

Each time you run a Rails app, the various classes (controller & model) are loaded into memory. Along with all of the Rails classes (ActiveRecord etc), your controllers & models have to be loaded, too.

Any extra code causes causes bloat, making your application buggy & unusable. The best developers know when to use their own code, and when to delegate to Rails. This example is a perfect demonstration of when to delegate.

Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • Thanks Rich. Thats a good example, What would I do as in my scenario there is no model. I dont want to store anything. Although storing could make perfect sense moving forward. But want to know another best practice if no model – fscore Oct 28 '15 at 15:34
  • And through model code I want different kinds of messages to go to view. Hows it possible with your example as validation happens only in model? – fscore Oct 28 '15 at 15:53
  • 1
    @fscore you can still use validations without persisting to the database, you can make a class that doesn't inherit from anything. – court3nay Oct 28 '15 at 20:33
  • 2
    wrapping up a bunch of functionality and logic in a new class is advanced stuff and is covered in something like http://railscasts.com/episodes/219-active-model?language=en&view=asciicast – court3nay Oct 28 '15 at 20:35
  • also, if you want people to be able to enter a phone number like `(710) 123-3456` then validating numericality won't work; you'll want to pre-process the number when writing - maybe `def number=(val); write_attribute :val, val.gsub! /\D/, ''; end;` -- not relevant if you aren't using the db, but that's how I'd do it! – court3nay Oct 28 '15 at 20:37
  • You *might* want to use virtual attributes too – Richard Peck Oct 29 '15 at 09:50
1

The output that I get is always The number is invalid no matter what I enter in text box.

The reason why your code always falls back to else part because the values that are coming from the params will always be strings. So the value of params[:phone_num] is a string. So your code is failing here if @phone.is_a? Integer. Instead you need change it to params[:phone_num].to_i

@phone = params[:phone_num].to_i
puts "phone_num: #{@phone}"
  if @phone.is_a? Integer 
    puts "phone_num is int"
    if @phone.to_s.length == 10
      puts "10 digit"
      perform(@phone)
      @output = "Valid Number, will receive a call"
    end
  else 
    puts "Wont be calling"
    @output = "The number is invalid"
  end

Note:

Yes. This is poor way to perform validations. I'm just answering the OP's question.

Pavan
  • 33,316
  • 7
  • 50
  • 76
  • FWIW, it seems kinda stupid to convert to an integer, check if it is an integer, convert to a string, and check the length. This is a poor way to perform validations in Rails, as well. – Brad Werth Oct 28 '15 at 05:59
  • @BradWerth What do you suggest the better way & Stack overflow only allows me to accept answers within a certain time so waiting for time to pass by – fscore Oct 28 '15 at 06:01
  • 1
    @fscore Rails validations. Like http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_numericality_of – Brad Werth Oct 28 '15 at 06:02
  • Or maybe http://stackoverflow.com/questions/10700800/how-to-validate-numericality-and-inclusion-while-still-allowing-attribute-to-be .... – Brad Werth Oct 28 '15 at 06:03
  • Or maybe http://stackoverflow.com/questions/23542960/rails-validating-phone-number-regex @fscore – Brad Werth Oct 28 '15 at 06:07
0

Take a look at this - A comprehensive regex for phone number validation - how to determine a string looks like a phone number. There's a very complex regex, because people have various forms for entering phone numbers!

I personally don't like super complex regexes, but it's pretty much what they were invented for. So this is when you want to figure out what sorts of forms are acceptable, write some tests, and make your code pass to your acceptance based on the massive link above!

edit: your code is wrong in a bunch of places; params are already a string, so try this! Remember your nested if/else/end, too.

@phone = params[:phone_num]
if @phone =~ /\A\d+\Z/ # replace with better regex
  # this just means "string is all numbers"
  puts "phone_num is int"
  if @phone.length == 10
    puts "10 digit"
    perform(@phone)
    @output = "Valid Number, will receive a call"
  else
    puts "Number length wrong, #{@phone.length}"
  end
else 
  puts "Wont be calling, not a number: #{@phone.inspect}"
  @output = "The number is invalid"
end
Community
  • 1
  • 1
court3nay
  • 2,215
  • 1
  • 10
  • 15