Custom Validation for format - ruby-on-rails

I have a class Links. The class has these attributes
Twitter
Facebook
Pinterest
Quora
I want to write a validation that makes sure when a user inserts a link into a textbox it starts with http or https.
The validation works, but I have a an issue when the user does not insert a link at all. It still tries to run the validation on the empty attribute and raises the error. The below code is my attempt at checking for a empty attribute.
Here's my validation:
class Links < ActiveRecord::Base
attr_accessible :facebook, :twitter, :quora, :pinterest
validate :formatted_link
def formatted_link
links = %w(facebook twitter pinterest quora)
if links.any? {|link| self[link].nil?}
#Don't want it to do any validation if column is nil.
#Would like to drop column if user doesn't add a link.
else
validates_format_of links, :with => URI::regexp(%w(http https))
errors.add(:base, "Your link must start with http or https.")
end
end
Reason:
If a user just submits "www.twitter.com/username" the url get's appended to my sites url "mydomain.com/page/www.twitter.com/username. Not sure why this is happening. If there is something else I could do to prevent this or something I am missing please let me know.
Thanks.

I think you need to convert links to a symbol before passing it to validates_format_of, but since it seems to be working for you, I may be wrong or your sample code above may be missing that detail.
Either way, you can skip validation on blanks with:
validates_format_of :foo, with: some_format, allow_blank: true

I think you're trying to do conditional validation in a roundabout way. Since you really just want to allow blanks, you can do it this way:
class Link < ActiveRecord::Base
Networks = [:facebook, :twitter, :quora, :pinterest]
attr_accessible *Networks
validates_format_of *Networks, :with => URI::regexp(%w(http https)), :allow_blank => true
end

Related

add custom validation method in Ruby on Rails

I need create a method the custom validation called findUpperCaseLetter or similar
I have a attribute called password that belongs to the model called User
My method is somewhat similar to the following. The password attribute must have at least a uppercase letter
def findUpperCaseLetter(username)
username.each_char do |character|
return true if character=~/[[:upper:]]/
end
return false
end
I want add this validation to the User model
class User < ActiveRecord::Base
attr_accessible :user_name,:email, :password
validates_presence_of :user_name,:email, :password
validates_uniqueness_of :user_name,:email
????
end
I have already the following regular expreession
validates_format_of :password, :with => /^[a-z0-9_-]{6,30}$/i,
message: "The password format is invalid"
How I modify it for add the following
The password must have at least one uppercase letter
You don't need custom validation to do this, you can use regex to validate the format of password. Add this to your model
validates :password, format: { with: /^(?=.*[A-Z]).+$/, allow_blank: true }
In Rails, you can do this by using format validator, I have added allow_blank: true to make sure when the field is empty it only throws Can't be blank error message and not format validator error message.
The work of this regular expression is to allow the password to be saved in the database only if it contains at least one capital letter. I have created a permalink on rubular, click here http://rubular.com/r/mOpUwmELjD
Hope this helps!

Devise: Unable to limit model validation to specific def's

So I'm working on the registration aspect of the site currently. I have a main sign up which is just full name, email and password. (aka new.html.erb)
After you fill in that information I direct you to a new site (setup.html.erb) and ask for more info like city, country etc.
On that you also have the edit profile account.
I am trying to make my app more secure and adding restrictions and presence etc in the model. However how can I limit them.
Currently if I do
validates :email, presence: true,
and I go to a form that doesn't even contain the email for nor permits it I get an error up that I need to add an email.
Also how do I fix this: I make presence true, I input require in html5. But still if I go to my source code and just remove the form and push submit it saves and I can bypass adding info.
Currently if I do validates :email, presence: true,
and I go to a form that doesn't even contain the email for nor permits it I get an error up that I need to add an email.
Fix:
what you need is a conditional validation. If we look at rail guides it says
Sometimes it will make sense to validate an object only when a given predicate is satisfied. You can do that by using the :if and :unless options, which can take a symbol, a string, a Proc or an Array.
So in your model you could do something like:
class Order < ActiveRecord::Base
validates :email, presence: true, if: :need_to_validate?
def need_to_validate?
#your condition to check whether you want email validation or not
end
end
Update:
You can use params[:action] and params[:controller] smartly to check in which action and controller(hence which view) you currently are in so your method would be:
def need_to_validate?
params[:action] == your_view_action && params[:controller] == your_controller_name #your condition to check whether you want email validation or not
end

Rails validation problem

