1

controller

@articles = current_user.articles

view

<% @articles.each do |article| %>
  <%= link_to "#{article.title} , #{article.author.name}" articles_path%>
<% end %>

Sometimes the article has no author, so is null in the database, which results in the following error

You have a nil object when you didn't expect it! The error occurred while evaluating nil.name

I still want to output the article title in this scenario, whats the best way to do this please?

7 Answers 7

4

Add a new instance method to your Article model.

class Article
  def title_and_author
    returning "" do |s|
      s << title
      s << ", " << author.name if author.name?
    end
  end
end

then in your view

<% @articles.each do |article| %>
  <%= link_to article.title_and_author, articles_path %>
<% end %>
Sign up to request clarification or add additional context in comments.

Comments

2

I suppose you could do something like this:

<% @articles.each do |article| %>
  <%= link_to (article.author ? "#{article.title} , #{article.author.name}" : article.title), articles_path %>
<% end %>

Using the short if/else form. If the author exist print the title and author, if not, print only the title.

Comments

2

There are the try method for that

<% @articles.each do |article| %>
  <%= link_to "#{article.title} , #{article.author.try(:name)}" articles_path%>
<% end %>

2 Comments

Cool, didn't know about the try method. This solution will print the comma even when it's not needed though...
2

Yet another solution:

<% @articles.each do |article| %>
  <%= link_to [article.title, article.author.try(:name)].reject{ |obj| obj.nil? }.join(', ') articles_path %>
<% end %>

You should probably have a helper if you find it too dirty.

Comments

1

If you are likely to come across this issue in a number of places within your application you may wish to modify the model class by adding one of the following methods

Modify the name attribute to return blank rather than nil

def name
  d = read_attribute(:name)
  d.nil? ? " " : d
end

Insert a blank instead of a null to the database

def before_save
  self.name = " " if self.name.nil?
end

Alternatively you could create a helper method that builds the link text based upon the existence of the name or not, like so

def link_text(title, name)
  if name.blank?
    title
  else
    "#{title} , #{name}"
end

Comments

1

I would go with creating a helper that wraps around link_to. Something like:

def link_to_article(article)
  if article.author.nil?
    link_to "#{article.title}", article_path(article)
  else
    link_to "#{article.title} , #{article.author.name}" article_path(path)
  end
end

# and in view simply do:
<%= link_to_article(article) %>

1 Comment

Those two link_to lines are almost identical. It hurts my eyes.
1

A 2020 solution using safe navigation could probably look something like this:

<%= link_to [article&.title, article&.author&.name].compact.join(",") articles_path %>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.