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

发布于 2024-11-19 20:20:22 字数 1399 浏览 2 评论 0原文

我在 Rails 3 中使用 Devise,并且在 Rails 中有一个用户模型,它开始变得有点拥挤..所以我想将所有登录方法放在一个模块中,并将它们包含在我的模型中。我正在尝试类似的东西:

app/model/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/autoloads/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)

有没有办法做我正在拍摄的事情是真的吗?

谢谢

I am using Devise in Rails 3, and have a User model in rails that is starting to get kinda crowded.. so I would like to put all of the login meethods inside of a module and include them from my model. I'm trying something like:

app/model/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

and

lib/autoloads/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

but the server doesn't seem to like that, as it loads with a NoMeethodError

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

Is there a way to do what I'm shooting for, or not really?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

無處可尋 2024-11-26 20:20:22

这不是您正在寻找的答案,但是,这是我的 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

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

This is not the answer you are looking for but, here is my 2 cents: You shouldn't put all that stuff in the User model. devise models have a clear responsibility: signing.

But if you really want to put everything hooked in User.rb, you can split the model in extensions (partially enabling DCI):

Add that to your 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

Then, you just add it into your model:

include Models::User::DeviseExt

In the app we have in my company we actually have no code at all in models, we put everything in extensions.

两仪 2024-11-26 20:20:22

我还没有使用过 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

I've not used Devise yet, but try this:

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

and in your model, include rather than extend:

class User < ActiveRecord::Base
  include Loginable
end
仅一夜美梦 2024-11-26 20:20:22

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

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

但它们不会覆盖 devise 本身中定义的相同方法(例如 email_required?)。因此,当您在用户模型本身上定义 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 中的所有方法都将覆盖 devise 的方法。
我不知道这是否是最好的解决方案,但它对我有用。希望有帮助。

This is an old question, but answers here didn't help me with Rails 4.2.

The problem is that when you define instance methods inside a module and include it into User model, they actually get defined on that instance.

But they don't override same methods in devise itself (like email_required?) defined inside devise method. So when you define email_required? on User model itself it works fine, but in included module they don't override devise's method.

But with Ruby 2 you can do this with prepend. Like this:

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

Now all methods in DeviseInstanceMethods will override devise's methods.
I don't know whether this is best solution, but it works for me. Hope it helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文