I've got a User model with three fields, :email, :display_name and :handle. Handle is created behind the scenes from the :display_name.
I'm using the following validations:
validates :display_name, :presence => :true, :uniqueness => { :message => "Sorry, another user has already chosen that name."}, :on => :update
validates :email, :presence => :true, :uniqueness => { :message => "An account with that email already exists." }
I use the handle as the to_param in the model. If the user fails the validation by submitting a :display_name that already exists, then tries to change it and resubmit the form, Rails seems to use the new handle as the validation for the email -- in other words, it assumes that the email doesn't belong to the current user and validation on the email then fails. At this point, Rails assumes that the changed display name/handle is the one to use for the look up and the update action can't complete at all, because it can't find the user based on the new handle.
Here's the update method:
def update
#user = User.find_by_handle(params[:id])
#handle = params[:user][:display_name]
#user.handle = #handle.parameterize
...
end
This problem doesn't happen when the validation first fails on a duplicate email, so I'm assuming it's something about the way I've written the update method -- maybe I should try setting the handle in the model?
maybe I should try setting the handle in the model?
^ This.
The controller isn't the place to do something like this. If it's model logic that's happening behind the scenes, beyond the user's control, why put it in controller code?
Do it instead in a before_save filter, which is guaranteed to run only after the chosen display name is determined to be available and the record is deemed valid. In this way the handle won't be changed on the cached record until it is actually committed to the db, eliminating the problem of the incorrectly generated URL.
before_save :generate_handle
...
def generate_handle
self.handle = display_name.parameterize
end

validating presence of email address (can't be blank)- Ruby on Rails

Pretty new at all this. I have a simple form for users to enter a couple pieces of information and then input their email address and push the submit button. I want to make it mandatory that they have to fill out their email address in order to push the submit button. If they don't fill out their email address they should get an error message on the email box that says the email can't be blank. I know this is super simple but I need exact help on where to put what code. I've been researching this all night and know that part of the code should go in the application_controller and other should go in the html file where the actual text_field:email is.
I'd be grateful if someone could clearly tell me what the necessary steps are for doing this. Thanks!
It should go in your model. Add this:
class Model < ActiveRecord::Base
validates_presence_of :email
end
Check this link for more info: http://guides.rails.info/activerecord_validations_callbacks.html#validates-presence-of
In Rails 2, which I would assume you are using, validations go in the model. Which is located in $Rails_app_directory/app/model/$Classname.rb
In order to add ActiveRecord validations you can use the line
validates_presence_of :email_address
You should also consider using Rails to generate a confirmation field and filtering out ill-formatted email addresses. You could accomplish the former with:
validates_confirmation_of :email_address
with this, all you need to add to your form is a text_field for :email_address_confirmation
and the latter with a regular expression such as:
validates_format_of :email_address, :with => /\A[\w\.%\+\-]+#(?:[A-Z0-9\-]+\.)+(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|jobs|museum)\z/i
From snipplr, place in your model
validates_format_of :email,
:with => /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i,
:message => 'email must be valid'

Validates uniqueness of :link

I have a url field named link in my model with the following validation
validates_uniqueness_of :link, :case_sensitive => false
When I put "http://stackoverflow.com", it goes well.
Now when I put "https://stackoverflow.com/" (with the trailing slach), this is also accepted as unique.
But I want it to be invalid though there is "/" at the last?
I'd suggest that you normalize your URLs (add/strip trailing slash, etc. see http://en.wikipedia.org/wiki/URL_normalization) before storing them in the DB and even before validation.
validates_uniqueness_of :link, :case_sensitive => false
before_validation :normalize_urls
def normalize_urls
self.link.strip!
self.link.gsub!(/\/$/,'')
end
This isn't quite what you were asking for but if you don't store normalized URLs, you'll have to query your DB for all possible variations during validation and that could quickly get expensive.
You could always do a custom validator (by using the validate method, for example).
It might look something like this:
class MyModel < ActiveRecord::Base
validate :link_is_unique
def link_is_unique
#Clean up the current link (removing trailing slashes, etc)
link_to_validate = self.link.strip.gsub(/\/$/,'')
# Get the current count of objects having this link
count = MyModel.count(:conditions => ['link = ?', link_to_validate])
# Add an error to the model if the count is not zero
errors.add_to_base("Link must be unique") unless count == 0
end
end
You could then add other logic to clean up the link (i.e. check for http://, www, etc.)
You can customize validations. See this railscast.

Resources