Dlaczego akcje „zorientowane na zakres” (szczególnie akcje „indeksowe”) są traktowane inaczej w Pundit?
Piszę w odniesieniu dohttps://github.com/elabs/pundit#scopes
Jestem pod wrażeniem, żeupoważnienie powinien odpowiedzieć na pytanieCzy masz dostęp do tego zasobu?, tj. atrue
/false
odpowiedź. Dotyczy to wszystkich akcji z wyjątkiemindex
, co według doktorów Pundita powinno powrócić inaczejActiveRecord::Relation
zależy od tego, kto pyta. Na przykład anAdministrator dostajescope.all
, podczaszwykły użytkownik dostajescope.where(:published => true)
.
app / policy / post_policy.rb
class Scope < Struct.new(:user, :scope)
def resolve
if user.admin?
scope.all
else
scope.where(:published => true)
end
end
end
app / controllers / posts_controller.rb
def index
@posts = policy_scope(Post)
end
Moja rezerwacja jest taka, że jest to śliskie zbocze i wkrótce dodam prezentację do zakresów (np.scope.all.order('created_at ASC')
) - i po prostu czuję się dziwnie robiąc topolityka autoryzacji.
Oczywiście, mogę przenieść to do kontrolera ...
def index
@post = policy_scope(post)
if user.admin?
@post = @post.order( 'created_at ASC' )
end
end
... ale czy to jest zadanie kontrolera? I nie sądzę, by słusznie było dodać takie wezwanie do widoku. Więc może to powinna być metoda modelowa?
Co powiesz na plusy / minusy robienia następujących rzeczy?
app / controllers / posts_controller.rb
To utrzymujeindex
tak jak inne metody, z jednym wywołaniemauthorize
i jedno wywołanie metody modelowej.
def index
authorize(Post)
@posts = Post.index(current_user)
end
app / policy / post_policy.rb
To po prostu daje prawdziwą / fałszywą odpowiedź. Czy masz autoryzację? Tak lub nie.
def index?
user.admin? || user.regular_user?
end
app / models / post.rb
A w modelu możemy uzyskać tak fantazyjne, jak nam się podoba.
def self.index(user)
if user.admin?
Post.all.order('created_at ASC')
else
Post.where(user_id: user.id)
end
end
Myśli?