2016-08-02 28 views
0

Ich habe Modelle für Benutzer, Profil und Organisationsanforderung. Die Verbände sind:Rails 4 - Verkettung von Modellverknüpfungen für den Zugriff auf zugehörige Methoden

Benutzer

has_one :profile, dependent: :destroy 
has_one :organisation_request, through: :profile 
    accepts_nested_attributes_for :organisation_request 

Profil

belongs_to :user 
belongs_to :organisation 

Organisation anfordern

belongs_to :profile 
# belongs_to :user#, through: :profile 
belongs_to :organisation 

In meinem Benutzermodell habe ich eine Methode namens full_name (die ich Format verwenden die Darstellung eines Benutzernamens

Ich versuche in meinem organisation_requests-Modell auf diese full_name-Methode zuzugreifen.

Ich versuche, das zu tun, indem Sie die folgende Methode in meiner Organisation Schreiben fordert Modell:

def related_user_name 
    self.profile.user.full_name 
end 

Wenn ich versuche, dieser Index fordert in meiner Organisation zu verwenden, wie folgt aus:

  <%= link_to orgReq.related_user_name, organisation_request.profile_path(organisation_request.profile.id) %> 

ich erhalte eine Fehlermeldung, die besagt:

undefined method `user' for nil:NilClass 

Wenn ich versuche, diese Idee in den Schienen Zusammenarbeit zu nutzen nsole, mit:

o = OrganisationRequest.last 

    OrganisationRequest Load (0.4ms) SELECT "organisation_requests".* FROM "organisation_requests" ORDER BY "organisation_requests"."id" DESC LIMIT 1 
=> #<OrganisationRequest id: 2, profile_id: 1, organisation_id: 1, created_at: "2016-08-01 22:48:52", updated_at: "2016-08-01 22:48:52"> 
2.3.0p0 :016 > o.profile.user.formal_name 
    Profile Load (0.5ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."id" = $1 LIMIT 1 [["id", 1]] 
    User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 1]] 
=> " John Test" 

Das Konzept scheint in der Konsole zu funktionieren? Kann jemand sehen, wo ich falsch gelaufen bin?

Antwort

1

Nicht Kettenmethoden, es ist eine schlechte Praxis, es verletzt die Law of Demeter. Die beste Wahl ist die delegate. Also statt:

def related_user_name 
    self.profile.user.full_name 
end 

können Sie haben:

class OrganisationRequest 
    belongs_to :profile 
    has_one :user, through: :profile 

    delegate :full_name, to: :user, allow_nil: true, prefix: true 
end 

Dann können Sie einfach organisation_request.user_full_name anrufen und es geht durch Profil> Benutzer und rufen full_name (und Sie werden nicht undefined erhalten, da die allow_nil: true wird es "bedecken")

Weitere Informationen über delegate here.

+0

Ich habe das versucht, aber ich bekomme eine Fehlermeldung (auf den Delegaten zeigen Zeile), die besagt: undefinierte lokale Variable oder Methode 'user 'für # Mel

+0

Sie können delegieren: full_name an: user, prefix: true, allow_nil: true in' Profile' und 'delegate: user_full_name, to :: profile, prefix: false, allow_nil: true' in OrganizationRequest. – dpedoneze

-1

Haben Sie alle Ihre Organisationsanfragen Profil haben überprüft? möglicherweise ist dies keine Best Practice, versuchen Sie zu verwenden

+0

Wie gesagt, Kettenmethoden wie diese sind eine schlechte Übung, die beste Wahl ist immer nur einen Aufruf wie: 'method.call_another' :) – dpedoneze