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

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

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

网上的资料很多, 比如 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 有些东西好亲切, 现在发现学习曲线好陡, 不知道各位高手是如果成长的, 谢谢你们提供一些宝贵经验, 先谢谢了!

我当初是看你列出的那些资料后慢慢做一些小 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 的错误,怎么改也没法成功。求各位帮助。

#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 中可以使用继续, 代理。

需要 登陆 后方可回复, 如果你还没有账号请 注册新账号