3

I have a rails helper where I have two link_to's side by side. If the friendship status is requested. It only displays the second link. How do I format this so both links show?

def action_buttons(user)
    case current_user.friendship_status(user) when "friends"
        link_to "Cancel Friendship", friendship_path(current_user.friendship_relation(user)), method: :delete, class: "btn btn-primary btn-xs"
    when "pending"
        link_to "Cancel Request", friendship_path(current_user.friendship_relation(user)), method: :delete, class: "btn btn-primary btn-xs"
    when "requested"
        link_to "Accept", accept_friendship_path(current_user.friendship_relation(user)), method: :put, class: "btn btn-primary btn-xs"
        link_to "Decline", friendship_path(current_user.friendship_relation(user)), method: :delete, class: "btn btn-default btn-xs"
    when "not_friends"
        link_to "Add as Friend", friendships_path(user_id: user.id), method: :post, class: "btn btn-primary btn-xs"
    end
end

2 Answers 2

3

Concatenate the strings. The return value of the block will be the last line returned; you must concatenate the return values of the two link_to calls.

  def action_buttons(user)
    case current_user.friendship_status(user)
    # ...
    when "requested"
      link_to("Accept", ...) +
      link_to("Decline", ...)
      # ...
    end
  end
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! Deceptively simple solution. :)
1

The accepted answer is fine if it works for you particular situation, but it's not very robust. It's not DRY, because you're repeating link_to and the class attributes in a bunch of other places. It falls apart if you need to manipulate the result, such as adding any other markup. Like, say you wanted to make the links list items.

If you outgrow what it does for you, I might suggest having your helper return data that your template then uses:

def action_buttons(user)
    case current_user.friendship_status(user) when "friends"
        [
          { 
            label: "Cancel Friendship",
            path: friendship_path(current_user.friendship_relation(user)),
            form_attributes: { method: :delete }
          }
        ]
    when "pending"
        # likewise
    when "requested"
        [
          {
            label: "Accept",
            path: accept_friendship_path(current_user.friendship_relation(user)),
            form_attributes: { method: :put }
          }, {
            label: "Decline", 
            path: friendship_path(current_user.friendship_relation(user)),
            form_attributes: { method: :delete }
          }
        ]
    when "not_friends"
        # likewise
    end
end

And then in the template, you simply iterate over the arrays and pull the appropriate attributes out of the hash that is returned.

Alternatively, you could have your helper take a block, and then yield to that block:

def action_buttons(user)
    case current_user.friendship_status(user) when "friends"
        yield(link_to "Cancel Friendship", friendship_path(current_user.friendship_relation(user)), method: :delete, class: "btn btn-primary btn-xs")
    when "pending"
        yield(link_to "Cancel Request", friendship_path(current_user.friendship_relation(user)), method: :delete, class: "btn btn-primary btn-xs")
    when "requested"
        yield(link_to "Accept", accept_friendship_path(current_user.friendship_relation(user)), method: :put, class: "btn btn-primary btn-xs")
        yield(link_to "Decline", friendship_path(current_user.friendship_relation(user)), method: :delete, class: "btn btn-default btn-xs")
    when "not_friends"
        yield(link_to "Add as Friend", friendships_path(user_id: user.id), method: :post, class: "btn btn-primary btn-xs")
    end
end

In this way, the template just provides the operation to do to each link in a block. That block might just be { |link| link } if all you want is concatenation, but you could also have it wrap in tags or whatever. I'd still recommend factoring out the link_to so that it's less repetitive.

1 Comment

Thank you for your input. I've bookmarked this for future use. :)

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.