davegson
davegson

Reputation: 8331

store path in variable

In one of my helpers I have to differ if the user is on a profile or not. The helper returns an array full of URLs.

def get_options(profile)
  if profile
    url_arr = profile_infinite_path(user, ...)

    # .
    # .
    # do stuff with profile_infinite_path
  else
    url_arr = infinite_path(user, ...)

    # .
    # .
    # do same stuff with infinite_path
  end
end

I want to make this code more DRY, so my plan was to store the path as a variable and then simply calling all the remaining code only once.

def get_options(profile)
  if profile
    var_path = profile_infinite_path
  else
    var_path = infinite_path
  end

  url_arr = var_path(user, ...)

  # .
  # .
  # do stuff with var_path
end

I also tried storing the path as a method, but no luck there.

var_path = profile_infinite_path.method

Upvotes: 1

Views: 1058

Answers (3)

Coenwulf
Coenwulf

Reputation: 1937

In ruby you can assign the results of an if-else expression to a variable. This allows you to call the desired method and assign the results like so:

url_arr = if profile
  profile_infinite_path(user, ...)
else
  infinite_path(user, ...)
end

# .
# .
# do stuff with url_arr

Upvotes: 1

Rails Fan
Rails Fan

Reputation: 1144

Store only a symbol in your variable eg

var_path = :profile_infinite_path

Then you can do send(var_path, other_args) to get the real URL. Eg if you have users:

var_path = :user_path

send(var_path, 2) would return "/users/2"

Upvotes: 1

Zach Kemp
Zach Kemp

Reputation: 11904

You have two options here. Since path helpers are methods, and methods can be invoked without arguments simply by stating them, an assignment like path = profile_inifite_path gives the result of the method invocation.

You can defer invocation by using a symbol to refer to the method, and then sending it as a message when needed:

var_path = :profile_infinite_path
# ...
send(var_path, user, ...)

The symbol is the first argument to send, and it is followed by any arguments you would have given to the method.

The other way you could handle this is to wrap the method call in a proc and invoke it when needed:

var_path = ->(*args){ profile_infinite_path(*args) }
# ...
var_path.call(user, ...)

I tend to prefer send for situations like this.

Upvotes: 4

Related Questions