Sarp Kaya
Sarp Kaya

Reputation: 3784

Elegant way to show corresponding text_field_tag value in Rails 4

So my problem is showing something that a model has in a nice and simpler way.

So what currently works?

In my viewer this works fine:

<%= text_field_tag(:first_name, (current_user.present? ? current_user : '').first_name.present? ? current_user.first_name : '') %> 

However this is too long and really hard to maintain, especially when I have several more fields.

So to avoid that I made this in my controller

def user_vals(value)
    if(current_user.present?)
      current_user.value.present? ? current_user.value : ''
    end
    return ''
  end

Within this controller I can call user_vals(:first_name) but get undefined methodvalue'` error. Furthermore I cannot just call

<%= text_field_tag(:first_name, @user_vals(:first_name)) %>

As I am getting some syntax error with brackets but that's not the real issue.

So my ultimate goal is to have something like this:

<%= text_field_tag(:first_name, @user_vals(:first_name)) %>

Rather than the first code I've given above. How can I achieve that?

Upvotes: 0

Views: 143

Answers (2)

pdobb
pdobb

Reputation: 18037

I would recommend to take a step back and try to use Duck Typing to solve this...

What you have right now is a current_user method. This method can return whatever object it wants if the user is not logged in, and that object can respond to whatever it wants. Here's a simplified example:

def current_user
  @user || OpenStruct.new(first_name: "")
end

Note: I'm assuming @user holds the currently-signed in user... but this may be a call to super instead, or whatever else depending on your implementation.

So now, instead of branching based on what type of object is coming back from the current_user method, you can now just use the returned object without regard.

current_user.first_name # => Either the User object's first name or `""`

You can go further with this by creating e.g. a GuestUser class and having GuestUser.new returned instead of the OpenStruct above. Guestuser would be a model that is not data-base backed and could respond to any number of methods as needed.

This idea has been represented by many others as well. And using a class to prevent repeated code switching based on nil actually has a name: The Special Case Pattern. As a quick, free example, see the Guest User RailsCast. Or, if you subscribe to Ruby Tapas, be sure to check out episode 112: Special Case. This topic, and many others, are also covered in depth in Avdi Grimm's excellent book: Confident Ruby, which I highly recommend.

Upvotes: 0

spickermann
spickermann

Reputation: 106782

You can use try in this case. Just write:

<%= text_field_tag(:first_name, current_user.try(:first_name)) %>

See: http://apidock.com/rails/Object/try

Upvotes: 1

Related Questions