2011-07-12 11 views
20

Czy możliwe jest zresetowanie domyślnego układu z metody before_filter w Rails 3?Układ zestawów szyn z metody before_filter

Mam następujący jak mój contacts_controller.rb:

class ContactsController < ApplicationController 
    before_filter :admin_required, :only => [:index, :show] 
    def show 
    @contact = Contact.find(params[:id]) 
    respond_to do |format| 
     format.html # show.html.erb 
     format.xml { render :xml => @contact } 
    end 
    end 
    [...] 
end 

A po moim application_controller.rb

class ApplicationController < ActionController::Base 
    layout 'usual_layout' 
    private 
    def admin_required 
    if !authorized?   # please, ignore it. this is not important 
     redirect_to[...] 
     return false 
    else 
     layout 'admin' [???] # this is where I would like to define a new layout 
     return true 
    end 
    end 
end 

wiem, może po prostu umieścić ...

layout 'admin', :only => [:index, :show] 

... zaraz po "before_filter" w "ContactsController", ale, ponieważ mam już kilka innych kontrolerów z wieloma działaniami, które są poprawnie filtrowane jako wymagane przez administratora, byłoby znacznie łatwiej, gdybym mógł po prostu zresetować układ z "usual_layout" do "admin" w metodzie "admin_required".

BTW, umieszczając ...

layout 'admin' 

... wewnątrz "admin_required" (jak próbowałem w kodzie powyżej), otrzymuję komunikat o błędzie niezdefiniowanej metody. Wygląda na to, że działa tylko poza definicjami, tak jak robiłem to dla "usual_layout".

Z góry dziękuję.

Odpowiedz

68

Od Rails guides, 2.2.13.2 Choosing Layouts at Runtime:

class ProductsController < ApplicationController 
    layout :products_layout 

    private 

    def products_layout 
    @current_user.special? ? "special" : "products" 
    end 
end 
+0

Nie zapomnij zaakceptować poprawnych odpowiedzi, dzięki – apneadiving

+0

Dzięki apneadiving, ale nie jest to dokładnie to, co miałem na myśli. Mam już wcześniej poprawnie wykonaną metodę na kilku kontrolerach, filtrując te same akcje, które powinny być renderowane za pomocą tego specjalnego układu. Ale ta metoda jest wywoływana przez polecenie before_filter. Nie chcę zastępować każdego before_filter na każdym kontrolerze komendą layoutu, które wskazuje teraz na metodę z wewnątrz, dostanę poprawną nazwę układu - lub dodam ją mimo to. Muszę zdefiniować specjalny układ z tej samej metody, która została wcześniej wywołana przez polecenie before_filter. – guicassolato

+0

Cóż, postanowiłem zastosować się do sugestii nieprzyjaciela. Zajęło mi to trochę czasu, ale zastąpiłem każdy "before_filter: admin_required,: only => [...]" według "layout: admin_required,: only => [...]". Wszystko działało dobrze. Dzięki. – guicassolato

18

Jeśli z jakiegoś powodu nie możesz zmodyfikować istniejący sterownik i/lub po prostu chcesz zrobić to w przed filtrem można wykorzystać self.class.layout :special Oto przykład:

class ProductsController < ApplicationController 
    layout :products 
    before_filter :set_special_layout 

    private 

    def set_special_layout 
    self.class.layout :special if @current_user.special? 
    end 
end 

To tylko kolejny sposób, aby zrobić to samo. Więcej opcji dla szczęśliwszych programistów !!

+11

Ogromnym problemem, który wpadł mi z tą metodą, jest to, że układ zostaje zbuforowany przez Rails i dlatego może być stosowany nawet wtedy, gdy nie powinien. Bezpieczeństwo nici lub niektóre takie. Użyj sposobu 'layout: set_layout' i' def set_layout', o wiele bezpieczniej :) – sevenseacat

2

Nowoczesny sposób na osiągnięcie tego jest użycie proc,

layout proc { |controller| user.logged_in? "layout1" : "layout2" }