I have models for User, Profile and Organisation Request. The associations are:
User
has_one :profile, dependent: :destroy
has_one :organisation_request, through: :profile
accepts_nested_attributes_for :organisation_request
Profile
belongs_to :user
belongs_to :organisation
Organisation Request
belongs_to :profile
# belongs_to :user#, through: :profile
belongs_to :organisation
In my user model, I have a method called full_name (which I use to format the presentation of a user's name.
I'm trying to access that full_name method in my organisation_requests model.
I'm trying to do that by writing the following method in my organisation requests model:
def related_user_name
self.profile.user.full_name
end
When I try to use this in my organisation requests index, like this:
<%= link_to orgReq.related_user_name, organisation_request.profile_path(organisation_request.profile.id) %>
I get an error that says:
undefined method `user' for nil:NilClass
When I try to use this idea in the rails console, with:
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"
The concept seems to work in the console? Can anyone see where I've gone wrong?
Don't chain methods, it's a bad practice, it violates the Law of Demeter . The best choice is to use the delegate
. So instead of:
def related_user_name
self.profile.user.full_name
end
You can have:
class OrganisationRequest
belongs_to :profile
has_one :user, through: :profile
delegate :full_name, to: :user, allow_nil: true, prefix: true
end
Then you can just call organisation_request.user_full_name
and it will go through profile > user and call full_name
(and you won't get undefined
since the allow_nil: true
will "cover" it)
More info about delegate here .
have you checked all of your organisation requests have profile? may be this is not best practice, try to use profile.try(:user).try(:full_name)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.