6

Mam aplikację szyn z modelem użytkownika, który może pełnić kilka ról. I to realizowane za pomocą bitową tak:Dopuszczanie tylko niektórych możliwych wartości w silnych parametrach Railsów

class User < ActiveRecord::Base 
    DEFAULT_ROLES = %w[developer entrepreneur] 
    ROLES = ['admin', 'entrepreneur', 'developer'] 

    def has_role?(role) 
    roles.include?(role.to_s) 
    end 

    def is?(role) 
    has_role?(role) 
    end 

    def roles=(roles) 
    self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.inject(0, :+) 
    end 

    def roles 
    ROLES.reject do |r| 
     ((roles_mask.to_i || 0) & 2**ROLES.index(r)).zero? 
    end 
    end 
end 

Na stronie Zapis na aplikacji, chcę użytkownikom zdecydować, czy są one „przedsiębiorca” lub „developer”. Jednak chcę się upewnić, że nie są w stanie przypisać sobie (ani nikomu innemu) żadnej innej roli, chyba że są już administratorem.

Moją pierwszą myślą było to zrobić w metodzie roles= przez changin to wyglądać

def roles=(roles) 
    unless current_user.is?(:admin) 
     validates_inclusion_of roles, :in => DEFAULT_ROLES 
    end 
    self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.inject(0, :+) 
    end 

Jednak, jak się dowiedziałem, nie można uzyskać dostępu current_user od wewnątrz modelu (co chyba marki Jeśli masz na to ochotę ...)

Moja następna próba polegała na sprawdzeniu, czy mogę to zrobić, używając Strong Parameters.

Spodziewałem się, że to wyglądać mniej więcej tak (używam opracowania, przesłanianie RegistrationsController)

class RegistrationsController < Devise::RegistrationsController 

    private 
    def sign_up_params 
    if (user_signed_in?) && (current_user.is?(:admin)) 
     params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, {roles: User::ROLES}) 
    else 
     params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, {roles: User::DEFAULT_ROLES}) 
    end 
    end 

    def account_update_params 
    if (user_signed_in?) && (current_user.is?(:admin)) 
     params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, :current_password, :about_me, {roles: User::ROLES}) 
    else 
     params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, :current_password) 
    end 
    end 
end 

Jednakże, gdy próbowałem, że mam to: enter image description here który sprawia, że ​​myślę I” nieporozumienie, jak naprawdę działają silne parametry.

Czy można ograniczyć, jakie wartości użytkownik może wprowadzić dla danego pola w oparciu o rolę tego użytkownika przy użyciu silnych parametrów? Jeśli nie, czy jest inny sposób, aby to osiągnąć?

+0

Należy zdefiniować jako sprawdzanie poprawności modelu. Silny parametr służy do filtrowania kluczy paramatycznych, a nie wartości. – kengo

+0

@kengo - Jak mogę sprawdzić to w modelu, jeśli nie mam dostępu do roli bieżącego użytkownika? (ponieważ administratorzy mogą modyfikować innych użytkowników, nie tylko samych siebie) – Ephraim

+0

Nie można zdefiniować silnego parametru jako wcześniejszego działania. Użyj tego w metodzie tworzenia lub aktualizacji. Account.new (account_update_params) – kengo

Odpowiedz

6

Zorientowałem się, oto jak to zrobiłem. (Jest to metoda zastępuje Devise na RegistrationController, jeśli nie używasz opracować, a następnie po prostu zastąpić cokolwiek sposób kontroluje jakie parametry są wprowadzane do nowego użytkownika.)

class RegistrationsController < Devise::RegistrationsController 

private 
    def sign_up_params 
    parameters = params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, :about_me, roles: []) 
    unless (user_signed_in?) && (current_user.is?(:admin)) 
     parameters[:roles] = parameters[:roles].reject { |h| !User::DEFAULT_ROLES.include? h } 
     parameters 
    end 
    end 


    def account_update_params 
    if can? :assign_roles, :all 
     params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, :current_password, :about_me, roles: []) 
    else 
     params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, :current_password) 
    end 
    end 

end 

Właśnie odfiltrowane parametr w parametrach [: role], aby uwzględnić tylko wartości zawarte w User::DEFAULT_ROLES (pokazane powyżej w pytaniu), a następnie zwróciło obiekt parameters.

+0

Tak, paramery są modyfikowalne (masz je posortowane zanim mogłem do ciebie wrócić) . – railsdog