ruby on rails - Rails3: Cloning already-validated object prevents clone being invalidated -- is this strange or normal? -


In the Rail (3.0) test code, I cloned one object, so I checked the verification without changing the original I can cloak it for If I have said that (closing valid)? Before cloning , the clone passes the validates_presence_of test, even after that I have set the member_id value to zero.

The following two tests have been made clear. In a test, the original ("contact") before has been cloned. The clone fails in validity in the right way when the member UID disappears. Rendering C is successful.

In the test two, the clone is created followed by the original is valid. Even if the clone. Member_id is set to zero, this is passed validation. In other words, the claim 2C fails. Between the tests only is the sequence of two rows:

  clone = contact. By emphasizing the clone (contact.valid ?, "A")  

What's going on here? Is this a normal ruby ​​behavior: cloning that I just do not understand?

  test "clone problem 1" contact = contact.new (: member_id = & gt; 1) clone = contact clone claim (contact.valid ?, "A") is cloned . Member_id = ZERO ("Clone valid ?," C) End test "Clone problem 2" contact = contact.new (: member_id = & gt; 1) Stress (contact.valid ?, "2A") clone = contact. Clone was cloned. Member_id = Zero (? Cloned.valid ?, "2C") End  

You are surprised It can not work!

OK, can be found in the rail code. The first verification code will run:

  # Validation Module # Returns the object of the error, which holds all the information about #type error messages. DF errors @ erers || = Errors.New (self) and  

Because this is the first run, this will make a new instance of error class. Simple, is not it? But there is a hold - the parameter itself is in your case this is the "contact" object.

Later, when you call the clone object again, the @reference will not be created again - because it is not empty. And it is! Instead of going through "clones", the old self is used.

The error class in the verification code then runs the code that reads the values ​​from the @bas from the beginning can you see it? The value for the test is read not from the original model but from the clone! So the value on the "clone" object runs from the values.

OK, so far "why not" and now there are some words about "how".

The solution is simple - set it for zero before cloning and verification. Since it is quite private, simple work does not work. But this works:

  cloned.instance_eval do @errors = nil end  

and some tips for interesting reading:

This is quite comprehensive explanations in how the Rail works 3.


Comments