Переменные экземпляра в макете - PullRequest
7 голосов
/ 03 декабря 2009

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

У меня есть модель Menuitem, которую я хотел бы отобразить в макете. Как можно передать переменную экземпляра в макет?

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

Спасибо!

Ответы [ 5 ]

15 голосов
/ 04 декабря 2009

Обычным способом передачи переменных из представления в родительский макет является использование метода content_for. (Этот ответ является копией + вставкой из аналогичного ответа, который я разместил на этот вопрос )

Содержимое обычного представления автоматически отображается в вызове yield без аргумента в макете. Но вы также можете поместить другое содержимое-заполнитель, используя yield с аргументом символа и указав это содержимое из представления с помощью content_for.

app/views/layouts/posts_layout.html.erb

<html>
  <head>
    <title>My awesome site</title>
  </head>
  <body>
    <div id="someMenuStructureHere">
      <%= yield(:menu_items) %> <!-- display content passed from view for menu_items -->
    </div>
    <%= yield %> <!-- display main view content -->
  </body>
</html>

app/views/posts/index.html.erb

<%= content_for :menu_items, some_helper_to_generate_menu %>
<h1>Here is you page content</h1>
3 голосов
/ 03 декабря 2009

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

def MenuItem.all_for_menu
  @@all_for_menu ||= MenuItem.find(:all)  #returns value if exists, or initializes it
end 

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

Другим подходом кэширования было бы поместить данные в частичную часть и кэшировать этот фрагмент, используя стандартный вызов кэширования:

<% cache(:controller => "menu_items",
         :action => "list", 
         :action_suffix => "all_menu_items") do %>
  <%= render :partial => "menu", :collection => MenuItem.all_for_menu %>
<% end %>

Вы можете истечь этот фрагмент, вызвав:

expire_fragment(:controller => "menu_items", :action => "list", :action_suffix => "all_menu_items")
0 голосов
/ 03 декабря 2009

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

В контроллере:

# Use whatever action you are currently displaying
def index 
  @menu_items = MenuItem.all
end

В файле просмотра index.html.erb:

<ul id="menu">
<% @menu_items.each do |menu_item| %>
   <%= h menu_item.name %>
<% end %>
</ul>

Очевидно, что если бы это было реальное меню, там тоже были бы гиперссылки:)

0 голосов
/ 03 декабря 2009

items_controller.rb (или что-то)

def show
   @menu_item = MenuItem.find(params[:id])
end

В представлении show.html.erb:

<%= @menu_item.name %>
0 голосов
/ 03 декабря 2009

Любые переменные экземпляра, определенные в контроллерах, автоматически доступны в ваших представлениях. Если вы ожидаете переменную экземпляра в макете для всех действий, вы можете рассмотреть определение переменной экземпляра в before_filter или ее инкапсуляцию в методе контроллера и использование helper_method , чтобы сделать ее доступной в ваших представлениях.

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