Problema con validaciones

Hola,

Debo de tener un fallo tonto en el siguiente modelo porque las
validaciones de “receiver” y “sender” no van, pero sí la de “amount”.
¿Qué estoy haciendo mal? Gracias.

class Transfer < ActiveRecord::Base
belongs_to :receiver,
:class_name => “User” ,
:foreign_key => “user_id”
belongs_to :sender,
:class_name => “User” ,
:foreign_key => “user_id”

validates_presence_of :receiver, :sender, :amount

protected
def validate
errors.add(:receiver,"…") if receiver.nil?
errors.add(:sender,"…") if sender.nil?
errors.add(:amount, “…”) if amount.nil? || amount < 0.01
end
end

On 9/5/07, Héctor Pérez Arenas [email protected] wrote:

Debo de tener un fallo tonto en el siguiente modelo porque las
validaciones de “receiver” y “sender” no van, pero sí la de “amount”.
¿Qué estoy haciendo mal? Gracias.

Como dice el “Warning” de la documentación [1], para validar la
presencia de una relación hay que utilizar el nombre de la clave
foránea, y no el de la
asociación:
validates_presence_of :user_id

PD: ¿Ambas relaciones utilizan la misma FK?

[1]
http://rails.rubyonrails.com/classes/ActiveRecord/Validations/ClassMethods.html#M000941

Damian J. wrote:

Como dice el “Warning” de la documentaci�n [1], para validar la
presencia de una relaci�n hay que utilizar el nombre de la clave
for�nea, y no el de la
asociaci�n:
validates_presence_of :user_id

PD: �Ambas relaciones utilizan la misma FK?

Cierto, gracias. Ahora queda según [2]

Una cosa más. ¿Son necesarias las siguientes lineas para que aparezca el
error?
errors.add(:receiver,"…") if receiver.nil?
errors.add(:sender,"…") if sender.nil?
¿o validates_presence_of ya lo hace? Suponía que sería así, pero
testeando sólo me aparece si lo añado explícitamente con errors.add en
el método validate [3].

[2]

class Transfer < ActiveRecord::Base
belongs_to :receiver,
:class_name => “User” ,
:foreign_key => “receiver_id”
belongs_to :sender,
:class_name => “User” ,
:foreign_key => “sender_id”

validates_presence_of :receiver_id, :sender_id, :amount

protected
def validate
#errors.add(:receiver,"…") if receiver.nil?
#errors.add(:sender,"…") if sender.nil?
errors.add(:amount, “should be at least 0.01”) if amount.nil? ||
amount < 0.01
end
end

[3]

def test_not_create_transfer_if_params_missing
check_not_create_transfer_if_missing(:amount)
check_not_create_transfer_if_missing(:receiver)
check_not_create_transfer_if_missing(:sender)
end

private
def create_transfer(params={})
default={:amount=>3.0,:receiver=>@user,:sender=>@userB}
Transfer.create(default.merge(params))
end

def check_not_create_transfer_if_missing(param)
t=create_transfer(param=>nil)
assert !t.valid?
assert t.errors.invalid?(param)
end

On 9/6/07, Héctor Pérez Arenas [email protected] wrote:

Una cosa más. ¿Son necesarias las siguientes lineas para que aparezca el
error?
errors.add(:receiver,“…”) if receiver.nil?
errors.add(:sender,“…”) if sender.nil?
¿o validates_presence_of ya lo hace? Suponía que sería así, pero
testeando sólo me aparece si lo añado explícitamente con errors.add en
el método validate [3].

Lo que pasa es que estás sobrescribiendo el método #validate, por lo
que las validaciones de Rails nunca ocurren.

Probá esto:

def validate
super
errors.add …
end

On 9/6/07, Héctor Pérez Arenas [email protected] wrote:

       :class_name => "User" ,
       :foreign_key => "receiver_id"

belongs_to :sender,
:class_name => “User” ,
:foreign_key => “sender_id”

validates_presence_of :receiver_id, :sender_id, :amount
end

¿Este es todo el código de la clase?

Hagamos las preguntas típicas… versión de Rails, plugins…

Damian J. wrote:

Lo que pasa es que est�s sobrescribiendo el m�todo #validate, por lo
que las validaciones de Rails nunca ocurren.

Aún así sigue igual: No valida sender ni receiver a no ser que lo añada
yo con errors.add

