Rails: запутался в синтаксисе для передачи локальных данных частям - PullRequest
97 голосов
/ 09 декабря 2010

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

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

<%= 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 } %>

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

Ответы [ 4 ]

151 голосов
/ 09 декабря 2010

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

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

5 голосов
/ 09 декабря 2010

если вам нужно указать: localals, вам нужно указать: частичный или: template

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

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

2 голосов
/ 10 декабря 2010

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

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

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

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

1 голос
/ 09 декабря 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...