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

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

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

网上的资料很多,比如 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 中可以使用继续,代理。

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