Regular expression trouble in rails 4 - ruby-on-rails

I've the following regex in my model
validates :profile_name, presence:true,
uniqueness:true,
format:
{
with: /^[a-zA-Z0-9_-]+$/,
message: "Must be formatted correctly"
}
My tests are not passing because of regex. I am validating the profile name.
Here is my error log:
The provided regular expression is using multiline anchors (^ or $),
which may present a security risk. Did you mean to use \A and \z, or
forgot to add the :multiline => true option? (ArgumentError)
I think am doing right, still it is not passing. Please Help me to fix this.

Use, \A and \z instead of ^ and $ for regex:
validates :profile_name, presence:true,
uniqueness:true,
format:
{
with: /\A[a-zA-Z0-9_-]+\z/,
message: "Must be formatted correctly"
}
Read more on Regular Expressions as to why.

Related

Discrepancy between Rubular regex and Rails regex

I want to validate U.S. phone numbers. On Rubular, the regex:
/^\(?([2-9][0-8][0-9])\)?[-.●]?([2-9][0-9]{2})[-.●]?([0-9]{4})$/
does not match the string:
'6463976583!'
as I expect. However, my Rails validator that uses the regex:
validates :phone, presence: true, format: {with: /^\(?([2-9][0-8][0-9])\)?[-.●]?([2-9][0-9]{2})[-.●]?([0-9]{4})$/}
seems to allow the same string.
Any thoughts as to where I'm going wrong?
pry(main)> '6463976583!'[/^\(?([2-9][0-8][0-9])\)?[-.]?([2-9][0-9]{2})[-.]?([0-9]{4})$/]?([0-9]{4})$/]
=> nil
pry(main)> '6463976583'[/^\(?([2-9][0-8][0-9])\)?[-.]?([2-9][0-9]{2})[-.]?([0-9]{4})$/]
=> "6463976583"
Perhaps try \A and \Z for your ActiveRecord validation: https://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_format_of
The documentation mentions it matches start and end of a string versus start and end of a line. I believe that Rails or Rubocop one, throws warnings if you don't use ^ and $ instead of \A or \Z
If you can't get the Rails validator to work, you can create a custom validator method and call your regex there

Rails: Validation with lots of format

