Райони макетів на дію?


165

Я використовую інший макет для деяких дій (переважно для нової дії в більшості контролерів).

Мені цікаво, який найкращий спосіб вказати макет? (Я використовую 3 або більше різних макетів в одному контролері)

Я не люблю використовувати

render: layout => 'ім'я'

Мені подобалося робити

макет "ім'я",: only => [: новий]

Але я не можу використовувати це для визначення двох або більше різних макетів.

Наприклад:

Коли я дзвоню макет 2 рази в один і той же контролер, з різними іменами макета і різними лише параметрами, перший ігнорується - ці дії не відображаються у вказаному нами макеті.

Примітка: я використовую Rails 2.


1
Документація по Rails Guides: guides.rubyonrails.org/…
Кевін

1
Гарна думка. Документація на Rails 2: guides.rubyonrails.org/v2.3.11/…
Кевін

2
(Крім того, я опублікував посібник, щоб допомогти майбутнім читачам. Я не сумніваюся, ви давно вирішили вашу проблему ;-)
Кевін

Відповіді:


297

Ви можете використовувати метод для встановлення макета.

class MyController < ApplicationController
  layout :resolve_layout

  # ...

  private

  def resolve_layout
    case action_name
    when "new", "create"
      "some_layout"
    when "index"
      "other_layout"
    else
      "application"
    end
  end
end

22
Класно, дякую. І якщо хтось захоче робити простіші речі з однокласником, можливе наступне. Його легко читати і розміщувати вгорі контролера. ---layout Proc.new{ ['index', 'new', 'create'].include?(action_name) ? 'some_layout' : 'other_layout' }
holli

1
Чи матиме це великий вплив на продуктивність програми, якщо різні макети використовують, скажімо, кілька різних файлів css & js відповідно?
Ноз

15
-1: Занадто складний. Коментар нижче ( stackoverflow.com/a/21203783/285154 ) - найкращий варіант.
dimitarvp

Дякую! Ця проблема все ще залишається в Rails 4.2, можливо, лише якщо ви використовуєте спадкові контролери на багатьох рівнях. Раніше я використовував метод, але не думав про тестування, коли у мене зараз була проблема, ще раз дякую.
244н.

@dimitko ні, це не так, я вже посилався на це рішення у самому питанні. Це не працює, якщо ви хочете використовувати 3 або більше різних макетів (як це точно в моєму випадку).
мрбрдо

201

Якщо ви вибираєте лише два макети, ви можете використовувати :only:

class ProductsController < ApplicationController
   layout "admin", only: [:new, :edit]
end

або

class ProductsController < ApplicationController
   layout "application", only: [:index]
end

2
Ну, проблема в тому, що ви не можете отримати доступ до таких об'єктів, як current_user, щоб умовно визначити макет
Andrew K

@AndrewK Динамічний вибір макета, здається, не є частиною заданого питання.
Нік

11
Якщо хтось із вас прочитав питання, ви б знали, що це не є правильною відповіддю, як я вже описав це рішення в самому запитанні, а також чому він не працює в моєму випадку (3 або більше макетів).
мрбрдо

2
Як сказав mrbrdo, це не відповідь. Його питання конкретно вказує (I am using 3 or more different layouts in the same controller). Ця відповідь дозволяє компонуватись, не макет, не різні макети.
Майкл

49

Ви можете вказати макет для окремої дії, використовуючи response_to :

  def foo
    @model = Bar.first
    respond_to do |format|
      format.html {render :layout => 'application'}
    end
  end

Для мене це більш гнучка відповідь. УСУШЕННЯ речей за допомогою застосування " layout "[...]" to the controller class only allows one statement effectively. If you have more than two layouts to deal with (say, admin, generic_app, tailored_app), you will experience Візуалізації" та / або переадресації було викликано кілька разів у помилках цієї дії; і у вас немає іншого вибору, як використовувати цю пропозицію.
Ієронім

1
Ця відповідь найкраща, її проста та акуратна, на відміну від використання методів з перемиканням або якщо твердження всередині.
kev

також він може вказати файл erb та макет як: format.html { render 'custom_index', layout: 'application' } однаково.
theway_3

12

Ви також можете вказати макет для дії, використовуючи візуалізацію:

def foo
  render layout: "application"
end


7

Різні способи вказати макет під контролером:

  1. У наступному коді макет програми_1 викликається під індексом, а показ дії контролера користувачів, а макет програми (макет за замовчуванням) викликається для інших дій.

    class UsersController < ApplicationController
      layout "application_1", only: [:index, :show]
    end
  2. У наступному коді макет програми_1 викликається для всіх дій контролера користувачів.

    class UsersController < ApplicationController
       layout "application_1"
    end
  3. У наступному коді макет програми_1 викликається лише для тестових дій контролерів користувачів, а для всіх інших макетів додатків дій (за замовчуванням).

        class UsersController < ApplicationController
          def test
            render layout: "application_1"
          end
        end

5

Точність:

Насправді, але робочий DRY спосіб - це те, що ви бачите вище, але з точністю: макет повинен відповідати вашим змінним для роботи ("@some"). Як:

def your_action
   @some = foo
   render layout: "your_layout"
end

І ні :

def your_action
   render layout: "your_layout"
   @some = foo
   @foo = some
end

Якщо ви робите перед запуском ... це також не буде працювати.

Сподіваюся, це допомагає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.