validation of special characters - ruby-on-rails

I want to validate login name with special characters !##S%^*()+_-?/<>:"';. space using regular expression in ruby on rails. These special characters should not be acceptable. What is the code for that?

validates_format_of :username, :with => /^[A-Za-z0-9.&]*\z/
will work

You've received regexps in this thread that answer your specific question. You're doing a black-list approach (blocking the characters you don't want) but is this really what's best? I see you didn't cover & or ~, and there are many other special characters that are likely still missing.
If you're trying to block special characters, I'd suggest a white-list approach, as per pablorc's regexp suggestion. It's far more broad and lists only what you want to allow....non-special characters: only words, underscore and numbers.
I've gone ahead and created a method for you that does a white-list approach using this regexp.
def valid_login?(str)
return true if (/^\w*$/.match(str))
return false
end
This method, valid_login?, returns true only if the string contains letters, numbers, or underscore, so all of your special characters (plus any other you've left out that do not meet these requirements), are safely detected.
Usage:
> valid_login?("testy")
true
> valid_login?("a b")
false
> valid_login?("a'")
false

Well I don't know rails but this is what the regex would look like in every other language I know:
^[^!##\$%\^\*\(\)\+_\-\?/\<\>:"';\. ]$

The regex /^\w*$/ allows to use only letters, numbers, and a underscore.
Also, you have a cheatsheet and a live ruby regexp editor on http://rubular.com

First off, I would recommend using a gem for login, like authlogic.
The gem can be configured to validate the email address. You also get the benefit of not having to worry about authenticating your users, etc.
Very easy gem to work with too.

validates_format_of :username, :with => /^[^!##S%\^\*()\+_-\?\/<>:\"';]+$/

Related

Rails friendly_id with arabic slug

My question is closely related to this one Rails friendly id with non-Latin characters. Following the suggested answer there, I implemented a little bit different solution (I know, it's primitive, but I just want to make sure it works before adding complex behavior).
In my user model I have:
extend FriendlyId
friendly_id :slug_candidates, :use => [:slugged]
def slug_candidates
[
[:first_name, :last_name],
[:first_name, :last_name, :uid]
]
end
def should_generate_new_friendly_id?
first_name_changed? || last_name_changed? || uid_changed? || super
end
def normalize_friendly_id(value)
ERB::Util.url_encode(value.to_s.gsub("\s","-"))
end
now when I submit "مرحبا" as :first_name through the browser, slug value is set to "%D9%85%D8%B1%D8%AD%D8%A8%D8%A7-" in the database, which is what I expect (apart from the trailing "-").
However the url shown in the browser looks like this: http://localhost:3000/en/users/%25D9%2585%25D8%25B1%25D8%25AD%25D8%25A8%25D8%25A7- , which is not what I want. Does anyone know where these extra %25s are coming from and why?
Meanwhile, I came a bit further, so I put my solution here maybe it could be helpful for someone else.
The 25s in the url seem to be the result of url_encoding the '%' in my slug. I don't know where this happens, but I modified my normalize_friendly_id function, so that it doesn't affect me anymore. Here it is:
def normalize_friendly_id(value)
sep = '-'
#strip out tashkeel etc...
parameterized_string = value.to_s.gsub(/[\u0610-\u061A\u064B-\u065F\u06D6-\u06DC\u06DF-\u06E8\u06EA-\u06ED]/,''.freeze)
# Turn unwanted chars into the separator
parameterized_string.gsub!(/[^0-9A-Za-zÀ-ÖØ-öø-ÿ\u0620-\u064A\u0660-\u0669\u0671-\u06D3\u06F0-\u06F9\u0751-\u077F]+/,sep)
unless sep.nil? || sep.empty?
re_sep = Regexp.escape(sep)
# No more than one of the separator in a row.
parameterized_string.gsub!(/#{re_sep}{2,}/, sep)
# Remove leading/trailing separator.
parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/, ''.freeze)
end
parameterized_string.downcase
end
Some comments on that:
I took only Latin and Arabic alphabets into account
I decided that if I allowed arabic characters in the url, then there is no sense to keep the friendly_id behavior of converting e.g. "ü" to "ue", "ö" to "oe", etc. So I leave such characters in the url.
I tried also to keep characters which might not be used in Arabic, but in other languages which use the Arabic alphabet such as Farsi or Urdu. I speak Arabic only, so I did a guess of which characters might be regarded as regular in other languages. For example is "ڿ" a regular character in any language? I have no idea, but I guess it could well be.
again, since I speak arabic, I stripped the "Tashkil" out of the text. I would say, that texts without tashkil are in general easier to read than the ones with. However, I don't know if I should take care of some similar stuff in other languages. Any hints are much appreciated.
Last: adding another alphabet would be as easy as adding the appropriate sequences to the regex. One only needs to know which characters should be white-listed.
I appreciate any comments or improvement suggestions.

Convert Sentence to Camelcase in Ruby [duplicate]

This question already has answers here:
Converting string from snake_case to CamelCase in Ruby
(10 answers)
Closed 9 years ago.
This seems like it would be ridiculously easy, but I can't find a method anywhere, to convert a sentence string/hyphenated string to camelcase.
Ex:
'this is a sentence' => 'thisIsASentence'
'my-name' => 'myName'
Seems overkill to use regex. What's the best way?
> s = 'this is a sentence'
=> "this is a sentence"
> s.gsub(/\s(.)/) {|e| $1.upcase}
=> "thisIsASentence"
You'd need to tweak that regexp to match on dashes in additions to spaces, but that's easy.
Pretty sure there's a regexp way to do it as well without needing to use the block form, but I didn't look it up.
Using Rails' ActiveSupport, the following works for both cases:
"this is a sentence".underscore.parameterize("_").camelize(:lower)
# => "thisIsASentence"
"my-name".underscore.parameterize("_").camelize(:lower)
# => "myName"
the underscore converts any dashes, and the parameterize converts the spaces.
'this is a sentence'.split.map.with_index { |x,i| i == 0 ? x : x.capitalize }.join # => "thisIsASentence"
If you use ActiveSupport (for instance because of Rails or any other dependency), then have a look at the ActiveSupport::Inflector module. These methods are immediately available to you for any String.
'egg_and_hams'.classify # => "EggAndHam"
'posts'.classify # => "Post"
Keep in mind that the standard separator in Ruby is the _, not the -. It means you probably need to replace it.
'my-name'.tr('-', '_').classify
=> "MyName"
'my-name'.tr('-', '_').camelize(:lower)
=> "myName"
Using ActiveSupport is just delegating the job. Keep in mind that, behind the scenes, these conversions in Ruby are very likely to be performed using regular expressions.
In fact, in Ruby regexp are cheap and very common.
You're looking for String#camelize
"test_string".camelize(:lower) # => "testString"
If you're using other separators than underscore, use the gsub method to substitute other characters to underscores before camelizing.

Devise not respecting config.email_regexp

I wanted to change the regex that defines valid emails in my application. I am trying to do this in config/initializers/devise.rb. To check whether the regex was working I tried to start with something easy like
config.email_regexp = /\d+/
when that didn't work, I thought maybe my knowledge of ruby's regex sytax was off and tried what I thought was a super simple regex
config.email_regexp = /a/
While changing the following DOES have an impact on the passwords allowed, the previous two lines seem to have no effect.
config.password_length = 2..128
What else should I do in order to modify the regex validating emails? (after I made each of these modifications I restarted the server to make sure the changes were picked up.)
You realize what those regex's match right?
/\d+/ matches one or more digits, and /a/ matches a single 'a'. This would make just about every email address invalid, no?
Check out this site to test your regexes and see if that helps:
http://rubular.com/
I had a similar issue, this time when setting the email_regexp to a constant defined elsewhere. I reported it at https://github.com/plataformatec/devise/issues/2233 with some failing/passing test case comparisons to try and nail it down.

What is the best way to replace smart quotes, smart apostrophe and ellipsis in Rails 3?

My application allows the user to enter text. When they copy and paste from MS Word, it pastes smart quotes, smart apostrophes and ellipsis. These characters get saved into the database and cause problems. What is the best way to replace these non-UTF-8 characters with normal quotes("), apostrophe(') and periods(...)?
Also, how do you test this functionality? I added a test with these special characters and # encoding: ISO-8859-1 at the top of the file. The special characters caused the tests stop running: /home/george/.rvm/gems/ruby-1.9.2-p180/gems/redgreen-1.2.2/lib/redgreen.rb:62:in 'sub': invalid byte sequence in UTF-8 (ArgumentError)...Apparently redgreen gem is incompatible with these characters...?
Thanks.
you can add a before_save method that will convert your text to UTF-8 corresponding characters. if you have just 1 field that might contain non-UTF8 chars then its simple, if you have many fields then it would be better if you dynamically iterate over changed text/string fields and fix UTF-8 problem. Either way you need to use String#encode. Here is an example
before_save :fix_utf8_encoding
def fix_utf8_encoding
columns = self.class.columns.select{|col| [:text,:string].include?(col.type)}.map{|col| col.name.to_sym}
columns.each do |col|
self[col] = self.self[col].encode('UTF-8', :invalid => :replace, :undef => :replace) if self[col].kind_of?(String) #Double checking just in case.
end
end
private :fix_utf8_encoding
And for bonus points you can also check if the field was changed using rails handy changed? helpers before fixing it.

Regex retrieved from a MYSQL database to validate email addresses using Ruby on Rails

I am using Ruby on Rails 3 and a MYSQL database. I would like to retrieve a regex from the database and then use that value to validate email addresses.
I aim to not put the regex value in line in my RoR application code, but outside so that the value can be recalled for other usages and from other places.
In order to populate the database, I put in my 'RAILS_ROOT/db/seed.rb' the following:
Parameter.find_or_create(
:param_name => 'email_regex',
:param_value => "[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
)
Notice: in the 'seed.rb' file I edited a little bit the original regex from www.regular-expressions.info adding two \ just before $. Here it is the difference:
#original from www.regular-expressions.info
[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?
#edited by me
[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?
After run rake db:seed in the Terminal, in MYSQL database I have this value (without \ near $):
[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?
Then in my RoR application I use the regex this way:
def validate(string)
email_regex = Regexp.new(Parameter.find_by_param_name('email_regex').param_value)
if email_regex.match(string)
return true
else
return false
end
end
The problem using the above regex is that I can successfully validate also email addresses with double '#' or without the final part like these:
name#surname#gmail.com # Note the double '#'
test#gmail
Of course I would like to refuse those email addresses. So, how can I adjust that? Or, how can I get what I want?
I tried also to seed these regex:
#case 1
\A[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\Z
#case 2
\\A[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\Z
#case 3
^[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$
that in the MYSQL database become respectively:
#case 1
A[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?Z
#case 2
\A[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\Z
#case 3
^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$
but also them don't work as expected.
UPDATE
Debugging I have
--- !ruby/regexp /[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/
that means that just before of all / characters Ruby added a \ character. Can be that my problem? In the 'seed.rb' file I tryed to escape all / adding \ statements but the debug output is always the same.
There are so many things wrong on so many levels here…
Storing application configuration in your database isn't recommended; slower performance, potential catch 22s (like how do you configure your database, from your database), etc. Try something like SettingsLogic if you don't want to have to build your own singleton configuration or use an initializer.
Rails has built in validation functionality as a mixin that's automatically part of any models inheriting from ActiveRecord::Base. You should use it, rather than define your own validation routines, especially for basic cases like this.
You can actually have an email address with multiple # signs, provided the first is escaped with a backslash or the local portion of the address is quoted.
Why are you escaping $ characters in a character class where they have no special meaning?
Regular expressions are okay for a very basic validation of an email address to make sure you didn't get complete garbage data to pass off to your mail server, but they aren't the best way to verify an email address.
I suggest you have a good look at the validations guide at RubyOnRails.org.
You shouldn't reinvent this wheel. See http://lindsaar.net/2010/1/31/validates_rails_3_awesome_is_true for a standard way to validate email addresses in Rails 3.
If you do choose to reinvent the wheel, don't use a regular expression. The gory details of why this is a bad idea are explained in http://oreilly.com/catalog/9780596528126, along with a very, very complicated regular expression that almost does it.

Resources