2

Authlogic requires many Active Record features that are not available in Active Model and thus not available in Mongoid. How can Authlogic be used with Mongoid?

4

1 回答 1

5

通过猴子修补 Authlogic 可以将 Authlogic 与 Mongoid 一起使用。YMMV。

首先,将 Authlogic 和 Mongoid 添加到 Gemfile。

gem 'mongoid', github: 'mongoid/mongoid' # Currently required for Rails 4
gem 'authlogic', '~> 3.3.0'

下一个猴子补丁 Authlogic。首先制作目录lib/modules并创建文件lib/modules/login.rb

# lib/modules/login.rb
module Authlogic
  module ActsAsAuthentic
    module Login
      module Config
        def find_by_smart_case_login_field(login)
          # Case insensitivity for my project means downcase.
          login = login.downcase unless validates_uniqueness_of_login_field_options[:case_sensitive] 

          if login_field
            where({ login_field.to_sym => login }).first
          else
            where({ email_field.to_sym => login }).first
          end
        end
      end
    end
  end
end

通过编辑告诉 rails 加载你的新模块config/application.rb

# config/application.rb
module YourApp
  class Application < Rails::Application
    config.autoload_paths += %W(#{config.root}/lib) # ADD THIS
  end
end

config/initializers/authlogic.rb通过创建并添加一行来告诉 rails 需要您的模块:

# config/initializers/authlogic.rb
require 'modules/login.rb'

下一步是关注可验证性。默认情况下,关注点仅在 Rails 4 中可用。您需要将其直接添加到 Rails 3 中的可验证类中。

# app/models/concerns/authenticable.rb
module Authenticable
  extend ActiveSupport::Concern

  included do
    include Authlogic::ActsAsAuthentic::Base
    include Authlogic::ActsAsAuthentic::Email
    include Authlogic::ActsAsAuthentic::LoggedInStatus
    include Authlogic::ActsAsAuthentic::Login
    include Authlogic::ActsAsAuthentic::MagicColumns
    include Authlogic::ActsAsAuthentic::Password
    include Authlogic::ActsAsAuthentic::PerishableToken
    include Authlogic::ActsAsAuthentic::PersistenceToken
    include Authlogic::ActsAsAuthentic::RestfulAuthentication
    include Authlogic::ActsAsAuthentic::SessionMaintenance
    include Authlogic::ActsAsAuthentic::SingleAccessToken
    include Authlogic::ActsAsAuthentic::ValidationsScope
  end

  def readonly?
    false
  end

  module ClassMethods
    def <(klass)
      return true if klass == ::ActiveRecord::Base
      super(klass)
    end

    def column_names
      fields.map &:first
    end

    def quoted_table_name
      self.name.underscore.pluralize
    end

    def default_timezone
      :utc
    end

    def primary_key
      if caller.first.to_s =~ /(persist|session)/
        :_id
      else
        @@primary_key
      end
    end

    def find_by__id(*args)
      find *args
    end

    def find_by_persistence_token(token)
      where(persistence_token: token).first
    end

    # Replace this with a finder to your login field
    def find_by_email(email)
      where(email: email).first
    end

    def with_scope(query)
      query = where(query) if query.is_a?(Hash)
      yield query
    end
  end
end

基本上就是这样。这是一个示例User类。

# app/models/user.rb
class User
  include Mongoid::Document
  include Mongoid::Timestamps

  include Authenticable

  field :name
  field :email
  field :crypted_password
  field :password_salt
  field :persistence_token
  field :single_access_token
  field :perishable_token

  field :login_count,        type: Integer, default: 0
  field :failed_login_count, type: Integer, default: 0
  field :last_request_at,    type: DateTime
  field :last_login_at,      type: DateTime
  field :current_login_at,   type: DateTime
  field :last_login_ip
  field :current_login_ip

  field :role, type: Symbol, default: :user

  index({ name: 1 })
  index({ email: 1 }, { unique: true })
  index({ persistence_token: 1}, { unique: true })
  index({ last_login_at: 1})

  validates :name, presence: true
  validates :email, presence: true, uniqueness: true
  validates :crypted_password, presence: true
  validates :password_salt, presence: true

  acts_as_authentic do |config|
    config.login_field = 'email' # Remember to add a finder for this
  end
end

然后UserSession看起来像这样:

# app/models/user_session.rb
class UserSession < Authlogic::Session::Base
  def to_key
    new_record? ? nil : [self.send(self.class.primary_key)]
  end

  def to_partial_path
    self.class.name.underscore
  end
end

应用程序控制器助手与往常一样。

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  helper_method :current_user

  private
  def current_user_session
    @current_user_session = UserSession.find unless 
      defined?(@current_user_session)
    @current_user_session
  end

  def current_user
    @current_user = current_user_session && 
      current_user_session.user unless defined?(@current_user)
    @current_user
  end
end

这就对了。其他一切都应该像以前一样工作。

于 2013-08-15T20:36:42.997 回答