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.?


person Meltemi    schedule 09.12.2010    source источник
comment
В комментарии ниже вы говорили, что API-документы рельсов не доступны для поиска. Вместо этого вам следует попробовать этот сайт: apidock.com/rails. Там также есть ruby ​​и rspec.   -  person ryeguy    schedule 10.12.2010


Ответы (4)


Короткий ответ: метод рендеринга просматривает первый аргумент, который вы передаете. Если вы передаете хеш (который включает :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. Вот почему этот сайт существует. Я даже чему-то научился из этого.

person Doug R    schedule 09.12.2010

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

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

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

person sethvargo    schedule 09.12.2010
comment
это связано с тем, как ruby ​​оценивает хэш, если вам это интересно. - person sethvargo; 09.12.2010
comment
Действительно, это работает... как я указал в своем вопросе... но мне интересно, почему? и где это задокументировано? только глядя на источник? И если это единственный способ найти и понять все это множество нюансов в Rails, то мне интересно, как и где найти и интерпретировать это из источника. . Я не могу просто щелкнуть по рендерингу, а затем перейти к источнику (во всяком случае, не с TextMate), или я могу? - person Meltemi; 09.12.2010
comment
ах! так что вам действительно интересно :). Да, единственный способ разобраться в этих вещах: а.) догадаться, как вы, и б.) просмотреть исходный код. Я понятия не имею, как развернуть источник, хотя... извините - person sethvargo; 09.12.2010
comment
хорошо, я кусаю... как ты ищешь такие вещи? ты просто копаешься в своем clone https://github.com/rails/rails.git? или есть лучший способ? Извините, но я относительно новичок в RoR и еще не нашел хорошего/простого/согласованного способа поиска документации по Rails... такой, который ЕСТЬ есть. http://api.rubyonrails.org/ не легко доступен для поиска. и исходник из git тоже не тот... вздох - person Meltemi; 09.12.2010
comment
Я ни в коем случае не эксперт, но я использую студию Aptana. Он построен на той же платформе, что и eclipse (если вы знакомы). Это позволяет вам щелкать и отслеживать, как вы сказали. Вы также можете выполнять поиск в коде, и он имеет встроенный терминал и т. Д. Внимание - это довольно большой файл. - person sethvargo; 09.12.2010

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

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

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

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

person iain    schedule 09.12.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

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

person Andrea Salicetti    schedule 09.12.2010
comment
Это помогает, спасибо! Но это не помогает мне помочь самому себе... если вы понимаете, о чем я... - person Meltemi; 10.12.2010