Hej,
zastanawiam się jakie jest wasze zdanie w kwestii nadpisywania to_s w modelach. Banalny przykład:
class User
def full_name
[firstname, lastname].compact.join(' ')
end
alias :to_s :full_name
end
zaciemnia czy rozjaśnia kod? Ew. tworzenie to_s z parametrami typu
to_s(:with_age)
Interesują mnie zalety i wady korzystania z tego (może jest jakaś ogólnie przyjęta praktyka?).
[quote=paneq]Z zupełnie innej beczki i nie na temat. Czemu nie?:
"#{firstname} #{lastname}"
[/quote]
To akurat rozumiem - jeśli brakuje pierwszego, to będzie niepotrzebna spacja z przodu. Choć lepiej chyba byłoby “#{f} #{l}”.strip.
to_s może przyjmować parametry - jest tak np. w wbudowanych klasach Rubiego:
10.to_s #=> "10"
10.to_s(16) #=> "a"
Nie widzę więc przeciwwskazań z zastosowaniem parametru (przynajmniej w kontekście podążania za standardami. Natomiast zastanawiam się, czy faktycznie jest sens tworzyć fullname i aliasować go przez to_s. Czy samo to_s nie wystarczy?
Ja rozumiem dlaczego to jest tak napisane i jaka jest różnica, tylko jeśli twoja aplikacja nie wymaga firstname (lub lastname) to kto by się tym przejmował
Dzięki za odpowiedzi. Powiem szczerze, że bardziej zależy mi na opinii o samym używaniu to_s niż aliasowaniu go Tzn. ilu z was używa tego w swoich aplikacjach i czy nie uważacie tego za zaciemnianie kodu (ostatnio miałem dyskusję na ten temat, dlatego mnie to ciekawi)?
ja uważam to za super praktykę - zysk jest zwłaszcza przy selectach - podając jako kolekcję User.all masz automagicznie opcje z imieniem i nazwiskiem - bez jakiejś żonglerki .map czy innymi cudami.
w większości przypadków, wydaje mi się, że jesteś w stanie zgadnąć. Widząc modele Restaurant, User, Article sądzę, że bez patrzenia w kod jesteś w stanie się domyśleć co .to_s zwraca. A gdy masz wątpliwości (lub model, w którym ciężko zgadnąć) - sprawdzenie tego w modelu zajmuje ułamek sekundy *
jasne, przy czym ja nie jestem wielkim fanem formtastica
Podsumowując: uważam, że .to_s daje zupełnie gratis dużo plusów. Jedyne, czego trzeba się trzymać, to żeby ta metoda była możliwie prosta. o ile parametryzacja metody w pewnych przypadkach wydaje mi się dopuszczalna, tak robienie jakiejś większej magii (nawet nie bardzo jestem w stanie wymyślić jakiś use-case), taki, że domyślenie się, co faktycznie metoda zwraca w więcej niż 10 sekund to zło.
Restauracja - nazwa, ale z miejscowością czy już nie
Użytkownik - login, email, full name - nie mam pojęcia.
Article - pewnie nazwe ale równie dobrze z jakiegoś powodu mogłaby to być część nazwy (by nie za długi) lub odpowiednia wersja bez jakiś znaków specjalnych czy coś. Może też z autorem.
Powiedziałbym, że pewnie jak pracujesz w projekcie to wiesz co zwraca (nauczyłeś się na pamięć lub znasz strukturę aplikajci na tyle by się domyślić) natomiast jak z doskoku siadasz to już nie byłbym taki pewien. Wydaje mi się, że w dłuższym czasie nie ma to wszystko szczególnego znaczenia. Ani dla czytelności ani dla wydajności pisania.
Moim zdaniem o wiele sensowniej do takich celów używać dekoratorów, np.: https://github.com/jcasimir/draper
W modelu nie powinno być logiki prezentacji, bo co jeśli np. będziemy chcieli dać tam i18n lub lokalizacje?
ile osób, tyle podejść - ja mimo wszystko uważam, że wszystko powinno być tak proste, jak to tylko możliwe(a .to_s jest chyba najprostszym rozwiązaniem)
rozmawialiśmy o w miarę prostych przypadkach (np. User), gdzie imienia i nazwiska raczej nie wpychasz do i18n. Jeśli natomiast znalazłbyś przypadek, gdy faktycznie trzeba, to można przecież to załatwić np. przez globalize(lub np. mongo)
Niezależnie od tego czego się później używa, warto zdefiniować to_s w taki sposób, żeby był krótki i dawał jakiś obraz obiektu, z którym mamy do czynienia. Jest to szczególnie przydatne przy pracy w konsoli.
W Django na przykład to jest normalna praktyka i pojawia się już w pierwszym tutorialu (Wait a minute. <Poll: Poll object> is, utterly, an unhelpful representation of this object.) - właśnie do ułatwienia pracy z konsolą (ale nie tylko - Django Admin też z tego korzysta np. do wyświetlania listy rekordów).
Tylko że w Ruby by default dostajesz w takim wypisaniu wartości wszystkich zmiennych instancyjnych, co jest bardzo prostą, czytelną i pomocną reprezentacją.
Z punktu widzenia ood to_s jest na zbyt niskim poziomie abstrakcji (powiedziałbym nawet, że na takim jak id) i raczej nie powinien byc używany w logice aplikacji. Jeżeli chcesz dostać full_name to napisz metodę, która to zrobi. to_s tak jak już ktoś wspomniał może być przydatny na konsoli albo przy debugowaniu.
Widziałem ostatnio kod (javowy), który w testach porównywał dwie daty bazując na tym co zwróci toString(). Problem w tym, że na polskich localach toString() zwraca coś innego niż na angielskich przez co oczywiście test w głupi sposób failował.
Nie po to mamy puts i p (lub puts zmienna.inspect ;))?[/quote]
Dokładnie. @Tomasz - prostą i pomocną, owszem, ale czytelną? Jak wypisuję 50 obiektów z 10 zmiennymi instancyjnymi, to nigdy to nie jest czytelne.