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

Понимание 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.?

Ответ 1

Короткий ответ - метод визуализации смотрит на первый аргумент, в который вы проходите. Если вы передадите хэш (который включает в себя :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.rb, render() в Rails 2, Rails 3 - другой). Это хорошее упражнение.

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

Ответ 2

если вам нужно указать: locals, вам нужно указать: partial или: template

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

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

Ответ 3

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

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

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

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

Ответ 4

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

Надеюсь на эту помощь!