是否可以在外部模块中加载Devise?

时间:2011-07-14 02:04:07

标签: ruby-on-rails ruby-on-rails-3 devise

我在Rails 3中使用Devise,并且在rails中有一个用户模型开始变得有点拥挤..所以我想将所有登录meethods放在一个模块中并从我的模型中包含它们。我正在尝试这样的事情:

应用程序/模型/ user.rb

class User < ActiveRecord::Base
  include UserImageable
  extend Loginable

  has_one  :profile, :dependent => :destroy
  has_many :items, :dependent => :destroy
  has_many :products, :through => :items

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :phone_number, :location, :photo, :profile_attributes, :access_token
  delegate :first_name, :last_name,  :phone_number, :phone_number=, :location, :location=, :photo,  :to  => :profile

  accepts_nested_attributes_for :profile
end

LIB /自动加载/ loginable.rb

module Loginable
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable

  def password_require?
    new_record?
  end
end

但服务器似乎不喜欢这样,因为它加载了NoMeethodError

loginable.rb:4:in `<module:Loginable>': undefined method `devise' for Loginable:Module (NoMethodError)

有没有办法做我正在拍摄的,或者不是真的?

由于

3 个答案:

答案 0 :(得分:2)

这不是您正在寻找的答案,但是,这是我的2美分:您不应该将所有这些内容放在用户模型中。设计模型有明确的责任:签字。

但是如果你真的想把所有东西都挂在User.rb中,你可以将模型拆分为扩展(部分启用DCI):

将其添加到lib / models / {modelname} /devise_ext.rb

module Models
    module User
        module DeviseExt
            extend ActiveSupport::Concern

            included do
                        devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable

            end

            module ClassMethods

            end

            module InstanceMethods      

                def password_require?
                                new_record?
                            end
            end #InstanceMethods

        end
    end
end

然后,您只需将其添加到模型中:

include Models::User::DeviseExt

在我们公司的应用程序中,我们实际上在模型中根本没有代码,我们将所有内容都放在扩展中。

答案 1 :(得分:1)

我还没有使用Devise,但试试这个:

module Loginable
  def self.included(base)
    base.send :devise, :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable
  end

  def password_require?
    new_record?
  end
end

在您的模型中,包括而不是扩展:

class User < ActiveRecord::Base
  include Loginable
end

答案 2 :(得分:1)

这是一个老问题,但这里的答案并没有帮助我使用Rails 4.2。

问题在于,当您在模块中定义实例方法并将其包含到用户模型中时,它们实际上会在该实例上定义。

但是他们不会在email_required?方法中定义的设计中覆盖相同的方法(如devise)。因此,当您在用户模型本身上定义email_required?时,它可以正常工作,但在包含的模块中,他们不会覆盖设计方法。

但是使用Ruby 2,您可以使用prepend执行此操作。像这样:

module User::AuthHelper
  extend ActiveSupport::Concern

  included do
    prepend DeviseInstanceMethods

    devise :database_authenticatable, :async, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, \
        :omniauthable, omniauth_providers: [:facebook, :instagram], authentication_keys: [:username]
  end

  module DeviseInstanceMethods
    def email_changed?
      false
    end

    def email_required?
      false
    end
  end
end

现在DeviseInstanceMethods中的所有方法都会覆盖设计方法。 我不知道这是否是最佳解决方案,但它对我有用。希望它有所帮助。