I would like to add a :presence and :uniqueness validation to a model in Rails. I'm using MongoDB and the Mongoid gem.
I have a model that is already in use and have existing records in the DB. I'd like to add a new :field and then add validations for :presence and :uniqueness for the field.
I know that by default, any existing records will simply add the :field and the result will be null unless I specify a :default.
My question is, since I want this new :field to be unique, will this cause an error for the existing records in the DB that will be null? Will I lose these records or does Rails just apply the validations to the new records?
Rails/AciveRecord will not ignore or delete your old records...
Validations work as follows: they are only used/checked when you try to write stuff to the database, e.g. when you create a new record or when you update a record. So in your case you will get validation errors when you try to update an old record without adding the new required fields.
I suggest that you try to clean up your database when adding the new fields (meaning adding sensible defaults to old records for the new required fields).
Related
I'm new to Ruby on Rails and I'm currently working on models. I have added a new validation to pre created attribute.
This is the validation that I have added.
validates_presence_of :services, :message => 'This field is non-editable'
Do I have to migrate the changes after adding validation? If yes then how?
Any kind of help would be greatly appreciated.
Records already in your database won't be affected. But it you edit a previous record, you won't be able to store it without passing the validation.
You've 3 options:
On edit/update, force new field value (default in your case)
Create a migration to set default value on the column.
Create a migration to update each row with a correct value (not really a good option in my mind)
I have a table Student(class_id(integer),marks(integer),rank(integer))
In my Seeds.rb file i have written something like this to make entry to table
Student.create(class_id:2 ,marks:"abcdef", rank: 2)
when i add these data to table by rake db:seed command ,i was expecting i would not be allowed to add this ,because for marks field of student, string is being inserted instead of integer.But rails added this record without any problem.
so how do i ensure this kind of entry doesnot happen and my table ensures type check.Me a newbie to rails and postgres
So, a validation like below will work. Add it to the Student model.
validates :marks, numericality: { only_integer: true }
Whenever you will try to create a Student record, this validation will be called by Rails. If it passes then the recored will be created, otherwise not. There are methods to check if a record is valid or not in rails.
Read the guide to know how validation works in rails.
I have a problem with mongoid. I have validation on some field, called flickr_id. The problem is, that Mongo doesn't support transactions and sometimes, somehow, despite the fact that there is validates :flickr_id, :uniqueness => true, there are duplicates in a database. How can I remove them from Rails application? Because anytime I want to do something with these objects which aren't unique, I get an error that it's not valid. How can I ignore validation in such situation?
I'm using validates_uniqueness_of an works as expected. Assuming that what you want is to clean your DB, you can comment that line and remove duplicated documents through console.
If not the case, you can add on to your validation, so the validation is only run when creating/updating but not when destroying:
:on Only run when specified, supports :create and :update.
More info here.
Try object.delete instead of object.destroy.
I'm working on a project in Rails 3 where I need to create an empty record, save it to the database without validation (because it's empty), and then allow the users to edit this record in order to complete it, and validate from then on out.
Now I've run into a pretty basic problem: I can't seem to save a model without validating it under any circumstances.
I've tried the following in the console:
model = Model.new
model.save(false) # Returns RuntimeError: Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
model.save( :validate => false ) # Returns same error as above
model = Model.create
model.save(false) # Same runtime error
model.save( :validate => false ) # Same runtime error
I then tried changing all the validations in the model to :on => :update. Same error messages on any attempt to save.
So what am I missing here? How can I create an empty record and then let validation occur as the user edits it?
Thanks!
It is a bad practice to have invalid models saved by normal use cases. Use conditional validations instead:
validates_presence_of :title, :unless => :in_first_stage?
or if you have many:
with_options :unless => :in_first_stage? do
validates_presence_of :title
validates_presence_of :author
end
This way nothing stands in way to have nightly integrity tests, which checks all records for validity.
A valid use case for saving without validations would be for testing edge cases, e.g. to test that a database constraint is enforced.
*sigh...*
Found the problem... one of my after_validate method calls was adding information and resaving the model, hence the errors I was getting weren't from the console input, they were coming from the after_validate method which was saving again.
Thanks all.
For emergencies only
Assuming that you have considered this very carefully and are certain that this is a good idea, you can save without validation using:
my_model.save validate: false
There are almost no valid use cases for this, and it should be considered an emergency one off procedure. Your use case does not qualify.
Problems with invalid records
Having invalid records in the database leads to all manner of problems down the line. For example, you send an email to all users and update a 'last_contacted_at' field on your user model. Your invalid users will not be updated and will descend into an email spiral of death.
Conditional validation
As other posters have pointed out, conditional validation will solve most issues for which you might otherwise have used validate: false.
Instead of placing an invalid model in the database, store the partially completed model (created with Model.new) in a session. Only save it to the database when it is completely valid.
I am looking on trying to use acts_as_paranoid plugin for soft delete of records. I was earlier managing it using a flag in the db. I know that this plugin will omit a record from searches and finds if the record is soft deleted. What I want to know is if I have a validation in the model like validates_uniqueness_of :email and I deleted(soft deleted) the record having email 'prince#gmail.com'. Now when I try to create a new user having same email, will the validation work and prevents the creation of the new record. Or will it omit the soft deleted record as it does for finds? (I would like this to happen, of course.)
acts_as_paranoid does not reimplement validates_uniqueness_of, so if you have (soft) deleted a record with email 'prince#gmail.com' you cannot create a new record with the same email.
The easy fix for this is to add a scope to validates_uniqueness_of:
validates_uniqueness_of :email, :scope => :deleted_at
This way you can have any number of (soft) deleted records with email 'prince#gmail.com' and still create a new record with the same email.
From our testing, the patching that acts_as_paranoid does affect the deletes, so you would end up with two records. From most of the conversations around the web, this is probably what you expect.
In our case, we didn't want this. When we create another user with the same email, we want to "undelete" the first user, and we'd like the validations to hep us with this. Turns out that we couldn't figure out a way to do what we wanted. We ended up not using acts_as_paranoid in this case, but we are still considering going back.
We did find one patch that allowed passing in a flag to validations (:with_deleted => true), so that you could explicitly control this. This seems like a good idea, but we decided not to pursue it. Unfortunately this issue highlights that this approach is a bit of a "leaky abstraction" and has to be used with care.
if yor are using "rails3_acts_as_paranoid" then have provision for above mentioned issue,
ActiveRecord's built-in uniqueness validation does not account for records deleted by ActsAsParanoid. If you want to check for uniqueness among non-deleted records only, use the macro validates_as_paranoid in your model. Then, instead of using validates_uniqueness_of, use validates_uniqueness_of_without_deleted. This will keep deleted records from counting against the uniqueness check.
Need to specify following way ,
acts_as_paranoid
validates_as_paranoid
validates_uniqueness_of_without_deleted :name