Ograniczenie dostępu do akcji kontrolera + dziedziczenie

Mamy zwierzęta, które dzielą się drapieżniki(predators), wszystkożerne(scavengers) i roślinożerne(herbivorous). I tych grup jest pewnie jeszcze kilka.
AnimalsController służy do tworzenia nowych zwierząt, i zarządzania nimi (zwykły crud)dziedziczą po nim PredatorsController, ScavengersController i HerbivorousController. Zmienna @habitat jest gdzieś poprawnie inicjalizowana. Chodzi o to, że na akcje new i create chcemy założyć następujące zabezpieczenie:

  1. Jeśli ktoś dopiero wchodzi na tą stronę, to ma otrzymać komunikat: brak dostępu.
  2. Jeśli ktoś jest na tej stronie, jest tam javascript, który ją przeładowuje z parametrem new_offer. W międzyczasie mógł się skończyć okres lęgowy danego zwierzęcia. Chcemy wtedy zmienić parę rzeczy na stronie i wyświetlić dodatkowo flash, że termin godowy minął.

Kod poniżej działa zgodnie z założeniami, ale przykro mi się robi, jak na niego patrzę.

[code=Ruby]class AnimalsController < ApplicationController
before_filter :check_auth

crud actions

def check_auth
return true if request.path_parameters[:action] != “new” and request.path_parameters[:action] != “create”
if params[:new_animal]
handle_new_animal_page
else
check_status ? true : (raise Authorization::PermissionDenied.new( “brak dostępu” ))
end
end

def check_status
return true if request.path_parameters[:controller] == ‘predators’ and @habitat.can_predators_reproduce?
return true if request.path_parameters[:controller] == ‘scavengers’ and @habitat.can_scavengers_reproduce?
return true if request.path_parameters[:controller] == ‘herbivorous’ and @habitat.can_herbivorous_reproduce?
return false
end

def handle_new_animal_page
unless check_status
flash.now[:error] = “minął termin godowy dla tego zwierzęcia”
params[:change_buttons] = true
end
true
end[/code]

Po pierwsze możemy ograniczyć metodę check_auth tylko do akcji new i create. Po drugie check_status w kontrolerze Animals niech zwraca fałsz, a w każdym z dziedziczących kontrolerów będzie sprawdzany konkretny warunek.

[code=Ruby]class AnimalsController < ApplicationController
before_filter :check_auth, :only => [:new, :create]

crud actions

def check_auth
if params[:new_animal]
handle_new_animal_page
else
check_status ? true : (raise Authorization::PermissionDenied.new( “brak dostępu” ))
end
end

def check_status
false
end

def handle_new_animal_page
unless check_status
flash.now[:error] = “minął termin godowy dla tego zwierzęcia”
params[:change_buttons] = true
end
true
end
end

class PredatorsController < AnimalsController
def check_status
@habitat.can_predators_reproduce?
end
end

class ScavengersController < AnimalsController
def check_status
@habitat.can_scavengers_reproduce?
end
end

class HerbivorousController < AnimalsController
def check_status
@habitat.can_herbivorous_reproduce?
end
end[/code]
Jak się tak napisze problem na forum, to odpowiedzi same się nasuwaję. :slight_smile: Jeszcze pewnie można poprawić metody handle_new_animal_page i check_auth.

A to jest grubsza sprawa niż myślisz. Nie tylko jak się napisze na forum pytanie to zaraz sam znajdziesz odpowiedź, to ma miejsce również gdy chcesz komuś zadać pytanie. Dlatego uważam że praca w biurze w jednym zespole jest nie do przecenienia. Ileż razy zdarzyło mi się zapytać kogoś “jak byś to zrobił” albo nawet pomyśleć o zadaniu pytania i odpowiedź się nasuwa sama… Ktoś wie jak się to nazywa? Ma ten syndrom jakąś nazwę?

[code]class AnimalsController < ApplicationController
before_filter :check_auth, :except => [:new, :create]

def check_auth
if check_status
true
else
if params[:new_animal]
flash.now[:error] = “minął termin godowy dla tego zwierzęcia”
params[:change_buttons] = true
else
raise Authorization::PermissionDenied.new( “brak dostępu” )
end
end
end

def check_status
case(controller.name)
when ‘predators’
@habitat.can_predators_reproduce?
when ‘scavengers’
@habitat.can_scavengers_reproduce?
when ‘herbivorous’
@habitat.can_herbivorous_reproduce?
else
false
end
end
end[/code]
Tylko widze mały problem z handle_new_animal, metoda sprawdza status ale bez wzgledu na jego stan zwraca zawsze true. Nie wiem czy to ma sens. Pozatym nie mam na czym testowac wiec to kod czysto hipotetyczny :wink:

Heh nie spojrzałem na kod wcześniejszy. W każdym bądź razie wydaje mi się że możesz jeszcze uprościć handle_new_animal.

Pracując w domu gada się do kaczki :wink: http://c2.com/cgi/wiki?RubberDucking