Mel Mel - 6 days ago 5
Ruby Question

Rails - how to write a method that uses attributes from different models

I'm trying to figure out how to write a method in my user model, that shows the user's full name and the title of the organisation that the user is from, in one line.

In my user model, I have a method called full_name, which works to add the first name and last name attributes together. That part works.

Now, I'm trying to write a method called 'formal_title', which adds the user's full name to an organisation.title.

I have models for User and Organisation. The associations are:

User

belongs_to :organisation


Organisation

has_many :users


My organisation table has an attribute called :title.

My attempt at writing a method in my user model is:

def full_name
if first_name.present?
[*first_name.capitalize, last_name.capitalize].join(" ")
else
test_full_name
end
end

def organisation_title
Organisation.title.where(organisation.id == self.organisation_id).titleize
end

def formal_title
[*self.full_name, self.organisation_title].join(",")
end


When I try this, I get an error in the console that says:

NoMethodError: undefined method `formal_title' for #<User:0x007fea3495fe90>


This error message makes no sense to me because the user that I'm testing this on has a first name, last name and organisation id to test against. the organisation_id in the user table references an organisation that has a title, so I'm lost as to why any part of this method could be missing but also confused about what the console doesn't know about the method.

Can anyone see what I've done wrong?

Entire user model has:

class User < ApplicationRecord
rolify strict: true # strict means you get true only on a role that you manually add
attr_accessor :current_role


# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable,
:omniauthable, :omniauth_providers => [ :linkedin, :twitter, :orcid ]


# --------------- associations

belongs_to :organisation, optional: true

has_one :device
has_many :identities, dependent: :destroy
has_one :profile, dependent: :destroy
has_one :setting, dependent: :destroy
has_one :org_request, dependent: :destroy
has_many :proposals, dependent: :destroy

# Conversations
has_many :authored_conversations, class_name: 'Conversation', foreign_key: 'author_id'
has_many :received_conversations, class_name: 'Conversation', foreign_key: 'received_id'
has_many :personal_messages, dependent: :destroy
# End Conversations

# teams
has_many :teams, foreign_key: "team_mate_id"
has_many :team_projects, through: :teams, source: :proposal
has_many :received_invitations, :class_name => "TeamInvitation", :foreign_key => 'recipient_id'
has_many :sent_invitations, :class_name => "TeamInvitation", :foreign_key => 'sender_id'




# --------------- scopes

# --------------- validations

validates :first_name, presence: { message: 'First name cannot be blank.' }
validates :last_name, presence: { message: 'Last name cannot be blank.' }
validates :email, format: { with: EMAIL_REGEX }
validates :email, uniqueness: { message: 'This email is already associated with an account. Try logging in.'}

# validates_format_of :first_name, with: /a-zA-Z/
# validates_format_of :last_name, with: /a-zA-Z/
# validates_length_of :password, within: 8..128


# --------------- class methods

def full_name
if first_name.present?
[*first_name.capitalize, last_name.capitalize].join(" ")
else
"test_full_name"
end
end

def organisation_title
# you don't need to do `Organisation.where...` here because you have defined the `belongs_to` association for `:organisation`. So, it will directly give you the `Organisation` object.
organisation.title.titleize
end

def formal_title
[*self.full_name, self.organisation_title].join(",")
end
# --------------- instance methods
def online?
true
# false
# !Redis.new.get("user_#{self.id}_online").nil?
end



end

Answer

I save my changes each time. then I reload! in the console.

Not enough. You should either restart the console or re-query the user.

u = User.find(u.id)

reload! doesn't affect already loaded objects, so the user you had there, it won't see the new method.

Comments