2012 in review – Tech Muffins & Musings Smoothie

The WordPress.com stats helper monkeys prepared a 2012 annual report for this blog.

Here’s an excerpt:

600 people reached the top of Mt. Everest in 2012. This blog got about 6,900 views in 2012. If every person who reached the top of Mt. Everest viewed this blog, it would have taken 12 years to get that many views.

Click here to see the complete report.

Compressing and Uncompressing Data in Android/Java Using Zlib

Compressing and Uncompressing Data in Android/Java Using Zlib

This Could Be Better

The Zlib data compression library is built into Java, and allows you to compress and decompress data. So, uh… ’nuff said?

1. If you have not already done so, download and install the Java Development Kit. Details are given in a previous tutorial. Make a note of the directory to which the files “javac.exe” and “java.exe” are installed.

2. In any convenient location, create a new directory named “CompressionTest”.

3. In the newly created CompressionTest directory, create a new text file named “CompressionTest.java”, containing the following text.

import java.io.*; import java.util.*; import java.util.zip.*; public class CompressionTest { public static void main(String[] args) { Compressor compressor = new Compressor(); String stringToCompress = "This is a test!"; //String stringToCompress = "When in the course of human events, it becomes necessary for one people to dissolve the bands that bind them..."; System.out.println("stringToCompress is: '" + stringToCompress + "'"); byte[] bytesCompressed = compressor.compress(stringToCompress); System.out.println("bytesCompressed…

View original post 713 more words

How to Override Android’s Back Key When Soft Keyboard is Open

There are various scenarios where we need to handle the Android powered handsets’ hardware “back” key to do some important stuff. One scenario that’s very common is to use it on your custom search view where pressing back key only leads to hide the keyboard and user has to tap it again to hide the search view.

Let’s consider this:

Here we have a search view with keyboard open. If user wants to cancel searching and go back, he can press the back key and here is what we get on back key press:

You can see that the keyboard has gone but the search view is still there. User has to press the back key another time to navigate back to original activity.

Apparently, there is no method in your activity which listens to hardware key events when software keyboard is open. onKeyDown() and onKeyUp() methods work only when keyboard is hidden and this happen because Android considers on-screen keyboard as a separate activity and behaves accordingly.

So what should one do to override it?

Answer is simple and the easiest way to do is to override onKeyPreIme() method which is inherited from View class. To override it, you need to create a custom view. we’ll do it With minimum of the effort. For the example above, we have an EditText which we have using for searching.

Now create a new class which extends from EditText class. Override all the constructors to avoid any possible app crash. Now we’ll override the onKeyPreIme() method and check for Back key:

@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        // User has pressed Back key. So hide the keyboard
        InputMethodManager mgr = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        mgr.hideSoftInputFromWindow(this.getWindowToken(), 0);
        // TODO: Hide your view as you do it in your activity
    }
    return false;
}

Replace your EditText with this brand new class and that’s all. Now whenever the soft keyboard is hidden through back key, you’ll be notified and you can do the required code to get things work your way.

Bonus Trick:

Here’s a bonus trick for you. If you have implemented menus in your activity, you might face a problem like this:

If you press menu key when the keyboard is opened, you ‘ll have your menus over the keyboard. Now isn’t that funny? But don’t worry, we don’t have to worry about this. What do we want here is that menus should not become visible when keyboard is opened. Piece of cake!! Update your above code to this:

@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        // User has pressed Back key. So hide the keyboard
        InputMethodManager mgr = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        mgr.hideSoftInputFromWindow(this.getWindowToken(), 0);
        // TODO: Hide your view as you do it in your activity
    } else if (keyCode == KeyEvent.KEYCODE_MENU) {
        // Eat the event
        return true;
    }
    return false;
}

And here you go!! Menus won’t show up on pressing menu key when the keyboard is visible.
Please share the post if you liked.

Creating an Alternate-Colored List View in Android

This post will help you make a list with alternate row in different colors. This is What your list will look like:

