6

Ich habe eine Rails-App mit einem Benutzermodell, das mehrere Rollen haben kann. Ich implementiert diese eine Bitmaske wie folgt aus:Nur bestimmte Werte in Rails zulassen Starke Parameter

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 

In der Anmeldeseite für die App, ich Benutzer auswählen möchten, wenn sie ein ‚Unternehmer‘ oder ein ‚Entwickler‘ sind. Ich möchte jedoch sicherstellen, dass sie sich selbst (oder anderen) keine andere Rolle zuweisen können, es sei denn, sie sind bereits Administrator.

Mein erster Gedanke war dies in der roles= Methode zu tun, indem sie changin wie

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 

jedoch zu sehen, wie ich herausgefunden habe, nicht current_user aus dem Inneren eines Modells zugreifen kann (was ich denke, macht Sinn, wenn Sie darüber nachdenken ...)

Mein nächster Versuch war zu sehen, ob ich dies mit Strong Parameters tun könnte.

Ich hatte erwartet, es in etwa so aussehen würde (ich bin mit ersinnen, das Überschreiben der 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 

Allerdings, wenn ich das versucht, ich habe dies: enter image description here , die mich, den ich denken lässt, Ich verstehe nicht, wie Strong Parameters wirklich funktioniert.

Ist es möglich, die Werte einzuschränken, die ein Benutzer für ein bestimmtes Feld basierend auf der Rolle des Benutzers mit Strong Parameters eingeben kann? Wenn nicht, gibt es einen anderen Weg, dies zu erreichen?

+0

Es sollte als Modellvalidierung definiert werden. Der starke Parameter dient zum Filtern von Parametern, nicht von Werten. – kengo

+0

@kengo - Wie kann ich es im Modell validieren, wenn ich nicht auf die Rolle aktueller Benutzer zugreifen kann? (da Admins möglicherweise andere Benutzer modifizieren, nicht nur sich selbst) – Ephraim

+0

Sie können starken Parameter nicht als before_action definieren. Verwenden Sie dies in create oder update-Methode. Account.new (account_update_params) – kengo

Antwort

6

Ich habe es herausgefunden, hier ist, wie ich es gemacht habe. (Dies ist die Methode überschreibt Devise des RegistrationController, wenn Sie nicht ersinnen verwenden, dann ersetzen Sie einfach, was Verfahren steuert, welche Parameter in einen neuen Benutzer eingegeben werden.)

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 

ich herausgefiltert nur die Parameter in Parameter [: Rollen], um nur Werte einzuschließen, die in User::DEFAULT_ROLES enthalten waren (oben in der Frage gezeigt), und dann das Objekt parameters zurückgegeben haben.

+0

Yup, params sind modifizierbar (du hast es sortiert, bevor ich dir antworten konnte) . – railsdog

Verwandte Themen