validates :username, exclusion: { in: %w(about account root etc..)
I am using the above to disallow users from using reserved usernames but they are still able to use them between underscores (I do allow underscores in usernames)
Is there anyway I can make rails validate the reserved username even if it is before or after an underscore?
Thanks
You could create a method to do your validations for you and use plain old ruby in that. As you can see in the docs here
This would look something like this for you:
validate :my_validation_method
def my_validation_method
errors.add(:username, :exclusion) if some_condition
end
What this does is say that the model needs to be validated with the my_validation_method as well as all your normal other validations. You then manually add the field that is in error (in your case :username) to the errors of the model, thus it fails validation.
Also note the validate rather than validates.
Your other question is basically how to check whether an entered value includes some words. You could do this like so:
def my_validation_method
forbid = %w(luke darth artoo fry bender)
errors.add(:username, :exclusion) if forbid.find { |w| username.include?(w) }
end
Here I added a condition to the adding of the error where we loop through each word in the forbidden list and check if username includes this word. Note that "blablaluke" would fail too! So it is not completely what you'd want. But you can play around with this yourself of course.
The level of normalization you do (e.g. stripping away other characters) could give you more control, like preventing ad_min, etc.
Update:
You can strip away characters like so:
username.tr('-_+$^&', '')
You can add whatever you want to strip away to that first string in tr.
according to the rails docs this way you can only check if a value is in a set of given values.
This helper validates that the attributes' values are not included in a given set.
i would just write a custom validation method - you can do whatever you want in there.
I'd probably use a Regex. Like this one:
validates_format_of :username, :with => /\A(([ _]*)(?!(about|admin|root|etc)[ _])[^ _]+)+([ _]+|\z)\z/
Related
I have a form which include number fields
<%= f.number_field :contribution_to_sales, class: 'form-control',:pattern=>["\d+"] %>
It allows 2.0 but I want it should not allow 2.0 .
How to do that?
You are missing anchors on your regular expression which causes the "2" in "2.0" to be matched (on some browsers). The regex to use is:
<%= ... pattern: "^\d+$" %>
You should probably be doing the validation on the model as well, as the HTML5 pattern attribute may not be obeyed by all browsers. Simply add:
class YourModel < ActiveRecord::Base
validates :contribution_to_sales, numericality: { only_integer: true }
...
end
Add the following to the Model this form relies on:
validate :format_numbers
def format_numbers
if self.number_field.include?(',') || self.number_field.include?('.')
errors.add(base: "Do not add commas or periods please")
end
end
That is one way to validate however I prefer the much more user friendly way which removes certain things a user may add that I know I don't want and then continue to process the form instead of reporting back with an error. This would be done by removing commas and since you don't want periods either I would imagine we can strip anything to the right of a period out as well. To do it this way you would do the following in your Model instead of the above:
validate :format_numbers
def format_numbers
self.number_field = self.number_field.gsub(/\.\d+/, '') #This will remove any period and all numbers to the right of that period.
self.number_field = self.number_field.gsub(',','') #This will remove all commas throughout.
end
This provides a smoother user experience since they can now type 2,000.00 in the form field and it will be saved as 2000
I have a search form with many fields. Each field is a parameter for searching a very large database. These parameters are passed to a search object. Some combinations of parameters are valid, others are not (they put too heavy a load on the system). What is the best way to write validations for combinations of parameters? For example: You should be able to search by name and one other field, but not name alone. In some cases if you enter a value in one field, you cannot enter a value in others
Currently I have something like this in my search class.
SEARCHABLE_ATTRIBUTES = [:name, :city, :state, :phone, :invoice_number, :payment_amount, :payment_date, :current_balance]
validate: valid_combinations
def valid_combinations
unless name.present? && (SEARCHABLE_ATTRIBUTES - [:name, :invoice_number]).select{|sa| send(sa).present?}.any?
errors.add(:name, "can't be given alone.")
end
if name.present? && invoice_number.present?
errors.add(:invoice_number, "can't be searched with name")
end
end
My valid search param restrictions get more complex than this, but this is just an example. Is there a better way to do this? I'd like to avoid one big valid_combinations method.
You can pass a condition to the validation and it will run only if that condition returns true.
So you could create separated validation methods and use them like this:
validate :at_least_another_column, if: Proc.new{|record| record.name }
Or, if you create a condition method named name_present you could code it like this:
validate :at_least_another_column, if: :name_present
To substitute your second condition you could use:absence and :message options. Looking like this:
validates :invoice_number, absence: true, if: :name_present , message: "can't be searched with name"
As you can see the code becomes much cleaner and understandable when using separated validations. But depending on how complex your conditions may be, it could be easier to create a giant validator method
There's a lot more about validations here
I have a form that allow me to edit an entry. I have a secondary set of attributes that must all be here if one of them have a value. I use conditional validates to do so :
validates_presence_of :raison_sociale,:nom_contact,
:prenom_contact,:telephone,
if: (:nom_contact?||:raison_sociale?||
:prenom_contact? || :telephone?)
But the strange thing is, those 4 fields are not evaluated the same way! If i remove nom_contact, it save. But if i remove it and telephone, it fails.
What i observed is that it was ignoring a blank field if it was the first one in the if condition! As soon as i put prenom contact as first condition i cannot save without nom_contact, but now it's prenon_contact that is ignored!
Why does my conditions behave strangly and what can i do?
What ca i do to avoid that?
You could put the if validation in a proc.
"Symbol-only" conditional validation expects a symbol for the name of a method that will be called.
You're including conditionals, which AFAIK won't work without being in a proc.
You can do some combinations by using an array, as per the docs:
class Computer < ActiveRecord::Base
validates :mouse, presence: true,
if: ["market.retail?", :desktop?]
unless: Proc.new { |c| c.trackpad.present? }
end
But those are and, not or.
I'd probably wrap it up in a method anyway; IMO it's a bit long for an in-line block, but that's more a matter of opinion.
Is it possible to pass :symbols to the valid? method so that I can define if the object is valid up to a certain point?
Eg. if I have an object Person and want to call Person.valid?(:basic_info) and it will return true only if a certain subset of fields (say name & gender) are present?
I saw something that I thought might be of use but cannot get it working, it's conditional validations http://guides.rubyonrails.org/active_record_validations_callbacks.html#conditional-validation , in particular grouping conditional validations, but I couldn't get it working...
Can anyone help me out here please...
I don't think there already present like this however you can write a method on your own like following
def is_valid_field?(field)
self.valid?
self.errors[field].blank?
end
and then just person.is_valid_field?(:basic_info)
To validate basic_info you'll have to define a custom validator:
class Person < ActiveRecord::Base
validate :basic_info_present
def basic_info_present
if name.blank? || gender.blank?
errors.add(:basic_info, "can't be in blank")
end
end
end
If you then want to see if there are errors on the specific field, you can use #Salil's approach.
Note however that since there is no actual attribute called basic_info in your model, the validation errors here will not come up in forms, etc. (although they will be in the errors hash). That may or may not be what you want.
I got this to work using conditional validations, so now i can use .valid?(:basic) say for when i only want to check that the person has a name with the call...
validates_presence_of :name, :when => [:basic]
Documentation here: http://apidock.com/rails/ActiveRecord/Validations/valid%3F
This way I can have the object return true when calling .valid? even when it doesn't have a name, good times...
I am just starting out in Rails, and trying to develop a simple application. I need to validate three values submitted to the application - each must meet the same validation criteria.
The validation is pretty simple:
Value is valid if unqiue, null or equal to "p" or "d".
The following gets me halfway there:
validates_uniqueness_of :value1, :value2, :value3, :allow_nil => true
I think I can use :unless to check whether the value is either "p" or "d", however I can't figure out how.
I guess I am trying to combine validates_uniqueness_of with validates_inclusion_of.
Any suggestions?
There are a few ways to do that. I'd probably go with something like this:
validates_uniqueness_of :wallport_id, :allow_nil => true, :unless Proc.new { |u| u.wallport_id == 'p' or u.wallport_id == 'd' }
You could also break the extra logic out in to its own method, like this:
validates_uniqueness_of :wallport_id, :unless :has_nonunique_wallport_id
NONUNIQUE_WALLPORT_IDS = ['p', 'd', nil]
def has_nonunique_wallport_id
NONUNIQUE_WALLPORT_IDS.include? wallport_id
end
or push the whole validation in to its own method, like this:
validate :has_valid_wallport_id
def has_valid_wallport_id
# check wallport id and return either true or false
end
The best approach probably depends on which you find most readable, which functionality you might want to expose to other parts of your code (eg, does anybody else need to know about valid non-unique wallport ids?), and which things you expect might change (eg, will you add more valid non-unique ids later?). There are also a few different ways of doing the actual check, which again just comes down to what you find most readable and how you think the system might evolve.