Rails: запутался в синтаксисе для передачи локальных объектов частичным


понимание рельсов "магия" в отношении рендеринга партиалов (и передачи в них местных жителей).

Почему это работает:

<%= render "rabbits/form" %>

и эту работу:

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

но это не работы:

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

а это:

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

кроме того, как я могу посмотреть эти нюансы, чтобы мне не нужно было беспокоить людей на S. O.?

4 96

4 ответа:

короткий ответ заключается в том, что метод render смотрит на первый аргумент, который вы передаете. Если вы передаете хэш (который включает :partial => 'foo', :locals => {blah blah blah}) затем он будет передавать все ваши аргументы в виде хэша и анализировать их соответственно.

если вы передаете строку в качестве первого аргумента, он предполагает, что первый аргумент является вашим частичным именем, а оставшаяся часть будет передана как ваши локальные. Однако в этом последующем вызове он фактически назначает :locals => your_locals_argument, который в данном случае является весь :locals => {locals hash}, вместо просто {locals hash}; т. е. вы в конечном итоге с :locals => {:locals => {locals hash}}, а не :locals => {locals hash}.

поэтому мой совет - просто всегда явно передавать значения одинаково все время, и у вас не будет проблем. Чтобы узнать об этом, я перешел непосредственно к самому коду (actionpack / lib / base.РБ,render() метод в рельсах 2; рельсы 3 отличается). Это хорошее упражнение.

кроме того, не беспокойтесь о том, чтобы "беспокоить" людей на SO. Вот почему этот сайт существует. Я даже научился что-то из этого.

Если вам нужно указать :местные жители, необходимо указать :частичное или :шаблон

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

должно работать

чтобы быть honost, я знаю только об этих случаях использования, потому что я не отставал от Rails в течение последних нескольких лет и читал объявления о том, что был добавлен новый способ сделать это. Я часто ошибаюсь в этом сам, но обычно это легко исправить.

Это одна из тех частей Rails API, которая не была тщательно продумана, если вы спросите меня. Он просто накапливал все больше и больше синтаксического сахара на протяжении многих лет, не осуждая ни одного из старых поведение. Метод рендеринга имеет диабет.

чтобы сделать его еще хуже, рендер ведет себя по-разному в контроллере и представлении. Я также смотрю на содержимое первого аргумента, чтобы увидеть, является ли он файлом, шаблоном, действием или частичным. Если он начинается с косой черты, то это файл или что-то в этом роде.

Я выступаю за использование более короткой нотации, когда это возможно. Потому что короткие обозначения действительно передают намерение довольно хорошо. Читая его, он обычно делает то, что вы думаете делает. Писать это не так просто.

вот источник метода рендеринга из 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

надеюсь, что это поможет!