2009-07-09 12 views
6

Jestem nowicjuszem w Ruby i ostatnio wpadłem na problem w porównaniu do wartości podczas tworzenia aplikacji Ruby on Rails. W kontrolerze miałem następujące oświadczenie, że zawsze zwrócony fałsz:Składnia Sprawdzanie lub "Kompilowanie" aplikacji Ruby on Rails

if (user.id != params[:id]) 

Problem był user.id (która jest Active Record) jest liczbą całkowitą i params [: id] jest ciągiem. Zajęło mi to trochę czasu i ostatecznie zmieniłem go na:

if (user.id != params[:id].to_i) 

Teraz instrukcja działa zgodnie z oczekiwaniami.

Aby uniknąć tego błędu w przyszłości, istnieje sposób na "kompilację" lub uzyskanie przez Ruby ostrzeżenia, jeśli spróbujesz porównać 2 różne typy? Niektóre inne problemy, na które napotkałem, które chciałbym "sprawdzić kompilacji" to:

  • Ostrzegaj mnie, jeśli utworzę zmienną, ale jej nie używam. Aby pomóc w sprawdzaniu literówek w nazwach zmiennych.
  • Upewnij się, że metoda istnieje w klasie, więc mogę uniknąć literówek nazw metod, a także pomóc w refaktoryzacji, na przykład jeśli zmieniam nazwę metody.

Obecnie używam Ruby 1.8.6-27 RC2 z Rails 2.3.2 i RadRails IDE w systemie Windows.

+0

Proszę nie odpowiadać na pytania dotyczące testowania kodu. Miałem test jednostkowy dla powyższego fragmentu kodu i ciągle się nie udawało (wraz z testowaniem ręcznym) i nie mogłem zrozumieć dlaczego. Czego szukam to sprawdzarka składni dla Rubiego, która znajdzie podobne błędy, które znajdzie standardowy kompilator. Thanx. –

+0

Kompilator języka C nie daje błędu za wykonanie 4 == 5.5. – Chuck

+0

Sprawdź jetbrains ruby ​​ide, https://www.jetbrains.com/ruby/ –

Odpowiedz

0

Najlepszym rozwiązaniem, które znalazłem, było IDE, które przeprowadzało sprawdzanie składni w locie, takie jak RubyMine. Nie jestem pewien, czy rozwiązałby mój pierwotny problem, ale pomógł mi znaleźć i naprawić kilka innych błędów składni i kompilacji. Dziękuję wszystkim za sugestie.

5

Najpierw przetestuj, a następnie kod. Jeśli napiszesz testy obejmujące wszystkie gałęzie aplikacji, uzyskasz pewność, że twój kod działa i generuje poprawne wyniki.

EDYCJA: Należy zauważyć, że możliwość porównania dwóch typów, nie zależy od nazw metod do ostatniej sekundy, itp. Są podstawowe funkcje Ruby.

Nie wywołujesz metody tak bardzo, jak wysyłasz wiadomość do obiektu. Obiekt jest wówczas odpowiedzialny za ustalenie, w jaki sposób obchodzić się z metodą. W Railsach służy to do uzyskiwania dostępu do kolumn DB w ActiveRecord. Nie ma metod dla kolumn, dopóki wiadomość o nazwie kolumny nie zostanie wysłana do obiektu.

Pisanie statyczne w języku Ruby działa wbrew systemowi pisania kaczkami. Często można uzyskać polimorfizm za darmo bez obawy o skomplikowane schematy dziedziczenia/interfejsu.

Proponuję obejmując te funkcje i zrekompensować niepewności poprzez testowanie

1

Ruby nie ma być bezpieczny. Pozwala porównywać dowolne dwa obiekty, i stąd bierze się wiele jego mocy. Railsy nie byłyby możliwe bez tak dynamicznego projektu.

Nawet skompilowany język, taki jak Java lub C, nie powstrzyma cię od zrobienia == na dwóch obiektach. Jak powiedział Ben, najlepiej najpierw przetestować. Sprawdź struktury, z którymi pracujesz. Jednym ze sposobów, aby uzyskać informacje na temat obiektu Ruby jest użycie:

puts object.class 
+0

obiekt p, zrzuci bardziej szczegółową wersję obiektu. Mieszanie p i put jest ogólnie zwyciężczynią w uzyskiwaniu informacji o debugowaniu. –

+0

Tak. Drukuj to moje wybrane narzędzie do debugowania. Możesz również użyć ./script/console, aby uzyskać interaktywny dostęp do obiektów. – mcandre

1

Ogólnie, najlepszym sposobem (znam), aby uniknąć tego typu problemu dla dynamicznych języków/skryptowych jest przenieść „logikę” metod/commands i napisać dla nich testy jednostkowe. Zasadniczo wszystko, co może zawieść, powinno zostać przetestowane. Kod na stronie powinien być głupim logiką ... zamiast wyświetlać tylko te elementy, które spełniają określone kryteria, powinien wyświetlać wszystkie elementy i otrzymywać listę pozycji z metody, która zwraca tylko te, które powinny być wyświetlane.

2

Ruby nie pozwala na ponowne zdefiniowanie operatora == dla obiektu.W Ruby 1.8 nie można, Ruby 1.9 miało to zrobić, ale nie udało mi się przekonać mojego skryptu do pracy w klasach podstawowych. Działa dobrze w przypadku niestandardowych zdefiniowanych obiektów.

class Object 

    alias :equal_without_warning :== 

    def ==(object) 
    unless self.class == object.class 
     warn("Comparing `#{self.class}' with `#{object.class}'") 
    end 
    equal_without_warning(object) 
    end 

end 

Zakładając, że nie zrobiłem jakiś głupi błąd kodowania, odpowiedź brzmi NIE, nie możesz sprawdzić, czy porównując różne typy obiektów.

Ponadto, powiedziałbym, że nie. W rzeczywistości Ruby nie jest zaprojektowany do pracy w ten sposób, jest to raczej podejście java niż styl Ruby.

+0

Będziesz musiał powtórzyć tę samą definicję dla klas podstawowych, ponieważ zwykle definiują one ponownie == bez odwoływania się do Obiektu # == – rampion

0

dwie rzeczy sugeruję:

One: Przeczytaj na IRB (lub skrypt/konsoli na szynach). Powszechną praktyką rozwojową w językach dynamicznych jest wypróbowywanie fragmentów kodu wewnątrz "żywego" interpretera (takiego jak IRB lub konsola szynowa). Ta praktyka pochodzi z najwcześniejszych języków dynamicznych, takich jak Smalltalk i Lisp. Ruby-debug jest również bardzo przydatny w rozwiązywaniu problemów i byłby naprawdę prostym sposobem wykrycia błędu w twoim przykładzie.

Po drugie: Czytaj dalej "Pisanie kaczek". "Typy" i zmienne działają trochę inaczej w Ruby niż wiele osób tego oczekuje. Jak rozumiem, zmienna taka jak user.id nie ma "typu". Wartość wskazała na przez user.id ma typ, ale sama zmienna nie. Uważam, że jest to po części powodem, dla którego nie ma narzędzia, które powiedziałoby ci, jaki był twój błąd przed uruchomieniem programu. Porównanie tych dwóch zmiennych nie jest błędem, ponieważ zmienne nie mają typu. user.id wskazywał na liczbę całkowitą w tym punkcie twojego programu, ale byłoby całkowicie legalne przypisanie user.id do wskazania ciągu znaków, w którym to punkcie porównanie to miałoby dużo więcej sensu. :-)

+0

Nie ma również powodu, aby nie porównywać dwóch różnych typów za pomocą '=='. – Chuck