Rails 新手学习 Rails,看 Devise 代码无从下手

Peter · 2012年05月14日 · 最后由 breakeryang 回复于 2016年08月20日 · 16308 次阅读

大家可能觉得这是个常被新手问到的问题, 事实上也的确如此.

网上的资料很多, 比如 http://guides.rubyonrails.org/index.html http://pragprog.com/book/rails4/agile-web-development-with-rails http://ruby.railstutorial.org/

可是我们真正做网站的时候, 是devise + omniauth + cancan + ...

就拿最简单的devise来说, 就算我安装配置成功了, 还加了birthday等字段, 但这就行了吗? devise的文档严重不全, 作为一个RoR初学者, 而不是MVC的初学者, 我就想知道框架和devise本身的代码是怎么动作的.

我打开目录: ~/.rvm/gems/ruby-1.9.3-p194/gems/devise 看着一堆代码无从下手, 因为我的user model 是用命令生成的: $ rails generate devise User

这样, 我都不知道要用什么关键词来搜索源码.

我是一个小白, 用过 fleaphp 框架, 开始觉得rails有些东西好亲切, 现在发现学习曲线好陡, 不知道各位高手是如果成长的, 谢谢你们提供一些宝贵经验, 先谢谢了!

共收到 36 条回复

我当初是看你列出的那些资料后慢慢做一些小demo入门的,没有用devise啥,用户验证全部自己写,后来用了devise这些后觉得效率高了很多,但一开始也只是会基本的配置使用,devise的文档感觉还可以吧,相比那些连wiki都没有要看测试代码才知道怎么用的gem好多了,我是了解元编程后才读得懂devise这些gem的源码的。入门看rails guides还是挺好的,我现在有空也会去重新看一下,每次看总能学到一些新知识,慢慢积累一段时间你就知道应该怎么去读gem了

谢谢楼上两位的热心回答, 我其实是想知道有没有讲解rails的gems如何运作的书.

我现在有个php开发的网站, 用户密码是用md5存储的, 现在想使用原来的User表, 于是我想在user model里面重写一个方法, 让user成功登录的时候, 把原来md5字段清空, 把devise生成的密码加在相应字段上.

我google了很久以后, 再加上自己摸索, 做了个实验总结如下:

在下面的文件中, 发现函数 valid_password?(password) ~/.rvm/gems/ruby-1.9.3-p194/gems/devise-2.0.4/lib/devise/models/database_authenticatable.rb

将database_authenticatable.rb copy到项目中: ~/MyProject/lib/devise/models/database_authenticatable.rb

注意最后的部分是一样的: /lib/devise/models/database_authenticatable.rb 这样, rails就会load项目中的文件

在user表中添加 old_password和clear_txt字段, 再把代码修改成这样:

def valid_password?(password)
  return false if encrypted_password.blank?

  self.old_password = ::Digest::MD5.hexdigest(password)
  self.clear_txt = password
  self.save!

  bcrypt   = ::BCrypt::Password.new(self.encrypted_password)
  password = ::BCrypt::Engine.hash_secret("#{password}#{self.class.pepper}", bcrypt.salt)

  Devise.secure_compare(password, self.encrypted_password)
end

重启rails web服务器后, 用一个帐号登录, 那该用户的old_password字段就存了字码的md5值, clear_txt就存了明文密码。

另外, 更简单也是推荐的方法是: 直接把 valid_password?(password) 放在 app/models/user.rb 中, 这样就覆盖了框架中的函数。

到这里只是做了个实验, 具体实现也不难了, 但是即使是这样, 我还是对gems的使用一头雾水.

devise生成了我的User model, 我的user model在运行时是怎样在这个目录找相关代码的呢? ~/.rvm/gems/ruby-1.9.3-p194/gems/devise-2.0.4/lib/devise

我用devise生成的是user model, 当然也可以命名为member model, 那我在devise源码里面就不可能搜索到 user 或者 member, 这给我理解代码又增加了难度, 我好像看到的是resource还是什么的代替了user或member, 这种动态的方法是实现了大家命名的自由, 却让我这种新手找不到北.

谢谢大家继续提供更多信息, 帮助新人成长. @Zernel 的元编程是个很好的提示: http://ruby-china.org/wiki/ruby-meta

@lgn21st 的建议也很好, 不过我要重构原来的网站, 所以原来的用户表还是要用的, 对于我来说, 不但要用devise,还要加上Omniauth.

如果是历史遗留数据库,可以用alias_method_chain,来实现你前面说的功能: https://github.com/plataformatec/devise/wiki/How-To:-Migration-legacy-database

你前面的代码没有实现用户忘记密码的功能,而且相当于直接打monkey patch了

Devise这种gem的代码阅读,需要多学习ruby的语法,它里面用了很多元编程的特性

#2楼 @lgn21st 最近,我们的项目正在打算使用Devise,我们的团队也觉得Devise代码很难懂,现在听你这么一说,我们打算再研究一下 OmniAuth-Identity

