Railsでモデルを分割しようと思った時

Rails4から導入されたconcernsを使うという方法もあるが、これは「他のモデルにまたがる処理があるときそれを分割する」場合に使うということらしいので、単純にモデルに色々な処理が入り過ぎたり、重複が沢山あってそれを整理するという場合には適用し辛いのかなと思った。

で、例えばですが、twitterログインやfacebookログインなどを使ってユーザログインさせる処理を書いている場合(userモデルを作って)、provider(twitterfacebook)毎の登録処理が微妙に似ていたりする。が、一つのメソッドにはしずらい。

そういった場合にif文が多くなるので、userモデルを親クラスとしてtwitter_userやfacebook_userを作って更にfactoryクラス作ってやったら、以外とすっきりした。
もっと良い方法があるのだろうけど、取りあえずこういう方法もあるんだなーという感想

class User < ActiveRecord::Base

  def self.create_account(auth)
    @user = UserFactory.create_user(auth[:provider])
    @user.create_account(auth)
  end

end
  1 class TwitterUser < User
  2
  3   def create_account(auth)
  4     @new_user = User.find_or_create_by(email: auth[:extra][:raw_info][:email]) do|user|
  5       user.name  = auth[:extra][:raw_info][:name]
  6       user.email = auth[:extra][:raw_info][:email]
  7     end
  8     @provider = AuthProvider.find_or_create_by(provider: auth[:provider], user_id: @new_user.id) do |auth_provider|
  9       auth_provider.user_id = @new_user.id
 10       auth_provider.uid      = auth[:uid]
 11       auth_provider.provider = auth[:provider]
 12       unless auth[:extra].blank?
 13         auth_provider.screen_name = auth[:extra][:raw_info][:nickname]
 14         auth_provider.image_path  = auth[:extra][:raw_info][:image]
 15       end
 16       auth_provider.token = auth["credentials"]["token"] unless auth["credentials"].blank?
 17     end
 18     @new_user.login_provider =  @provider
 19     
 20     @new_user
 21   end
 22 end
  1 # coding: utf-8
  2
  3 class FacebookUser < User
  4
  5   def create_account(auth)
  6     @new_user = User.find_or_create_by(email: auth[:info][:email]) do |user|
  7       user.name  = auth[:info][:name]
  8       user.email = auth[:info][:email]
  9     end
 10     @provider = AuthProvider.find_or_create_by(provider: auth[:provider], user_id: auth[:user_id]) do |auth_provider|
 11       auth_provider.user_id = @new_user.id
 12       auth_provider.uid      = auth[:uid]
 13       auth_provider.provider = auth[:provider]
 14       unless auth[:info].blank?
 15         auth_provider.screen_name = auth[:info][:nickname]
 16         auth_provider.image_path  = auth[:info][:image]
 17       end
 18       auth_provider.token = auth["credentials"]["token"] unless auth["credentials"].blank?
 19       auth_provider.save
 20     end
 21     @new_user.login_provider =  @provider
 22     @new_user
 23   end
 24 end

最後にFactoryクラス

  1 class UserFactory
  2   def self.create_user(provider)
  3     if provider  == 'facebook'
  4       @user = FacebookUser.new
  5     elsif provider == 'twitter'
  6       @user = TwitterUser.new
  7     end
 10     @user
 11   end
 12 end