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?

Meltemi
źródło
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.

Doug R.
źródło
5

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

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

powinno działać

sethvargo
źródło
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.

iain
źródło
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!

Andrea Salicetti
źródło
To naprawdę pomaga , dzięki! Ale to mi nie pomaga ... jeśli wiesz, co mam na myśli ...
Meltemi