HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyrailsMinor

Tell, Don't Ask when dealing with displaying model attributes or a null replacement

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withnullaskdealingtelldisplayingattributeswhenmodeldon

Problem

I have the following model:

# == Schema Information
#
# Table name: clients
#
#  id         :integer          not null, primary key
#  first_name :string(255)
#  last_name  :string(255)
#  email      :string(255)
#

class Client < ActiveRecord::Base
  def full_name
    if first_name.blank? && last_name.blank?
      'Name: unknown'
    else
      first_name + ' ' + last_name
    end
  end

  def email_address
    email.blank? ? 'Email: unknown' : email
  end
end


Which has the following spec:

RSpec.describe Client, type: :model do

  describe 'full_name' do
    it 'should return first_name + last_name if not blank' do
      @client = create(:client, first_name: 'John', last_name: 'Doe')
      @client.full_name.should == 'John Doe'
    end

    it "should return 'Name: unkonwn' if name is blank" do
      @client = create(:client, first_name: '', last_name: '')
      @client.full_name.should == 'Name: unknown'
    end
  end

  describe 'email_address' do
    it 'should return email if email is not blank' do
      @client = create(:client, email: 'example@example.com')
      @client.email_address.should == 'example@example.com'
    end

    it "should return 'Email: unkonwn' if email is blank" do
      @client = create(:client, email: '')
      @client.email_address.should == 'Email: unknown'
    end
  end
end


As you can see I am creating methods (email_address, full_name) to display attributes (or a combination of attributes) in views. If the attribute is blank I want to return a string saying the value is unknown.

I have many more attributes that I would like to display this way, but it seems inefficient to come up with alternative method names for methods that simply return the attribute or the "blank alternative".

As an example, these are some of the other attributes: sex, age, source. Rather than calling client.sex or client.age I would create a method and call client.name_of_sex or client.age_string -- it starts to get awkward (I

Solution

Definitely, this does not belong in the model. The orthodox way is to create a helper. Note how you can use the pattern Object#presence:

module ApplicationHelper
  def show_field(field, value)
    value.presence || "#{field}: unknown"
  end
end


And use it in the views:



You can go a step further and use OOP view presenters if you like the idea (personally I don't use them).

Code Snippets

module ApplicationHelper
  def show_field(field, value)
    value.presence || "#{field}: unknown"
  end
end
<%= show_field("Name", user.full_name) %>

Context

StackExchange Code Review Q#73326, answer score: 3

Revisions (0)

No revisions yet.