To accomplish this, first of all create a layout file and add a listview in it. We name this file “categories.xml“:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/RelativeLayout1">
    <ListView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/listView1" />
</RelativeLayout>

Next, you need to create an activity. Let’s name this file “CategoriesActivity.java” and enter following code in oncreate() method:

setContentView(R.layout.categories);
ListView listView = (ListView) findViewById(R.id.listView1);
listView.setAdapter(new CategoriesListAdapter(this));

Next step it to create create a custom adapter for our list. In our code above, we’ve named it CategoriesListAdapter. Extend this class from BaseAdapter and implement the methods as usual.

Now, in CategoriesListAdapter.java, we’ll first declare and initialize a list of colors:

public class CategoriesListAdapter extends BaseAdapter {
    private final int[] bgColors = new int[] { R.color.list_bg_1, R.color.list_bg_2 };
}

You have to define these colors in an xml file e.g., colors.xml under res/color. Alternatively, you can use Android’s built-in colors like Color.YELLOW or Color.BLUE for which you don’t need to define these colors. But if you select the first method, your colors.xml will look like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="list_bg_1">#ffffff</color>
    <color name="list_bg_2">#fef2e8</color>
</resources>

Now the last step is to set these colors in getView() method. Use the following code snippet for this:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.item_categorylist, null);
        holder = new CategoryContentsHolder();
        holder.title = (TextView) convertView.findViewById(R.id.txtCategoryName);
        convertView.setTag(holder);
    } else
        holder = (CategoryContentsHolder) convertView.getTag();
        int colorPosition = position % bgColors.length;
        convertView.setBackgroundResource(bgColors[colorPosition]);
        if (holder != null) {
            holder.name.setText(categoryStringArray[position]);
        }
        return convertView;
    }
}

class CategoryContentsHolder {
    TextView title;
}

That was all! The same way you can create a list with 3 or more color.

A Beginner’s Guide to Design Patterns with Java Examples

Ever wondered what design patterns are? In this article, I’ll explain why design patterns are important, and will provide some examples, in Java, of when and why they should be used.

What are Design Patterns?

Design patterns are optimized, reusable solutions to the programming problems that we encounter every day. A design pattern is not a class or a library that we can simply plug into our system; it’s much more than that. It is a template that has to be implemented in the correct situation. It’s not language-specific either. A good design pattern should be implementable in most—if not all—languages, depending on the capabilities of the language. Most importantly, any design pattern can be a double-edged sword— if implemented in the wrong place, it can be disastrous and create many problems for you. However, implemented in the right place, at the right time, it can be your savior.

There are three basic kinds of design patterns:

  • Structural
  • Creational
  • Behavioral

Structural patterns generally deal with relationships between entities, making it easier for these entities to work together.

Creational patterns provide instantiation mechanisms, making it easier to create objects in a way that suits the situation.

Behavioral patterns are used in communications between entities and make it easier and more flexible for these entities to communicate.

Why should we use them?

Design patterns are, by principle, well-thought out solutions to programming problems. Many programmers have encountered these problems before, and have used these ‘solutions’ to remedy them. If you encounter these problems, why recreate a solution when you can use an already proven answer?

Example

class StrategyExample {
    public static void main(String[] args) {
        Context context;

        // Two contexts following different strategies
        context = new Context(new ConcreteStrategyAdd());
        int resultA = context.executeStrategy(3,4);

        context = new Context(new ConcreteStrategySubtract());
        int resultB = context.executeStrategy(3,4);
    }
}

// The classes that implement a concrete strategy should implement this
// The context class uses this to call the concrete strategy
interface Strategy {
    int execute(int a, int b);
}

// Implements the algorithm using the strategy interface
class ConcreteStrategyAdd implements Strategy {

    public int execute(int a, int b) {
        System.out.println("Called ConcreteStrategyAdd's execute()");
        return a + b;  // Do an addition with a and b
    }
}

class ConcreteStrategySubtract implements Strategy {

    public int execute(int a, int b) {
        System.out.println("Called ConcreteStrategySubtract's execute()");
        return a - b;  // Do a subtraction with a and b
    }
}