Puede que el error esté en las foreign_key de los belongs_to, porque
amount sí que lo valida sin necesidad del errors.add De hecho, si borro
el método validate de mi modelo, sí valida amount pero no receiver ni
sender. En este caso el código queda:

class Transfer < ActiveRecord::Base
belongs_to :receiver,
:class_name => “User” ,
:foreign_key => “receiver_id”
belongs_to :sender,
:class_name => “User” ,
:foreign_key => “sender_id”

validates_presence_of :receiver_id, :sender_id, :amount
end

Damian J. wrote:

Hagamos las preguntas t�picas… versi�n de Rails, plugins…

La versión de Rails es la 1.2.3 y hasta el momento sólo utilizo los
plugins restful_authentication, open_id_authentication y
annotate_models.

�Este es todo el c�digo de la clase?

class Transfer < ActiveRecord::Base
belongs_to :receiver,
:class_name => “User” ,
:foreign_key => “receiver_id”
belongs_to :sender,
:class_name => “User” ,
:foreign_key => “sender_id”

validates_presence_of :receiver_id, :sender_id, :amount

protected
def after_create
User.transfer(:receiver=>receiver,:sender=>sender,:amount=>amount)
end
end

Y por si el problema puede estar en los has_many de User:

class User < ActiveRecord::Base
has_many :transfers, :order=>‘created_at DESC’,
:foreign_key=>‘receiver_id’
has_many :outgoings, :class_name => “Transfer”, :order=>‘created_at
DESC’, :foreign_key=>‘sender_id’


end

On 9/7/07, Héctor Pérez Arenas [email protected] wrote:

Es decir, assert !t.valid? va bien (no crea la transfer) pero assert
t.errors.invalid?(:sender) no (a no ser que incluya explícitamente el
método validate, según [5]). En cambio, con amount sí que incluye el
error (si creamos la transferencia sin :amount).

Amigo!

No sería así? :slight_smile:

t.errors.invalid?(:sender_id)

Damian J. wrote:

No ser�a as�? :slight_smile:

t.errors.invalid?(:sender_id)

Vaya, creía que lo había probado. Puede que lo haya hecho en
check_not_create_transfer_if_missing y no sólo en el t.errors.

Muchas gracias Damian :wink:

On 9/7/07, Héctor Pérez Arenas [email protected] wrote:

Vaya, creía que lo había probado. Puede que lo haya hecho en
check_not_create_transfer_if_missing y no sólo en el t.errors.

un placer :slight_smile:

He creado una aplicación nueva (que adjunto) sólo con el código de mi
comentario anterior y con el transfer_test.rb de [4].

Aunque en los últimos comentarios no lo he dejado muy claro, realmente
sí que valida pero no añade el error, como comentaba en el segundo
comentario:

Una cosa más. ¿Son necesarias las siguientes lineas para que aparezca el
error?
errors.add(:receiver,"…") if receiver.nil?
errors.add(:sender,"…") if sender.nil?
¿o validates_presence_of ya lo hace? Suponía que sería así, pero
testeando sólo me aparece si lo añado explícitamente con errors.add en
el método validate [3].

Es decir, assert !t.valid? va bien (no crea la transfer) pero assert
t.errors.invalid?(:sender) no (a no ser que incluya explícitamente el
método validate, según [5]). En cambio, con amount sí que incluye el
error (si creamos la transferencia sin :amount).

¿Alguna idea de qué hago mal? Gracias de nuevo.

[4]

def setup
@user=User.create
@userB=User.create
end
def test_not_create_transfer_if_params_missing

check_not_create_transfer_if_missing(:amount)

check_not_create_transfer_if_missing(:receiver)

check_not_create_transfer_if_missing(:sender)

#Temp:
t=Transfer.create(:amount=>3.4, :sender=>@user, :receiver=>@userB)
assert t.valid?

t=Transfer.create(:amount=>3.4)
assert !t.valid?
assert t.errors.invalid?(:sender)

end

[5]

class Transfer < ActiveRecord::Base
belongs_to :receiver,
:class_name => “User” ,
:foreign_key => “receiver_id”
belongs_to :sender,
:class_name => “User” ,
:foreign_key => “sender_id”

validates_presence_of :receiver_id, :sender_id, :amount

protected
def validate
super
errors.add(:receiver,"…") if receiver.nil?
errors.add(:sender,"…") if sender.nil?
errors.add(:amount, “…”) if amount.nil? || amount < 0.01
end
end