2016-03-21 6 views
1

Ich habe ein Projekt- und ein Beziehungsmodell, um eine "folgende" Beziehung zwischen einem Benutzer und einem Projekt herzustellen. Ich habe drei Rollen für die 'Beziehung' eingerichtet, die enum im Beziehungsmodell verwenden ... sie sind Admin, Kollaborateur und Besucher. Ich muss jedoch die Standardrolle basierend auf der Art und Weise festlegen, in der die Beziehung zwischen Benutzer und Projekt hergestellt wird. Die folgenden einfachen Szenarien benötigt:Festlegen der Standardrolle mit Enum basierend auf der Projekterstellung

(a) Ein Benutzer, der ein Projekt erstellt wird, automatisch das Projekt folgende ... soll die Beziehung Rolle ‚Admin‘ bei der Erstellung des Projektes festgelegt wird

(b) wenn ein Besucher auf die Website einfach auf eine Seite Projektprofil navigiert, können sie die auf ‚Follow‘ Schaltfläche, um eine folgende Beziehung aufzubauen ... aber dies sollte die Beziehung Rolle zu "Besucher

Relationship-Modell gesetzt:

class Relationship < ActiveRecord::Base 
    belongs_to :follower, class_name: "User" 
    belongs_to :followed, class_name: "Project" 
    validates :follower_id, presence: true 
    validates :followed_id, presence: true 

    enum role: [:admin, :collaborator, :visitor] 
    after_initialize :set_default_role, :if => :new_record? 

    def set_default_role 
    self.role ||= :admin 
    end 
end 

Re Hänge Controller:

class RelationshipsController < ApplicationController 
    before_filter :authenticate_user! 

    def create 
    @project = Project.find(params[:relationship][:followed_id]) 
    current_user.follow!(@project) 
    # relationship.visitor! View railsapps documentation for devise pundit#roles 
    redirect_to @project 
    end 

    def destroy 
    @project = Project.find(params[:id]).followed 
    current_user.unfollow!(@project) 
    redirect_to @project 
    end 

    private 

    def relationship_params 
    params.require(:relationship).permit(:followed_id, :follower_id) 
    end 

Projekte Controller-

class ProjectsController < ApplicationController 
    before_filter :authenticate_user!, only: [:create, :new, :edit, :update, :delete, :followers] 

def create 
    @project = current_user.own_projects.build(project_params) 
    if @project.save 
     if params[:project][:projectimage].present? 
     render :crop 
     else 
     flash[:success] = "You've successfully created a project..." 
     redirect_to @project 
     end 
    else 
     render 'new' 
    end 
    end 

    def update 
    @project = Project.find(params[:id]) 
    if @project.update_attributes(project_params) 
     if params[:project][:projectimage].present? 
     render :crop 
     else 
     flash[:success] = "Project Created" 
     redirect_to @project 
     @project.followers << current_user #this establishes the following relationship as soon as a new project is created between user/project 
     end 
    else 
     render 'edit' 
    end 
    end 

end 

Benutzermodell:

class User < ActiveRecord::Base 
    has_many :own_projects, :class_name=>'Project' 

    has_many :projects 
    has_many :relationships, foreign_key: "follower_id", dependent: :destroy 

    has_many :followed_projects, through: :relationships, source: :followed 
    # Include default devise modules. Others available are: 
    # :confirmable, :lockable, :timeoutable and :omniauthable 
    devise :database_authenticatable, :registerable, 
     :recoverable, :rememberable, :trackable, :validatable 

    def following?(some_project) 
    relationships.find_by_followed_id(some_project.id) 
    end 

    def follow!(some_project) 
    self.relationships.create!(followed_id: some_project.id) 
    relationship.visitor! 
    end 

end 

Was brauche ich in meinem Code ändern, um entweder 'admin' die Standardrolle festlegen oder "Besucher" basierend auf den beiden oben genannten Szenarien?

+1

Warum geben Sie beim Erstellen einer neuen Beziehung nicht einfach immer die 'Rolle' an? Warum sollte man sich mit dem Standardwert beschäftigen, wenn dieser unter anderen Bedingungen (außerhalb der Beziehung) anders ist? – BoraMa

+0

Wenn ich die after_initialize und die set_default_role wie erwähnt entfernt habe (und einfach die - enum role verlassen habe: [: admin,: collaborator,: visitor] ... wie würde ich diesen Beziehungsrollentyp von 'admin' für ein neues Projekt festlegen erschaffen werden?In der Erstellungsaktion des Projektcontrollers oder Beziehungscontrollers? thx – BB500

+1

Ja, das habe ich gemeint. Sie könnten die relevante Rolle im Wesentlichen überall dort festlegen, wo die Beziehung erstellt wird, z. in der Methode 'follow!' in 'User':' self.relationships.create! (folge_id: some_project.id, role:: visitor) 'oder in den Controllern. – BoraMa

Antwort

1

Wie in der obigen Ausführungen beschrieben, denke ich, dass Sie ausdrücklich role angeben sollen, wenn Ihre Relationship s erstellen, da die Rollen von den Bedingungen unterscheiden, die nicht inhärent auf die Relationship Klasse.

Jetzt, da die Relationship die Mittelsmann im has many :through Verbindung zwischen Ihren User und Project Modellen sind, können Sie einfach nicht den normalen Weg der Nutzer Projekte zur Verbindung verwenden << verwenden, aber müssen die Mittelsmann konstruieren Relationship explizit einschließlich Ihrem benutzerdefinierten Parameter (wie die Rolle).

class Project < ActiveRecord::Base 
    has_many :relationships, foreign_key: :followed_id, dependent: :destroy 
    has_many :users, through: :relationships 
end 

class User < ActiveRecord::Base 
    has_many :relationships, foreign_key: :follower_id, dependent: :destroy 
    has_many :projects, through: :relationships 

    # this will create the relationship association with the 'visitor' role 
    def follow_project!(some_project) 
    self.relationships.create!(followed_id: some_project.id, role: :visitor) 
    # I think you can even omit the ids here and work with objects: 
    # self.relationships.create!(followed: some_project, role: :visitor) 
    end 

    # this will create the relationship association with the 'admin' role 
    def administrate_project!(some_project) 
    self.relationships.create!(followed: some_project, role: :admin) 
    end 

    # this will create the relationship association with the 'collaborator' role 
    def collaborate_on_project!(some_project) 
    self.relationships.create!(followed: some_project, role: :collaborator) 
    end 
end 

class Relationship < ActiveRecord::Base 
    belongs_to :follower, class_name: "User" 
    belongs_to :followed, class_name: "Project" 

    enum role: [:admin, :collaborator, :visitor] 
end 

Die follow_, administrate_ und collaborate_on_project! Methoden funktionieren auf die gleiche Art und Weise aber jeweils Sätze unterschiedliche Rolle in der Beziehung:

Ihre Lösung sollte auf die einem posted here analogical sein. Dann können Sie rufen Sie einfach an den entsprechenden eine von der Steuerung, zum Beispiel der ‚admin‘ Beziehung zu setzen, wenn ein Projekt erstellen:

class ProjectsController < ApplicationController 

    def create   
    # ideally you should wrap multiple separate saves in a transaction so that 
    # either they all succeed or all fail 
    Project.transaction do 
     # this creates a barebone project, without any association 
     @project = Project.create!(project_params) 
     # this associates the project to the current user with admin role 
     current_user.administrate_project!(@project) 
     # ...     
    end 
    end 

end 

Bitte auch sicher rails guides auf das lesen: durch Verbände sorgfältig.

+0

Vielen Dank Bora für Ihre Hilfe. – BB500