Pytanie - odpowiedź

Mam taki pomysł, żeby założyć jeden zbiorczy wątek, gdzie kto chce zadaje krótkie pytanie w jakiejś konkretnej kwestii (bo sprawa jest błaha i bez sensu zakładać nowy wątek, a nie ma kogo zapytać) i jeśli ktoś ma ochotę i czas to odpowiada.

Mnie np. jako początkującego często coś nurtuje, a googlowanie za jakimś drobiazgiem języka, subtelną różnicą między metodami itp. bywa żmudne i mało efektywne. Bo nie wiesz np. jak sformułować pytanie.

Jeśli temat się przyjmie to fajnie, jak nie to albo ktoś wrzuci do koszta albo umrze śmiercią naturalną (tzn. poleci w dół :D)

To ja zacznę.

Czy (tak było w starszych wersjach RoR)

:presence => true

to DOKŁADNIE to samo co

presence: true

?
Z czego wynika taki zapis? przypuszczam, że chodzi o możliwości Rubiego, ale nie wiem dokładnie o co.

To jest po prostu nowa składnia zapisywania hashy, dostępna od Rubiego 1.9 i tyle :wink:

Jest to dokładnie to samo, większość preferuje nowy zapis. Zwykle w projekcie się trzyma jednej z wersji w całym kodzie.

1 Like

@beskidy1 Nie wiem czy administrator tego forum zaakceptuje Twój pomysł, bo z obserwacji wynika że na forach dyskusyjnych preferowane jest umieszczanie każdego pytania w oddzielnym temacie. Mi Twój pomysł podoba się, bo zawsze wydawało mi się niecelowe zakładanie nowego tematu gdy ktoś chce zapytać o jakiś drobiazg. Z drugiej strony, umieszczenie wszystkich pytań i odpowiedzi utrudnia późniejsze znalezienie czegoś za pomocą wyszukiwarki. Ale może mylę się.

Też się nad tym czasem zastanawiam. Składnia haszy to jeden z większych idiotyzmów składni tego języka.

Co w tym idiotycznego? W większości przypadków w Hashah kluczami są symbole. Używanie dwukropka oszczędza 2 znaki (krótsze = lepsze) i wygląda przyjaźniej (podobnie do JSONa).
Stary format jest potrzebny, bo czasami chcemy mieć inny klucz niż symbol i tyle.

Primo, jakby krótsze było lepsze to by ludzie nazywali zmienne i metody jedną literą, a zmiast “def” i “rescue” mielibyśmy “d” i “r”. Dwa znaki jeszcze nikogo nie zbawiły.

Secundo, wprowadzanie nowego formatu, który ma jedynie zastąpić szczególny przykład użycia starego, a przez to komplikowanie składni języka to dość “interesujący” pomysł w sytuacji gdy parsowania kodu Ruby’ego nie życzyłbym nawet temu co ojca i matkę zabił.

Tertio, spróbuj kiedyś początkującemu wytłumaczyć, że to jest w sumie to samo, ale się inaczej pisze, ale w sumie to nie to samo, bo klucz jest zawsze symbolem.

Wprowadzenie tej składni ma związek z wprowadzeniem keyword arguments. Jak wiemy, gdy nie było ich w języku to wszyscy stosowali hash jako ostatni argument w metodach. Wtedy jako pierwszy krok do implementacji tych argumentów wprowadzono alternatywną skadnię dla hashy z symbolami jako klucze. Użycie nowej składni sprawiało wrażenie, że coś takiego już jest w języku. Kolejnym krokiem było dodanie nazwanych parametrów def foo(bar: 1) i wtedy składnia deklaracja pokrywała się z wywołaniem. Można oczywiście dyskutować, że znak “:” zamiast “=>” nic nie wnosi, ale ja osobiście widzę w nim sens. Wprowadza zdecydowanie mniej “zamieszania” wizualnego. Przy wywołaniach, gdzie podajemy kilka argumentów (a w rubym/railsach to chleb powszedni) różnica jest już znacząca.

1 Like

Dzięki wszystkim za wyjaśnienia. I znowu ja mam pytanie :smiley:

validates :content, length: { maximum: 140 }

Dlaczego parametr maximum przekazywany jest w klamrowych nawiasach (chodzi o to, że to ma być blok kodu)?

Już na początku nauki Railsów zastanowiła mnie taka składnia i wciąż jej nie rozkminiłem :slight_smile: Rozumiem, że do metody validates przekazywany jest parametr (jako symbol) :content i :length. I jak to dalej rozumieć, że razem z parametrem length (który jest symbolem) przekazujemy dodatkowy parametr :maximum, który też jest symbolem i wsazuje na wartość 140?

Uff… chyba za bardzo namieszałem…

Czytałem trochę o symbolach i haszach w Rubym, ale powyższego zapisu nadal nie rozumiem.
Wiem, że to drobiazg, ale wydaje mi się, że automatyczne pisanie czegoś czego się nie rozumie (“bo tak było w tutorialu”) jest trochę bez sensu.

Nie. To, co wywołujesz, to tak na prawdę:

validates(:content, { length: { maximum: 140 } })

a metoda jest zdefiniowana na wzór tego

def self.validates(column, options = {})

Jest to jedna z “prawie” konwencji railsów jeśli chodzi o publiczne API, że ostatni parametr jest hashem który przyjmuje wszystkie dodatkowe parametry.
+
http://heartmindcode.com/2013/09/05/parentheses-in-ruby/

1 Like

Owszem, podobna sygnatura jest dość powszechna w Railsach, ale nie dotyczy wspomnianej metody. Ma to o tyle znaczenie, że może ona przyjmować jako argument listę atrybutów:

validates(*attributes)

Dzięki temu możliwa jest poniższa konstrukcja:

validates :first_name, :last_name, presence: true

Nie zgłębiałem się w samą metodę, Railsy często używają też metody #extract_options (lub podobnej), która wybiera tego hasha z listy argumentów. Jedno z dwóch :wink:

EDIT: O, prawie trafiłem: http://apidock.com/rails/ActiveSupport/CoreExtensions/Array/ExtractOptions/extract_options!

Dziś pytanie trochę z innej beczki :smiley:

Nie rozumiem takiego zapisu:

redirect_to @user

Skąd RoR wie o co mi chodzi? No bo przecież @user to tylko zmienna zawierająca obiekt, którym jest pojedynczy użytkownik. Nie ma to nic wspólnego ze ścieżką url.

Chodzi o:

Note that we can omit the user_url in the redirect, writing simply redirect_to @user to redirect to the user show page.

Źródło: https://www.railstutorial.org/book/sign_up#sec-the_finished_signup_form

W odpowiedzi na takie pytania przydatna okazuje się dokumentacja. Dla metody #redirect_to będzie to http://apidock.com/rails/v4.0.2/ActionController/Redirecting/redirect_to

Krótko mówiąc pod spodem wywołana zostanie metoda #url_for, która z kolei przedzierając się przez gąsz innych wywołań, skończy na wywołaniu czegoś w okolicach: @user.class.model_name.route_key albo singular_route_key, co dla modelu User, zwróci "users" lub "user", co prowadzi nas w końcu do helpera user_url.

Swoją drogą to jest jedna z najbardziej magicznych części railsów. Jest tyle różnych wyjątków, że metody w to zaangażowane są niezwykle skomplikowane (wystarczy pomyśleć o namespace’ach, albo ilości różnych argumentów jakie przyjmuje samo #url_for).