// Configured with a ConcreteStrategy object and maintains a reference to a Strategy object
class Context {
    private Strategy strategy;

    // Constructor
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int a, int b) {
        return strategy.execute(a, b);
    }
}

Pretty simple, right? Now, let’s take a closer look at the strategy pattern.

Strategy Pattern

The strategy pattern is a behavioral design pattern that allows you to decide which course of action a program should take, based on a specific context during runtime. You encapsulate two different algorithms inside two classes, and decide at runtime which strategy you want to go with.

In our example above, the strategy is based on whatever the context variable was at the time the class was instantiated. If you give it the context for ConcreteStrategyAdd, it will use ConcreteStrategyAdd, and vice versa.

Cute, but where can I use this?

Imagine that you’re currently developing a class which can either update or create a new user record. It still needs the same inputs (name, address, mobile number, etc.), but, depending on a given situation, it has to use different functions when updating and creating. Now, you could probably just use an if-else to accomplish this, however, what if you need to use this class in a different place? In that case, you’ll have to rewrite the same if-else statement all over again. Wouldn’t it be easier to just specify your context?

Class User {
    public void createOrUpdate(String name, String address, String mobile, String userId)
    {
        if(userId == null) {
            // it means the user doesn't exist yet, create a new record
        } else {
            // it means the user already exists, just update based on the given userid
        }
    }
}

Now, the “usual” strategy pattern involves encapsulating your algorithms inside another class, but in this case, another class would be wasteful. Remember that you don’t have to follow the template exactly. Variations work as long as the concept remains the same, and it solves the problem.

Adapter Pattern

The adapter pattern is a structural design pattern that allows you to repurpose a class with a different interface, allowing it to be used by a system which uses different calling methods.

This also lets you alter some of the inputs being received from the client class, making it into something compatible with the adaptee’s functions.

How can I use this?

Another term to reference an adapter class is a wrapper, which basically lets you “wrap” actions into a class and reuse these actions in the correct situations. A classic example might be when you’re creating a domain class for table classes. Instead of calling the different table classes and calling up their functions one by one, you could encapsulate all of these methods into one method using an adapter class. This would not only allow you to reuse whatever action you want, it also keeps you from having to rewrite the code if you need to use the same action in a different place.

Compare these two implementations:

Non-Adapter Approach

