Confundido acerca de 'responder_to' vs 'responder_to?'

79

Estoy aprendiendo Rails con railstutorial.org y algo me confunde: en este capítulo el autor nos dice que hagamos algunas pruebas en la consola con el respond_to?método en un objeto User, y funciona bien. Pero más tarde, cuando escribimos la prueba para el :encrypted_passwordatributo, usa respond_to.

Por curiosidad, probé respond_toen la consola, para un objeto Usuario, y aparece un error que dice que el método no existe. Por desgracia, si intento escribir la prueba usando en respond_to?lugar de respond_to, la prueba no se ejecuta.

¿Alguien podría explicarme la diferencia y por qué la prueba solo se ejecuta con respond_to?

agente_secreto
fuente

Respuestas:

171

Ruby trata ?y !como caracteres reales en un nombre de método. respond_toy respond_to?son diferentes. ?indica que este debe responder con verdadero o falso (por convención; esto no es un requisito). Específicamente:

respond_to?es un método Ruby para detectar si la clase tiene un método particular. Por ejemplo,

@user.respond_to?('eat_food')

devolvería verdadero si la Userclase tiene un eat_foodmétodo.

respond_toes un método de Rails para responder a tipos de solicitudes particulares. Por ejemplo:

def index
  @people = Person.find(:all)

  respond_to do |format|
    format.html
    format.xml { render :xml => @people.to_xml }
  end
end

Sin embargo, en el enlace RailsTutorial que proporcionó, verá un método RSpecshould interactuando con el respond_tométodo RSpec . Esto no estaría disponible en su consola, a menos que ejecute rails console test.

Tim Sullivan
fuente
Pero si lee el ejemplo en el libro, respond_to no se usa con un tipo de solicitud, sino con un atributo. ¿Quizás Rails anula el método Ruby para que también acepte atributos?
agente_secreto
1
Ese es un método RSpec para probar: rspec.info/documentation ... no estaría disponible en la consola a menos que establezca ENV para probar.
Tim Sullivan
3
Me parece realmente extraño que los creadores de Ruby decidieran usar el mismo nombre de declaración "respond_to" para dos cosas diferentes: descubrir si un objeto tiene un método O responder a un tipo de solicitud. Oh si, hay un? eso los hace diferentes. Guau. \ o /
Junior Mayhé
4
Estos no eran creadores de Ruby en absoluto. El primero es un método Ruby. El segundo es un método Rails en ActionController. El tercero es un método de biblioteca RSpec. ? y! en Ruby tienen significado, entonces la diferencia entre respond_to y respond_to? son iguales a la diferencia entre trim y trimr.
Tim Sullivan
2
Para que los futuros usuarios no se confundan, al ?final del nombre de un método en ruby no garantiza que el método devolverá un booleano. El ?es sólo una parte del nombre del método, como cualquier otro carácter. Que los métodos de signo de interrogación deberían devolver un booleano es una convención bien establecida, pero no se sigue universalmente. (ver, por ejemplo, github.com/rails/rails/pull/5329 y la conmoción causada cuando un método de signo de interrogación no devolvió un bool)
Andrew
4

respond_to?es una evaluación booleana. Se respond_toutiliza (normalmente) para determinar la información de la pantalla. Más información aquí . Las respond_to?comprobaciones para ver si existe un método y devuelve verdadero si lo hace y falso si no lo hace.

Micharch54
fuente
3

La prueba utiliza ayudantes convenientes para que sea más fácil de usar.

Ruby es Ruby, por lo que usar el buen viejo respond_to?funcionaría si lo llama de esta manera:

 @user.respond_to?(:encrypted_password).should be_true

Hay otro que se respond_tousa en controladores pero aún nada que ver con los que ya conociste.

apneadiving
fuente