user5715347
user5715347

Reputation:

Display issue with certain values in rails

I am having a problem:

<% @post.each do |post| %>
    <%=link_to post.title, post %>
    <p>Published
    <%= time_ago_in_words(post.created_at) %> ago by
    <%= post.user.user_name %></p>
<% end %>

The user name doesn't display it stays just blank in the webpage while if i type:

<%= post.user.email%>

It works the email displays. I don't understand why the user_name isn't showing up and for me it makes no sense. I am using the weBrick server for development if you need to now.

Upvotes: 0

Views: 40

Answers (1)

Richard Peck
Richard Peck

Reputation: 76774

It probably means you don't have user_name present in the associative user field, although if it was missing completely, it would normally throw an exception.

I'd say the record is blank or NULL in the db, hence it has no actual value when you output it.

The way to resolve is to make sure you're storing the value in your db. Rails has validations for this purpose:

#app/models/user.rb
class User < ActiveRecord::Base
   validates :user_name, presence: true
end

This will fire each time you create or update a user record, which means that when you send params like in your comments...

#<User id: 1, user_name: nil, full_name: nil, email: "[email protected]", password_digest: "$2a$10$wLxvI3RYjjIY2lmga0irU.Rlf0pwCM6/HlsgbI10eb1...", role: nil, created_at: "2015-12-25 09:39:37", updated_at: "2015-12-25 09:39:37">

... it will come back with an error that you cannot create the record because user_name is not present.


In situations like this, we use a method to fall back onto the email if the name doesn't exist:

#app/models/user.rb
class User < ActiveRecord::Base
   def user_name
       self[:user_name] || email
   end
end

This allows you to call @user.name and if they don't have it, it pulls the email instead.

This way, if you validate on having the email present, you'll be able to always return a value.

--

Another cool trick is delegate, which avoids the law of demeter (IE only have one point when calling attributes):

#app/models/post.rb
class Post < ActiveRecord::Base
   delegate :user_name, to: :user
end

This will allow you to call:

<%= post.user_name %>

... with it calling the user_name attribute from the User model.

Upvotes: 1

Related Questions