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, :ph开发者_如何学JAVAone_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
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.
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
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.
精彩评论