0

Consider this helper method:

module SomeHelper

  def display_button
    Foo.find_by_id params[:id] and Foo.find(params[:id]).organizer.name != current_name and Foo.find(params[:id]).friends.find_by_name current_name
  end

end

How to refactor into something more readable?

Rails 3.2.2

4
  • is this supposed to be boolean? Commented Sep 6, 2012 at 14:46
  • Yes, it is boolean. I should have added that to the question. Commented Sep 6, 2012 at 14:56
  • 4
    Please note that and/or is not the same as &&/|| in Ruby. Commented Sep 6, 2012 at 14:57
  • @AndrewMarshall - Actually, that was causing a problem. I want the and/&& to be evaluated last. and is lower precedence. techotopia.com/index.php/Ruby_Operator_Precedence Commented Sep 6, 2012 at 15:00

3 Answers 3

4

Something like this?

module SomeHelper

  def display_button?
    if foo = Foo.find(params[:id])
      foo.organizer.name != current_name if foo.friends.find_by_name(current_name)
    end
  end

end

Note: if the helper method is returning a boolean, I would append the name with a ? ... ruby convention.

Sign up to request clarification or add additional context in comments.

Comments

2

You can factorize the call to Foo.find(params[:id]) and use exists? for the third condition

module SomeHelper
  def display_button
    foo = foo.find_by_id params[:id]
    foo and foo.organizer.name != current_name and foo.friends.where(:name => current_name).exists?
  end
end

You can also create several methods to gain on reusability (and will save trouble if you model changes):

module SomeHelper
  def display_button
    foo = foo.find_by_id params[:id]
    foo && !is_organizer?(foo, current_name) && has_friend?(foo, current_name)
  end

  def is_organizer?(foo, name)
    foo.organizer.name == name
  end 

  def has_friend?(foo, name)
    foo.friends.where(:name => name).exists?
  end
end

1 Comment

Breaking into multiple methods is really the key to refactoring the original method, which was doing too much.
1

try invokes the passed block on non-nil objects. Returns nil otherwise. So the return will be nil,true,false depending on your data.

def display_button
    Foo.find_by_id(params[:id]).try do |foo|
       foo.organizer.name != current_name && 
         foo.friends.find_by_name current_name
    end
  end

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.