I want to validate a Nickname but I have a lot of format like this:
validates :nickname, presence: true, unniqueness: true, format: { with: /\A[a-zA-Z0-9]+\Z/ }, format: { without: /\s/ }, format: { without: /[!-\/\#\^\~\`\(\)\[\]\>\<\=]/ }
warning: key :format is duplicated and overwritten on line 38
warning: key :format is duplicated and overwritten on line 38
Obviously down't work in this way, how can I solve it? Thank you
Your first regex covers everything:
format: { with: /\A[a-zA-Z0-9]+\Z/ }
but you probably want \z instead of \Z to avoid issues with trailing newlines. Anything that matches /\A[a-zA-Z0-9]+\z/ won't contain any space characters so the /\s/ test is already covered, similarly for the punctuation test.
Also, you've misspelled uniqueness as unniqueness so you'll want to fix that too.
That would leave you with just:
validates :nickname, presence: true, uniqueness: true, format: { with: /\A[a-zA-Z0-9]+\Z/ }
If you really did have multiple regexes to test then you could do it in a custom method:
validate :nickname_format
def nickname_format
return if(!nickname) # The `presence: true` takes care of complaining about this.
if(nickname ~! ...)
errors.add(:nickname, 'blah blah')
elsif(...)
...
end
end
so that you could check each regex individually.

Regexp in format: validation isn't stopping the right characters

I'm new to regex and I'm trying to only allows letters, numbers, quotes and the following characters: !.:?!_+=, -
I have the validation below in a guide modal. I can name a guide just '&' if I want and it accepts it, from my understanding this validation should stop me.
validates :name, presence: true, length: { maximum: 255 }, uniqueness: { case_sensitive: false },
format: { with: /[a-zA-Z 1-9 0!.'":?!_+=, -]/, message: "only allows letters, numbers, quotes and !.:?!_+=, -" }
Not sure what is going wrong, I tested out the regex in Rubular.com and it works in there.
Edit
After testing it, it turns out it stops '&' but lets '&11' pass. If an invalid key is with a valid key it passes. Maybe I'm using format: wrong or shouldn't be using format: for this?
I've simplified a bit your regex, added proper starting/ending line markers and added a + at the end to match if there is one or more char in the input. Here's what it looks like:
/\A[a-zA-Z0-9 !.'":?!_+=,-]+\z/
If you want to have a cleaner one:
/\A[\w !.'":?!_+=,-]+\z/
Since \w matches [a-zA-Z0-9]

Regular expressions with validations in RoR 4

There is the following code:
class Product < ActiveRecord::Base
validates :title, :description, :image_url, presence: true
validates :price, numericality: {greater_than_or_equal_to: 0.01}
validates :title, uniqueness: true
validates :image_url, allow_blank: true, format: {
with: %r{\.(gif|jpg|png)$}i,
message: 'URL must point to GIT/JPG/PNG pictures'
}
end
It works, but when I try to test it using "rake test" I'll catch this message:
rake aborted!
The provided regular expression is using multiline anchors (^ or $), which may present a security risk. Did you mean to use \A and \z, or forgot to add the :multiline => true option?
What does it mean? How can I fix it?
^ and $ are Start of Line and End of Line anchors. While \A and \z are Permanent Start of String and End of String anchors.
See the difference:
string = "abcde\nzzzz"
# => "abcde\nzzzz"
/^abcde$/ === string
# => true
/\Aabcde\z/ === string
# => false
So Rails is telling you, "Are you sure you want to use ^ and $? Don't you want to use \A and \z instead?"
There is more on the rails security concern that generates this warning here.
This warning raises because your validation rule is vulnerable for javascript injection.
In your case \.(gif|jpg|png)$ matches till the end of the line. So your rule will validate this value pic.png\nalert(1); as true:
"test.png\n<script>alert(1)</script>" === /\.(gif|jpg|png)$/i
# => true
"test.png\n<script>alert(1)</script>" === /\.(gif|jpg|png)\z/i
# => false
Read the acticles:
http://caiustheory.com/validating-data-with-regular-expressions-in-ruby
http://guides.rubyonrails.org/security.html#regular-expressions
The problem regexp is not in devise, but rather lives in config/initializers/devise.rb. Change:
# Regex to use to validate the email address
config.email_regexp = /^([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})$/i
to:
# Regex to use to validate the email address
config.email_regexp = /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\Z/i
The warning is telling you that strings like the following will pass validation, but it is probably not what you want:
test = "image.gif\nthis is not an image"
re = /\.(gif|jpg|png)$/i
re.match(test) #=> #<MatchData ".gif" 1:"gif">
Both ^ and $ matches the start/end of any line, not the start/end of the string. \A and \z matches the start and the end of the full string, respectively.
re = /\.(gif|jpg|png)\z/i
re.match(test) #=> nil
The second part of the warning (“or forgot to add the :multiline => true option”) is telling you that if you actually want the behaviour of ^ and $ you can simply silence the warning passing the :multiline option.
If Ruby wants to see \z instead of the $ symbol sign, for security, you need to give it to him, then the code would look like this :
validates :image_url, allow_blank: true, format: {with: %r{\.(gif|jpg|png)\z}i, message: 'URL must point to GIF, JPG, PNG.'}

Devise validation constantly failing on sign up

Making a simple Ruby on Rails app as practise that requires a user to sign up.
Everything works well until I implement regex validation on a 'profile_name' field
Here's my 'user' model:
validates :profile_name, presence: true,
uniqueness: true,
format: {
with: /^a-zA-Z0-9_-$/,
message: 'Must be formatted correctly.'
}
And yet the profile name 'jon' simply refuses to pass. Where could this error be coming from, other than my 'user' model?
You need to add brackets around the ranges so that the regex matches "any of the range" rather than "all of the range in order". Put a + on the end to allow it to match anything in the range more than once.
You also need to change your beginning and ending of lines to beginning and ending of strings!
validates :profile_name, presence: true,
uniqueness: true,
format: {
with: /\A[a-zA-Z0-9_-]+\z/,
message: 'Must be formatted correctly.'
}
Details:
\A # Beginning of a string (not a line!)
\z # End of a string
[...] # match anything within the brackets
+ # match the preceding element one or more times
Really useful resource for generating and checking regex: http://www.myezapp.com/apps/dev/regexp/show.ws
Try like this , It is working fine
validates :name, presence: true,
uniqueness: true,
format: {
with: /\A[a-zA-Z0-9_-$]+\z/,
message: 'Must be formatted correctly.'
}
I just tested your regular expression in Rubular with the 'jon'. There is no matching.
I am not optimized regular expression coder. But still the below regular expression works.
/^[a-zA-Z0-9_-]+$/
So try
validates :name, presence: true,
uniqueness: true,
format: {
with: /^[a-zA-Z0-9_-]+$/,
message: 'Must be formatted correctly.'
}

Resources