The buzz cut

Ramblings from the barbershop

Finding Available OmniAuth Providers

| Comments

I’m working on a project that uses OmniAuth to connect a user’s account to LinkedIn, Twitter, and Google Plus. Easy enough, right? On one screen in my app, I needed to display the services that a user had already connected, and the ones that were still available to connect.

The former is easy:

1
<%= render current_user.services %>

But what about displaying services that the user hadn’t connected yet? I didn’t want to store a constant of available providers, as that’d just be one more place I’d have to edit when adding a new provider. So, I dug around a bit and found this:

1
OmniAuth::Strategies.constants

That returns an array of providers, with one caveat: it adds Developer, OAuth2, and Oauth to the list by default. I didn’t want those exposed to the end user, so I added a method in my Service.rb class:

1
2
3
def self.available_providers
  OmniAuth::Strategies.constants.reject {|item| item =~ /Developer|OAuth2|Oauth/i }
end

Then, to display the services that the user hadn’t connected yet, I used:

1
2
3
4
5
Service.available_providers.each do |service|
  unless current_user.services.pluck(:provider).include?(service)
    ...
  end
end

This works great, but it doesn’t feel 100% right. Any suggestions on how to do it better?

Update

Matt Brand reminded me that you can subtract arrays in ruby. While looking at that part of the code, I realized I’d sinned and had this current_user.services.pluck(:provider) logic within the loop. While rails would’ve cached that query, it’s still bad form. I started to rewrite that block with:

1
2
3
(Service.available_providers - current_user.services.pluck(:provider)).each do |service| %>
  ...
end

But that’s just too much logic for an erb, so I added a method to my User.rb model:

1
2
3
  def remaining_services
    Service.available_providers - services.pluck(:provider)
  end

And now my code for displaying the available services looks like this:

1
2
3
current_user.remaining_services.each do |service|
  ...
end

Now, I just need someone to recommend a better way to get available providers from OmniAuth, as OmniAuth::Strategies.constants still feels wrong.

Comments