User user = new User();
user.createOrUpdate( //inputs );

Profile profile = new Profile();
profile.createOrUpdate( //inputs );

If we needed to do this again in a different place, or even reuse this code in a different project, we would have to type everything all over again.

Better

That’s opposed to doing something like this:

Account account = new Account();
account.createNew( //inputs );

In this situation, we have a wrapper class, which would be our Account class:

class Account()
{
    public void createNew( //inputs )
        User user = new User();
        user.createOrUpdate( //subset of inputs );

        Profile profile = new Profile();
        profile.createOrUpdate( //subset of inputs );
    }
}

This way, you can use your Account again whenever you need it—plus, you’d be able to wrap other classes under your account class as well.

Factory Method Pattern

The factory method pattern is a creational design pattern which does exactly as it sounds: it’s a class that acts as a factory of object instances.

The main goal of this pattern is to encapsulate the creational procedure that may span different classes into one single function. By providing the correct context to the factory method, it will be able to return the correct object.

When can I use this?

The best time to use the factory method pattern is when you have multiple different variations of a single entity. Let’s say you have a button class; this class has different variations, such as ImageButton, InputButton and FlashButton. Depending on the place, you may need to create different buttons—this is where you can use a factory to create the buttons for you!

Let’s begin by creating our three classes:

Interface Button {
    public String getHtml();
}

Class ImageButton implements Button {
    public String getHtml() {
        return "..."; //This should be whatever HTML you want for your image-based button
    }
}

Class InputButton implements Button {

    public String getHtml() {
        return "..."; //This should be whatever HTML you want for your normal button (<input type="button"... />);
    }
}

Class FlashButton implements Button {
    public String getHtml() {
        return "..."; //This should be whatever HTML you want for your flash-based button
    }
}

Now, we can create our factory class:

Class ButtonFactory
{
    public static Button createButton(String type)
    {
        try
        {
            Class buttonClass = Class.forName(type);
            java.lang.reflect.Constructor cons = buttonClass.getConstructor(classParm);
            return cons.newInstance(objectParm);
        } catch(Exception x) {
            System.out.println("The button type " + type + " is not recognized.");
        }
        return null;
    }
}

We can use this code like so:

String[] buttons = {"ImageButton", "InputButton", "FlashButton"};
for(int i=0; i<buttons.length; i++) {
    ButtonFactory.createButton(buttons[i]).getHtml();
}

The output should be the HTML of all your button types. This way, you would be able to specify which button to create depending on the situation and reuse the condition as well.

Decorator Pattern

The decorator pattern is a structural design pattern which enables us to add new or additional behavior to an object during runtime, depending on the situation.

The goal is to make it so that the extended functions can be applied to one specific instance, and, at the same time, still be able to create an original instance that doesn’t have the new functions. It also allows for combining multiple decorators for one instance, so that you’re not stuck with one decorator for each instance. This pattern is an alternative to subclassing, which refers to creating a class that inherits functionality from a parent class. As opposed to subclassing, which adds the behavior at compile time, “decorating” allows you to add new behavior during runtime, if the situation calls for it.

To implement the decorator pattern, we can follow these steps:

  1. Subclass the original “Component” class into a “Decorator” class
  2. In the Decorator class, add a Component pointer as a field
  3. Pass a Component to the Decorator constructor to initialize the Component pointer
  4. In the Decorator class, redirect all “Component” methods to the “Component” pointer, and
  5. In the Decorator class, override any Component method(s) whose behavior needs to be modified

Steps courtesy of http://en.wikipedia.org/wiki/Decorator_pattern

When can I use this?

The best place to use the decorator pattern is when you have an entity which needs to have new behavior only if the situation requires it. Once we’ve established our decorations, we can start programming them.

The following example illustrates the use of decorators using coffee making scenario. In this example, the scenario only includes cost and ingredients.

// The Coffee Interface defines the functionality of Coffee implemented by decorator
public interface Coffee {
    public double getCost(); // returns the cost of the coffee
    public String getIngredients(); // returns the ingredients of the coffee
}

// implementation of a simple coffee without any extra ingredients
public class SimpleCoffee implements Coffee {
    public double getCost() {
        return 1;
    }
    public String getIngredients() {
        return "Coffee";
    }
}

The following classes contain the decorators for all Coffee classes, including the decorator classes themselves:

// abstract decorator class - note that it implements Coffee interface
abstract public class CoffeeDecorator implements Coffee {
    protected final Coffee decoratedCoffee;
    protected String ingredientSeparator = ", ";

    public CoffeeDecorator(Coffee decoratedCoffee) {
        this.decoratedCoffee = decoratedCoffee;
    }

    public double getCost() { // implementing methods of the interface
        return decoratedCoffee.getCost();
    }

    public String getIngredients() {
        return decoratedCoffee.getIngredients();
    }
}

// Decorator Milk that mixes milk with coffee. Note it extends CoffeeDecorator
public class Milk extends CoffeeDecorator {
    public Milk(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }

    public double getCost() { // overriding methods defined in the abstract superclass
        return super.getCost() + 0.5;
    }

    public String getIngredients() {
        return super.getIngredients() + ingredientSeparator + "Milk";
    }
}

// Decorator Whip that mixes whip with coffee. Note it extends CoffeeDecorator
public class Whip extends CoffeeDecorator {
    public Whip(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }

    public double getCost() {
        return super.getCost() + 0.7;
    }

    public String getIngredients() {
        return super.getIngredients() + ingredientSeparator + "Whip";
    }
}

// Decorator Sprinkles that mixes sprinkles with coffee. Note it extends CoffeeDecorator
public class Sprinkles extends CoffeeDecorator {
    public Sprinkles(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }

    public double getCost() {
        return super.getCost() + 0.2;
    }

    public String getIngredients() {
        return super.getIngredients() + ingredientSeparator + "Sprinkles";
    }
}

Here’s a test program that creates a Coffee instance which is fully decorated (i.e., with milk, whip, sprinkles), and calculate cost of coffee and prints its ingredients:

public class DecoratorTest
{
    public static void main(String[] args)
    {
        Coffee c = new SimpleCoffee();
        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());

        c = new Milk(c);
        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());

        c = new Sprinkles(c);
        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());

        c = new Whip(c);
        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());

        // Note that you can also stack more than one decorator of the same type
        c = new Sprinkles(c);
        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
}
}

The output of this program is given below:

Cost: 1.0; Ingredients: Coffee
Cost: 1.5; Ingredients: Coffee, Milk
Cost: 1.7; Ingredients: Coffee, Milk, Sprinkles
Cost: 2.4; Ingredients: Coffee, Milk, Sprinkles, Whip
Cost: 2.6; Ingredients: Coffee, Milk, Sprinkles, Whip, Sprinkles

Example courtesy Wikipedia decorator pattern example

Singleton Pattern

The singleton design pattern is a creational design pattern which makes sure that you have one single instance of a particular class in the duration of your runtime, and provides a global point of access to the single instance.

This makes it easier to set up a point of “coordination” for other objects that use the singleton instance as well, since the singleton’s variables will always be the same for anything that calls it.

When can I use this?

This solution is thread-safe without requiring special language constructs, but it may lack the laziness of the one below. The INSTANCE is created as soon as the Singleton class is initialized. That might even be long before getInstance() is called. It might be (for example) when some static method of the class is used. If laziness is not needed or the instance needs to be created early in the application’s execution, or your class has no other static members or methods that could prompt early initialization (and thus creation of the instance), this (slightly) simpler solution can be used:

public class MySingleton {

    private static final MySingleton INSTANCE = new Singleton();

    // Private constructor prevents instantiation from other classes
    private MySingleton() {
    }

    public static MySingleton getInstance() {
        return INSTANCE;
    }
}

By doing this, we can access our MySingleton instance from different parts of our code, even in different classes. This data will persist throughout all getInstance calls.

Conclusion

There are many more design patterns to study; in this article, I’ve only highlighted some of the more prominent ones that I use when programming. If you’re interested in reading about the other design patterns, Wikipedia’s Design Patterns page has a plethora of information. If that’s not enough, you can always check out Design Patterns: Elements of Reusable Object-Oriented Software, which is considered to be one of the best design pattern books available.

One last thing: when you use these design patterns, always  make sure that you’re trying to solve the correct problem. As I mentioned previously, these design patterns are a double-edge sword: if used in the wrong context, they can potentially makes things worse; but if used correctly, they become indispensable.


Post inspired from: http://net.tutsplus.com/articles/general/a-beginners-guide-to-design-patterns/


I’ll highly appreciate your feedback on this article.

Social Network Authentications with Omniauth and Authlogic

As I discussed my experience developing an application in Rails 3 using authlogic and omniauth in my last post, Here is the tutorial as promised.

Step 1:

First of all you need to setup a Rails 3 application using authlogic gem. If you’re feeling some difficulty, try these tutorials for help:

Authlogic railcasts: http://railscasts.com/episodes/160-authlogic
Authlogic with Rails 3 tutorial: http://www.dixis.com/?p=352

Step 2:

Add the following line to your gemfile:

gem 'omniauth'

and then install the bundle

bundle install

Step 3:

Now create a ruby file in config/initializers. I’ve named it as omniauth.rb. Put the following code in it:

Rails.application.config.middleware.use OmniAuth::Builder do
    provider :twitter, 'CONSUMER_KEY', 'CONSUMER_SECRET'
    provider :facebook, 'APP_ID', 'APP_SECRET'
    # Mention other providers here you want to allow user to sign in with
end

* You can get the keys by creating an application on twitter and facebook each.

Step 4:

A user can be authenticated e.g., for twitter by redirecting him to:

http://HOST:PORT/auth/twitter

After authentication, user will be redirected back to

http://HOST:PORT/auth/twitter/callback

We can handle this callback and redirect user to a controller#action where we can process his registration and/or session handling as well as can fetch some useful data. For this, add the following lines in your routes.rb file:

resources :authentications
match '/auth/:provider/callback' => 'authentications#create'

Let’s add a couple of links on our login page which allow user to sign in via facebook or twitter:

<a href="/auth/twitter">Sign in with Facebook</a>
<a href="/auth/facebook">Sign in with Twitter</a>

Step 5:

Until here, we’ve nicely setup the user part of authentication. Now we’ve to handle the callback from social websites after authentication. Create a scaffold authentication. Here are required code snippets:

Authetications Migration:

class CreateAuthentications < ActiveRecord::Migration
    def self.up
        create_table :authentications do |t|
            t.integer   :user_id
            t.string    :provider
            t.string    :uid
            t.timestamps
        end
    end

    def self.down
        drop_table :authentications
    end
end

Authentication Model:

class Authentication < ActiveRecord::Base
    belongs_to :user
    validates :user_id, :uid, :provider, :presence => true
    validates_uniqueness_of :uid, :scope => :provider
end

Step 6:

And lastly, the authentications controller will be contain following code:

class AuthenticationsController < ApplicationController
  def create
    omniauth = request.env['omniauth.auth']
    authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])

    if authentication
      # User is already registered with application
      flash[:info] = 'Signed in successfully.'
      sign_in_and_redirect(authentication.user)
    elsif current_user
      # User is signed in but has not already authenticated with this social network
      current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
      current_user.apply_omniauth(omniauth)
      current_user.save

      flash[:info] = 'Authentication successful.'
      redirect_to home_url
    else
      # User is new to this application
      user = User.new
      user.authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'])
      user.apply_omniauth(omniauth)

      if user.save
        flash[:info] = 'User created and signed in successfully.'
        sign_in_and_redirect(user)
      else
        session[:omniauth] = omniauth.except('extra')
        redirect_to signup_path
      end
    end
  end

  def destroy
    @authentication = current_user.authentications.find(params[:id])
    @authentication.destroy
    flash[:notice] = 'Successfully destroyed authentication.'
    redirect_to authentications_url
  end

  private
  def sign_in_and_redirect(user)
    unless current_user
      user_session = UserSession.new(User.find_by_single_access_token(user.single_access_token))
      user_session.save
    end
    redirect_to home_path
  end
