rails validation with regex - ruby-on-rails

I'm reading agile web development with rails 6.
In chapter 7, Task B: validation and unite testing
class Product < ApplicationRecord
validates :image_url, allow_blank: true, format: {
with: %r{\.(gif|jpg|png)\z}i,
}
what does the i mean in the end here?
It should mean that it's ending with .git or .jpg or .png

The i in your query tells the regex to match using a case insensitive match. There is nothing really unique to rails here so you may want to look into regexes in general to learn all the different terms you can use to modify your expression.
The expression %r{\.(gif|jpg|png)\z}i is equivalent to /\.(gif|jpg|png)\z/i
the \. means the period character
the | is an or as you stated
the \z is end of string with some caveats that you can read more about here: http://www.regular-expressions.info/anchors.html
and the i is incentive case matching
This means you would match 'test.jpg', 'test.JPg', 'test.JPG' or any permutation of those three characters in any case preceded by a period that occurs at the end of the string.
Here are the docs for regex formats in ruby specific:
https://ruby-doc.org/2.7.7/Regexp.html
And here is something where you can play with and learn regexes in general and try some expressions yourself:
https://regexr.com

short explain:
The "i" at the end of the regular expression is a modifier that makes the expression case-insensitive. This means that it will match both upper and lowercase letters in the image URL.

Related

RegEx contain a combination of letters, numbers, and a special character

