Railsy: mylą się co do składni przekazywania miejscowych do podrzędnych


99

Zrozumienie "magii" Railsów w odniesieniu do renderowania podrzędnych (i przekazywania do nich miejscowych).

Dlaczego to działa:

<%= render "rabbits/form" %>

A ta praca:

<%= render "rabbits/form", :parent => @warren, :flash => flash %>

ale to nie działa:

<%= render "rabbits/form", :locals => { :parent => @warren, :flash => flash } %>

Ale to robi:

<%= render :partial =>"rabbits/form", :locals => { :parent => @warren, :flash => flash } %>

Poza tym, jak mogę sprawdzić te niuanse, żeby nie przeszkadzać ludziom w SO?


3
W komentarzu poniżej powiedziałeś, że dokumenty rails api nie są tak przeszukiwalne. Zamiast tego powinieneś wypróbować tę stronę: apidock.com/rails . Zawiera również ruby ​​i rspec.
— ryeguy

Odpowiedzi:


152

Krótka odpowiedź jest taka, że ​​metoda render sprawdza pierwszy przekazany argument. Jeśli przekażesz hash (który zawiera :partial => 'foo', :locals => {blah blah blah}), przekaże wszystkie argumenty jako hash i odpowiednio je przeanalizuje.

Jeśli jako pierwszy argument przekażesz łańcuch, zakłada on, że pierwszy argument jest nazwą częściową, a pozostałą część przekaże jako lokalne. Jednak w tym kolejnym wywołaniu faktycznie przypisuje :locals => your_locals_argument, co w tym przypadku jest całością :locals => {locals hash}, a nie tylko {locals hash}; tzn. skończysz z :locals => {:locals => {locals hash}}, a nie :locals => {locals hash}.

Więc radzę po prostu zawsze jawnie przekazywać wartości w ten sam sposób przez cały czas, a nie będziesz mieć problemów. Aby się tego dowiedzieć, przeszedłem bezpośrednio do samego kodu ( actionpack / lib / base.rb , render()metoda w Railsach 2; Rails 3 jest inny). To dobre ćwiczenie.

Ponadto nie martw się, że „przeszkadzasz” ludziom w SO. Dlatego ta strona istnieje. Nawet się czegoś z tego nauczyłem.


5

jeśli chcesz określić: lokalne, musisz określić: częściowe lub: szablon

<%= render :partial => "rabbits/form", :locals => {...} %>

powinno działać


ma to związek ze sposobem, w jaki Ruby ocenia wartość skrótu, jeśli jesteś ciekawy w ten sposób.
— sethvargo

Rzeczywiście, działa ... tak jak określiłem w swoim pytaniu ... ale zastanawiam się, dlaczego? i gdzie jest to udokumentowane? tylko patrząc na źródło? A jeśli to jedyny sposób, aby znaleźć i zrozumieć te niezliczone niuanse w Railsach, to zastanawiam się, jak i gdzie mam znaleźć i zinterpretować to ze źródła. Nie mogę po prostu kliknąć „renderuj”, a następnie przejść do źródła (w każdym razie nie z TextMate), czy mogę?
— Meltemi

1
ach! więc faktycznie jesteś zainteresowany :). Tak, jedyny sposób, aby to rozgryźć, to a.) Mieć przeczucie tak jak ty i b.) Wyświetlić kod źródłowy. Nie mam jednak pojęcia, jak drążyć źródło ... przepraszam
— sethvargo

OK, będę gryźć ... jak ty patrzeć tego rodzaju rzeczy? czy po prostu przekopujesz się przez swoje clone https://github.com/rails/rails.git? Czy jest jakiś lepszy sposób? Przepraszam, ale jestem stosunkowo nowy w RoR i nie znalazłem jeszcze dobrego / łatwego / spójnego sposobu na przeglądanie dokumentacji Rails ... takiej, że jest . http://api.rubyonrails.org/nie jest łatwo przeszukiwać. a źródłem z git też nie jest ... westchnienie
— Meltemi

w żadnym wypadku nie jestem ekspertem, ale korzystam ze studia Aptana. Jest zbudowany na tej samej platformie co zaćmienie (jeśli znasz). Pozwala na „kliknięcie” i śledzenie, tak jak powiedziałeś. Możesz także wyszukiwać w kodzie i ma wbudowany terminal, itp. Uwaga - jest to całkiem duży plik
— sethvargo

2

Szczerze mówiąc, wiem tylko o tych przypadkach użycia, ponieważ nadążałem za Railsami przez ostatnie kilka lat i przeczytałem ogłoszenia, że ​​został dodany nowy sposób robienia tego. Często sam się w tym popełniam, ale zwykle łatwo to naprawić.

To jedna z tych części Rails API, które nie zostały dokładnie przemyślane, jeśli o mnie chodzi. Po prostu przez lata gromadził coraz więcej cukru syntaktycznego, nie umniejszając żadnego starego zachowania. Metoda renderowania ma cukrzycę.

Co gorsza, render zachowuje się inaczej w kontrolerze i widoku. Patrzę również na zawartość pierwszego argumentu, aby sprawdzić, czy jest to plik, szablon, akcja czy część. Jeśli zaczyna się od ukośnika, jest to plik lub coś w tym rodzaju.

Jestem zwolennikiem używania krótszej notacji, gdy tylko jest to możliwe. Ponieważ krótkie zapisy całkiem dobrze przekazują zamiar. Czytając go, zwykle robi to, o czym myślisz. Pisanie podszablonów nie jest proste.


1

Oto źródło metody renderowania z http://api.rubyonrails.org/classes/ActionView/Rendering.html#method-i-render :

def render(options = {}, locals = {}, &block)
  case options
  # Here is your last case
  when Hash
    if block_given?
      _render_partial(options.merge(:partial => options.delete(:layout)), &block)
    elsif options.key?(:partial)
      _render_partial(options)
    else
      template = _determine_template(options)
      lookup_context.freeze_formats(template.formats, true)
      _render_template(template, options[:layout], options)
    end
  when :update
    update_page(&block)
  else
    # here the first three cases
    _render_partial(:partial => options, :locals => locals)
  end
end

Mam nadzieję, że to pomoże!


To naprawdę pomaga , dzięki! Ale to mi nie pomaga ... jeśli wiesz, co mam na myśli ...
— Meltemi
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.