Nie masz pewności co do „respond_to” i „respond_to?”

79

Uczę się Railsów z railstutorial.org i coś mnie pogubiło: w tym rozdziale autor mówi nam, abyśmy wykonali testy w konsoli respond_to?metodą na obiekcie User i wszystko działa dobrze. Ale później, kiedy piszemy test dla :encrypted_passwordatrybutu, używa respond_to.

Z ciekawości wypróbowałem respond_tow konsoli obiekt User i otrzymałem komunikat o błędzie informujący, że metoda nie istnieje. Niestety, jeśli spróbuję napisać test używając respond_to?zamiast respond_to, test nie działa.

Czy ktoś mógłby mi wyjaśnić różnicę i dlaczego test działa tylko z respond_to?

agente_secreto
źródło

Odpowiedzi:

171

Ruby traktuje ?i !jako rzeczywiste znaki w nazwie metody. respond_toi respond_to?są różne. ?wskazuje, że powinno to odpowiedzieć prawdą lub fałszem (zgodnie z konwencją; nie jest to wymagane). Konkretnie:

respond_to?jest metodą Rubiego służącą do wykrywania, czy klasa ma określoną metodę. Na przykład,

@user.respond_to?('eat_food')

zwróci wartość true, jeśli Userklasa ma przypisaną eat_foodmetodę.

respond_tojest metodą Railsową służącą do odpowiadania na określone typy żądań. Na przykład:

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

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

Jednak w podanym odnośniku RailsTutorial widzisz metodę RSpecshould oddziałującą z respond_tometodą RSpec . To nie byłoby dostępne w twojej konsoli, chyba że uruchomisz rails console test.

Tim Sullivan
źródło
Ale jeśli przeczytasz przykład w książce, odpowiedź_to nie jest używana z typem żądania, ale z atrybutem. Może Railsy przesłaniają metodę Ruby, więc akceptuje również atrybuty?
agente_secreto
1
To jest metoda testowania RSpec: rspec.info/documentation ... nie byłaby dostępna w konsoli, chyba że ustawisz ENV na testing.
Tim Sullivan
3
Wydaje mi się naprawdę dziwne, że twórcy Rubiego zdecydowali się użyć tej samej nazwy instrukcji „respond_to” do dwóch różnych celów: dowiedzieć się, czy obiekt ma metodę LUB odpowiedzieć na typ żądania. O tak, jest? to czyni je innymi. Łał. \ o /
Junior Mayhé
4
To wcale nie byli twórcy Rubiego. Pierwsza to metoda Ruby. Druga to metoda Railsów w ActionController. Trzecia to metoda biblioteki RSpec. ? i ! w Rubim mają znaczenie, więc różnica między respond_to i respond_to? są równe różnicy między trymowaniem i trymowaniem.
Tim Sullivan
2
Aby przyszli użytkownicy nie byli zdezorientowani, ?znak na końcu nazwy metody w ruby nie gwarantuje, że metoda zwróci wartość logiczną. To ?tylko część nazwy metody, jak każdy inny znak. To, że metody ze znakami zapytania powinny zwracać wartość logiczną, jest ugruntowaną konwencją, ale nie jest powszechnie przestrzegana. (patrz na przykład github.com/rails/rails/pull/5329 i zamieszanie spowodowane, gdy metoda ze znakiem zapytania nie zwróciła wartości bool)
Andrew
4

respond_to?jest wartością logiczną. respond_toJest stosowany (zwykle) do określania informacji na wyświetlaczu. Więcej informacji tutaj . Do respond_to?sprawdza, czy metoda istnieje i zwraca true jeśli to robi i false jeśli nie.

Micharch54
źródło
3

Test korzysta z wygodnych pomocników, aby był bardziej przyjazny dla użytkownika.

Ruby to Ruby, więc użycie starego dobrego respond_to?byłoby działało, gdybyś nazwał to w ten sposób:

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

Jest inny respond_toużywany w kontrolerach, ale nadal nie ma to nic wspólnego z tymi, których już spotkałeś.

bezdechu
źródło