I'm finding a regular expression which adheres below rules.
Acceptance criteria: Password must contain a combination of letters, numbers, and at least a special character.`
Here is my Regex:
validates :password, presence: true,
format: { with: ^(?=[a-zA-Z0-9]*$)([^A-Za-z0-9])}
I am not all that great at regex, so any and all help is greatly appreciated!
You can use the following RegEx pattern
/^(?=.*\d)(?=.*([a-z]|[A-Z]))([\x20-\x7E]){8,}$/
Let's look at what it is doing:
(?=.*\d) shows that the string should contain atleast one integer.
(?=.*([a-z]|[A-Z])) shows that the string should contain atleast one alphabet either from downcase or upcase.
([\x20-\x7E]) shows that string can have special characters of ascii values 20 to 7E.
{8,} shows that string should be minimum of 8 characters long. While you have not mentioned it should be at least 8 characters long but it is good to have.
If you're unsure about the ASCII values, you can google it or you could use the following instead:
/^(?=.*\d)(?=.*([a-z]|[A-Z]))(?=.*[##$%^&+=]){8,}$/
As suggested in the comments, a better way can be:
/\A(?=.*\d)(?=.*([a-z]))(?=.*[##$%^&+=]){8,}\z/i
Here:
\A represents beginning of string.
\z represents end of string.
/i represents case in-sensitive mode.
P.S: I have not tested it yet. May be I'll test and update later if required.

Regex password validation for non-sequence data

I'm attempting to validate that my passwords may not contain any sequential characters such as "123" or "abcd" etc. I'm new to regex and i'm trying to do it by having the following code in my User model:
validate :password_complexity
def password_complexity
if password.present? and not password.match(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d). /)
errors.add :password, "must include at least one lowercase letter, one uppercase letter, and one digit"
end
end
This is probably somewhat outside the bounds of regex. I would recommend looking into zxcvbn, which has also been ported into a ruby gem of the same name and even exists as a devise plugin. This will provide you with significantly more robust verification. You may also consider just inspecting the code for these projects, for inspiration, if you are determined to learn how one might implement something like this from scratch.
I agree that this isn't a job for a regex: maybe you could do it but it would be very complicated. Here's how i would do it.
def contains_sequential_characters?(string)
sequential = false
string.split("").each_with_index do |char,i|
if (string[i+1] == string[i]+1) && char =~ /[a-y0-8]/i
sequential = true
end
end
sequential
end
At the heart of this solution is that calling an array index on a string (eg "foo"[2]) will give you the ascii code of the character at that position. We only care about ascii codes that are next to each other between a-z and 0-9, which is why i'm also matching the first character against a-y (not z) and 0-8 (not 9).
You can use the below regex, which will accept a minimum of 13 digits and will not accept either sequential digits or sequential characters:
(?=.*?[0-9])(?!.*((12)|(23)|(34)|(45)|(56)|(67)|(78)|(90)|(01)))(?=.*?[a-zäöüß])(?!.*((ab)|(bc)|(cd)|(ef)|(fg)|(gh)|(hi)|(ij)|(jk)|(kl)|(lm)|(mn)|(no)|(op)|(pq)|(qr)|(rs)|(st)|(tu)|(uv)|(vw)|(wx)|(xy)|(yz)))(?=.*?[A-ZÄÖÜ])(?!.*((AB)|(BC)|(CD)|(EF)|(FG)|(GH)|(HI)|(IJ)|(JK)|(KL)|(LM)|(MN)|(NO)|(OP)|(PQ)|(QR)|(RS)|(ST)|(TU)|(UV)|(VW)|(WX)|(xy)|(yz))).{13,}

How to create a validation in Rails that checks if a string contains only emoji characters?

I need to check if the given string is using Unicode emojis only (😀). What would be the possible solution?
Matching a comprehensive set of emoji is difficult. You can either use a set of regular expressions to look for 'emoji-like' things, you can somewhere mark all emoji with special characters for start/end, or you can make a list of all possible emoji and match against it.You likely want to use some kind of regular expression.
If you want to use a regular expression, you can use the active record "match"
class Emoji < ActiveRecord::Base
validates :something, format: { with: /[:;][\)3\/|\(]/,
message: "only allows emojis" }
end
I might have escaped a few things there that ruby doesn't require escaping, but you get the idea. That regular expression will match one of : or ; and then one of ), (, /, or | which fit together to make a face. However lots of emoji can be more complicated. This next example compares the string with a list of valid emoji that you have in listOfEmoji. It uses the inclusion validator.
class Emoji < ActiveRecord::Base
validates :something, inclusion: { in: listOfEmoji,
message: "%{value} is not in the list of valid emoji" }
end
Finally, you might escape the start and end of anything that earlier in the code you identified as emoji. You'd have to use something that wouldn't be included in an actual emoji to do this, and then match it as a regular expression. for example, if you replace :) with emoji:)endemoji you could validate it with a regular expression like this:
class Emoji < ActiveRecord::Base
validates :something, format: { with: /emoji.+endemoji/,
message: "only allows emojis" }
end
.+ is the regular expression for (any character) 1 or more times. so that would match a special signal that your code would wrap what it knows is an emoji with that you could later use to identify an emoji. There are better words to use than emoji, endemoji though. My favorite is the ascii 7, the character for a typewriter bell!
All of these are possibilities and the best answer depends a lot on how you want to build your code and what you're trying to do.

Regular Expression for excluding numbers or special characters

I'm setting up a user form in Rails that requires a first name and last name. I decided to use the 3rd to last regular expression from the this Ruby doc to ensure that they don't enter any numbers or special characters. Unfortunately when I return to the form I get this error:
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?.
I'm just beginning to learn RegEx so if there's a better way to write this validation I'm all ears.
Code:
validates :first_name, :last_name, length: {minimum: 2}, format: {with: /^([^\d\W]|[-])*$/, message: 'First Name/Last Name cannot have any numbers or special characters'}
The documentation you linked to states:
Note: use \A and \Z to match the start and end of the string, ^ and $ match the start/end of a line.
Since you don't need multiline support for names (i.e. newlines in the name should be regarded invalid), you can safely change this to:
/\A([^\d\W]|[-])*\Z/
See also this answer which explains the security risk a bit more.
You will need to use \A for start of line and \z for end of line instead of ^ and $ due to security reasons. So your regexp should be
/\A([^\d\W]|[-])*\z/

regex basic url expression

Hi I'm creating a regular expression (ruby) to test the beginning and end of string. I have both parts but can't join them.
Beginning of string
\A(http:\/\/+)
End of string
(.pdf)\z
How to join?
Bonus if it could validate in-between and accept anything (to avoid http://.pdf)
By the way, rubular http://rubular.com is a neat place to validate expressions
Use .+ to match any character except \n one or more times.
\A(http:\/\/+).+(\.pdf)\z
Should match http://www.stackoverflow.com/bestbook.pdf but not http://.pdf

Resources