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

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.