Validates and nested forms - ruby-on-rails

my ruby on rails 3.0.3 app display an empty address form when showing the cart to a customer.
The addresse module ask the presence of all fields :
validates :nom,:prenom,:adresse,:code_postal,:ville,:email, :presence => true
If I validate an empty form it works despite validate condition.
I complete the forms, go to next page and comes back to the now populated creation form. Now if i remove a field the valiates is taken into account.
Here is my empty address creation code for the nested form in the show action :
if (#cartshowed.adresse_client.nil?)
#cartshowed.build_adresse_client
end
I guess that when usind the empty address validation is ignored, but as soon as i validate data for an already valid adress it works.
How can i have validation working when i create the address, and not only for edition ?
PS : The edition/creation is done on the same page through the same controllers. Edition was not intended to exist but it works.
EDIT : After several try i think my problem is that creating adresse through nested forms completly overiddes validates field in address.
How can i kee validates restriction in a nested form?

If Addresse is a nested attribute (i.e. Cart has_one Address), perhaps you should use the accepts_nested_attributes_for which allows you to add a :reject_if Proc.
accepts_nested_attributes_for :addresse, :reject_if => :any_blank
I couldn't give a better example than Ryan Daigle:
http://archives.ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#method-i-accepts_nested_attributes_for

It seems that as soon as i use reject_if the validation of my children model is not totaly taken into account. Removing the reject_if resolved all my problems. Now an empty form or a form not conform to the validates requirement is correctly rejected at the update_attributes step in the controller.

Related

What is the rationale for `reject_if`?

I've come across reject_if in cocoon's README, and also in the documentation for Nested Attributes. What is the rationale for using reject_if when the associated active record objects can determine whether they're valid or not?
For nested objects, you may not want to attempt to submit a record that is :all_blank or for any other reason you may want to check on. The point being, an empty or incomplete (in some way) object can, this way, simply not be built / added to the nested objects collection.
Validations serve a different purpose. If an empty object, say, fails validation then the whole form submit will fail. The reject_if approach allows submission to succeed in such a case by removing the object from consideration before validations fire.
The Rails guides has a description of the rationale for :reject_if, though it doesn't explicitly compare this option to just validating the sub-objects:
9.5 Preventing Empty Records
It is often useful to ignore sets of fields that the user has not
filled in. You can control this by passing a :reject_if proc to
accepts_nested_attributes_for. This proc will be called with each
hash of attributes submitted by the form. If the proc returns false
then Active Record will not build an associated object for that hash.
The example below only tries to build an address if the kind
attribute is set.
class Person < ActiveRecord::Base
has_many :addresses
accepts_nested_attributes_for :addresses, reject_if: lambda {|attributes| attributes['kind'].blank?}
end
As a convenience you can instead pass the symbol :all_blank which
will create a proc that will reject records where all the attributes
are blank excluding any value for _destroy.

Rails accepts_nested_attributes_for with _destroy can skip presence validation

So I have a typical Rails model with accepts_nested_attributes_for with presence validation
(snippets)
class Book < ActiveRecord::Base
...
has_one :cover
accepts_nested_attributes_for :cover, allow_destroy: true
validate :require_cover
def require_cover
errors.add('', 'You must have a cover for the book.') if self.cover.blank?
end
...
end
This works and validates okay on the first step when I'm creating. But when I try to edit it and click delete on the cover (clicking delete adds _destroy true) and save it, it deleted the cover but the validation regarding presence has passed already.
I think what happened was:
tagged destroy cover
validation process happens (thinks there is still cover (but maybe doesn't recognize destroy))
valid and goes to saving
saves book and
passes
No validation again regarding the no cover
Have I done this incorrectly? Is there another way to implement this? Or how do I revalidate this scenario (like, after the save and destroy that has happened, there would be another validation to say that the resulting object is now invalid)?
I found the fix to my question, I was right that the save doesn't take into account those that are tagged as _destroy.
This link describes the problem better and has the answer to it too.
http://homeonrails.com/2012/10/validating-nested-associations-in-rails/
Basically he rejected those that are marked for destruction and counted the remaining ones.

Check if data is already inserted in database in rails

I'm doing an ajax call to save data.Now the issue is that user might unknowingly submit the same data twice and it will become duplicate. Is there any shortcut or validation for abandoning the user from submitting or saving the same data twice?
Also please note that created_at,updated_at will not be same when the user submits the form for the second time. Also the only thing that can be unique in my table is ID :) .
If I have 10 form fields and until and Unless all the 10 fields of my form are same the validator will not reject the data.
You can use an attribute like 'title' and check if it's uniq for that user :
class SomeModel < AR
validates_uniqueness_of :title, :scope => [:user_id]
end
I do not think there's a reasonable solution of this problem on the server side.
Try a simple magic of javascript disable_with.

Rails 3 : Mass-assignment with ActiveAdmin and has_one

I am developing a rails application in which I have two models User and Client.
User is backed by devise and is responsible for authentication and has_one Client which holds the client details for a given user. This relation is always present as I ensure that a Client model is created whenever I create a User.
For the administration area I am using ActiveAdmin. Now, when I try to create a User through the administration interface I use a form like this:
form do |f|
f.inputs :username, :email, :password
f.inputs :name => "Client", :for => :client do |client|
client.inputs :name, :address, ...
end
end
The problem is that either the User nor the Client are saved and the page is reloaded with validation errors. I have checked rails console and there's a WARNING: Can't mass-assign protected attributes: client_attributes message every time I try to create a User.
I have searched over this issue and found that in order to allow for mass-assignment one had to define attr_accessible for each of the fields allowed for the assignment. So, I had put this directive in Client model for each of the fields mentioned above and the message keeps appearing, preventing the models to be properly saved.
Does anyone have a clue on this?
The problem is not in your Client model, but in your User model - because this is the primary model you are trying to create. All you need to do is to add client_attributes to the list of attr_accessible attributes in your User model, just as the error message in the log files says, e.g.:
class User < ActiveRecord::Base
attr_accessible :client_attributes
end
I imagine you already have a list of accessible attributes in the User class. So just add client_attributes to the end of that list.
The changes you made to your Client model (i.e. adding a list of attributes to attr_accessible) is not needed for this to work. If you want, you can also go ahead and undo that.

stop record from being saved if all empty strings in rails

I currently have a nested forms model. The nested forms for the paperclip attachments work fi and don't populate the DB with blanks, but another one I have for quotes always saves one blank quote along with my main model when I create a new one. How can I just have it silently fail and bypass writing this to the db? It's an optional field so I don't want to give them an error.
Use the following option on accepts_nested_attributes
accepts_nested_attributes_for :quotes, :reject_if => :all_blank
If you want to be more specific about when the record is considered blank, :reject_if also can take a proc.

Resources