SeriouslyAwesome/democratictravelers

View on GitHub
app/models/user.rb

Summary

Maintainability
A
0 mins
Test Coverage
class User < ActiveRecord::Base
  # SCOPES
  scope :registered, -> { where(guest: false).order('created_at DESC') }
  scope :guests, -> { where(guest: true) }
  scope :inactive, -> { where('updated_at < ?', 14.days.ago) }

  # ASSOCIATIONS
  has_many :experiences, dependent: :destroy
  has_many :locations, through: :experiences

  # VALIDATIONS
  validates :name, presence: true
  validates :uuid, uniqueness: true
  validates :username, uniqueness: true,
                       format: { with: /\A^[a-z0-9\-_]+$\z/i, multiline: true }

  with_options unless: :from_social? do |u|
    u.validates :password, presence: true, length: { in: 4..100 }
    u.validates :password_confirmation, presence: true
    u.validates :email, presence: true, uniqueness: true
  end

  # CALLBACKS
  before_validation :generate_uuid
  before_save :ensure_auth_token
  after_create { add_role :user }
  after_create :subscribe, if: proc { |u| u.email && u.mailing_list? }

  # DELEGATIONS

  # MACROS
  rolify
  devise :database_authenticatable, :registerable, :recoverable, :rememberable,
         :trackable, :omniauthable, :marketable
  has_reputation :votes, source: { reputation: :votes, of: :experiences },
                         aggregated_by: :sum

  # CALLBACK METHODS
  def generate_uuid
    self.uuid = SecureRandom.hex(8) unless uuid.present?
    self.username = uuid unless username.present?
  end

  def ensure_auth_token
    self.authentication_token = generate_auth_token unless authentication_token
  end

  def subscribe
    Gibbon::API.lists.subscribe id: '32d72a73df', email: { email: email }
  end

  # CLASS METHODS
  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
      user.assign_attributes(
        provider: auth.provider, uid: auth.uid, email: auth.info.email,
        username: auth.info.nickname, name: auth.info.name,
        location: auth.info.location
      )
    end
  end

  def self.new_with_session(params, session)
    if session['devise.user_attributes']
      new(session['devise.user_attributes'], without_protection: true) do |u|
        u.attributes = params
        u.valid?
      end
    else
      super
    end
  end

  # INSTANCE METHODS
  def admin?
    has_role? :admin
  end

  def from_social?
    provider.present?
  end

  def password_required?
    super && provider.blank?
  end

  def update_with_password(params, *options)
    if encrypted_password.blank?
      update_attributes(params, *options)
    else
      super
    end
  end

  def first_name
    name.split.first
  end

  def last_name
    name.split.last
  end

  def short_name
    n = name.split
    first = n.first
    last = n.size > 1 ? n.last[0, 1] + '.' : ''
    [first, last].reject(&:empty?).join(' ')
  end

  def voted_for?(experience)
    evaluations.where(
      target_type: experience.class,
      target_id: experience.id).present?
  end

  private

  def generate_auth_token
    loop do
      token = Devise.friendly_token
      break token unless User.find_by(authentication_token: token)
    end
  end
end