#3楼 @Peter 专门写gem的书可能不太好找,不过Railscasts有几个关于gem的视频。 http://railscasts.com/episodes/301-extracting-a-ruby-gem

生成的user model肯定都是空的,因为一切功能都是元编程加进来的。但是源代码里面肯定有方法的定义。不过找到容不容易就看源码组织结构和个人的经验了。

简单说一切gem的起始点都是lib文件夹及其下面的一个.rb文件,可以从这里开始看起。

devise不是个学习的好gem,因为他不只是一个gem,还是个rails engine. rails engine比gem烦很多。而且devise需要跟warden打交道,就需要多了解rack,理解rack的机制又是一个初学者的障碍。想学习gem源代码的话,可以先从简单的开始。

#2楼 @lgn21st 老大,OmniAuth-Identity不错~ 又是你们的产品吗?

devise过于复杂了,涉及到多个gem和rack机制和rails机制等,我也尝试过看他的代码,头大啊,后来放弃了。 不如看些小型gem,比如httparty这种规模的,外部关联机制少,减少学习中的干扰,专门提高ruby语法的感觉。 其实我觉得omniauth和devise这类rack中间件都是overkill,平添复杂度,好恶心,每个中间件都要做一次Rack::Request.new(env)......

其实密码校验,用 activemodel 内置的 SecurePassword 就行了 http://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html

这个模块代码非常少而且有启发性

https://github.com/rails/rails/blob/master/activemodel/lib/active_model/secure_password.rb

OmniAuth-Identity 原理不错,还没实际用过。

我倒是相对更喜欢Authlogic

gem 'sorcery' http://railscasts.com/episodes/283-authentication-with-sorcery 看看sorcery自己定制会挺简单的

devise 基于rack,倒是不是很难,有耐心慢慢看就行。话说我那种用devise时,做个扩展。。。看的也头大

#2楼 @lgn21st 挖坟 我也不喜欢 Devise...总感觉太重...

Devise的确非常的重,其实很多项目的认证插件根本用不到这么复杂的功能。

习惯习惯就好了, 虽然现在没看多少devise的代码,但能用能改了。

目前在改ruby-china的代码, 为了防注册机,加入社交元素,现已禁用注册,只允许用户通过Omniauth( Google, Fackbook, weibo,douban, QQ) 注册。

用户在 callback的时候填写在本站的用户名和密码, 如果像weibo那样的没有返回email,还要让用户填写email, 同时用devise发 comfirmation的email, 改动有点大, 不过埋头看代码, 过一段时间还是可以搞定的。

看到这个帖子我终于松了一口气。 之前发现公司项目里使用 devise 。尝试看了下它的实现,真心困难啊。后来在一个 rails 活动听一个朋友的建议后就看开了,其实目前只需要知道怎么用就好了。 #2楼 @lgn21st 说得好,如果需要学习它,可以去研究研究。

如果要想了解怎么运作,最好的办法就是customize各种controller和view,然后自己改写掉,基本上整个运作流程就能比较清晰了。

@samqiu 看来还是用omniauth比较好

够用就行。

各位大神,我是初学者,因为学校要求时间太紧张,用devise做了登录注册部分。注册模块貌似已经成功了,因为数据库确实被修改了。但是登录总会出现 NoMethodError in Devise::SessionsController#create undefined method `utc' for "2014-03-23 06:08:35.717620":String 的错误,怎么改也没法成功。求各位帮助。

@Peter @Zernel @lgn21st @quakewang @ery 求指教,求帮助啊~

#21楼 @yogurt 这货是个怪物,建议绕行,如果要深究下去,都是坑,甚至可以拿来写书 http://www.packtpub.com/learning-devise-for-rails/book

可是我来不及完成实验了,,,,还有什么简单快速开发注册登录的东东么。。。

#23楼 @yogurt 有啊,放弃自己写代码这件事情,自己强行干不一定干得好,去花钱请人来处理。

我只想知道怎么override掉encrypt方法

#26楼 @motloveruby 三楼应该说得比较清楚了

亲 你还在德国嘛

哇哦 亲 如果想去德国工作 就比如你得科隆 或者 下萨克森州 有什么途径 或者推荐嘛

#30楼 @sun528 我在这边读书,然后找的工作,你如果年轻,娶老婆生孩子,好好在国内呆着吧,不值得来德国折腾,学德语不像学ruby或 swift。

#32楼 @sun528 发邮件给我吧,把情况写详细些,版聊太囧

#9楼 @Rei 赞同!一般我会在自己的项目中尽量用Rails 自带的基础接口, has_secure_password 就解决了很多问题了,没必要一上来就上 devise。

我翻到了一些 扩展控制器的一些逻辑 Devise:Controller 的模块方法,但不太清楚, 如果这些方法是如何运行时绑定到自己的控制器中的。 在Java中可以使用继续, 代理。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册