end

Step 7:

Update your user model and add following lines in it:

def apply_omniauth(omniauth)
  self.email = omniauth['user_info']['email']

  # Update user info fetching from social network
  case omniauth['provider']
  when 'facebook'
    # fetch extra user info from facebook
  when 'twitter'
    # fetch extra user info from twitter
  end
end

And here your go. You application is all ready for authentication with facebook and twitter. And yes, you can also register/signin using conventional email and password technique.

Interesting Fact:

The application that we’ve coded above not only supports one-time user registration using social networks. It also supports multiple social accounts for a single user. Yes, you read that right.

Remember, we have separate authentications table. So a user can have more than 1 way of  entering in the site. How to do this? Well, it’s as simple as reading this line. Once the user is signed in, you can redirect him again to the paths we used initially for signing him in. That is, you can write these lines again in your user’s homepage

<a href="/auth/twitter">Sign in with Facebook</a>
<a href="/auth/facebook">Sign in with Twitter</a>

and he’ll have multiple social accounts associated with same user. Of course, you can hide the links of those networks user has already connected with his account.

How is this done?

Go though the code of the authentications controller again. We’ve a nice little condition there:

elsif current_user
  # User is signed in but has not already authenticated with this social network
  current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
  current_user.apply_omniauth(omniauth)
  current_user.save

In case user is signed in, another authentication will be added for him and that’s all. Try to logout and login with newly added network. Yes, it meant to be as easy as 1,2,3…

Share the post if you liked it and it helped you.