大家可能觉得这是个常被新手问到的问题,事实上也的确如此。
网上的资料很多,比如 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 了
Devise 在处理用户注册登陆上,的确是相当便利。但如果你要定制的时候,看 Devise 的源码发现找不到北,呵呵,你并不孤独!
实际上 Devise 算是一个特例了,不是所有的 gem 都实现得这么复杂晦涩短时间内难以让人把持。Devise 的代码写的太灵活,真不是那么容易去定制的,他的作者是相当牛,是 Rails 的 core team member 之一。如果你觉得对 Ruby/Rails 掌握达到了一定的阶段,打算通过阅读代码提升的话,Devise 得源码值得学习,但是就作一个注册登陆的组件来说,我觉得它作的有点过火了。
我一直避免在新项目中使用 Devise,如果需要作注册登陆的话,我个人推荐使用OmniAuth-Identity,且这个 gem 容易跟其他 OmniAuth 系列的 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 的语法,它里面用了很多元编程的特性
#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 源代码的话,可以先从简单的开始。
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 原理不错,还没实际用过。
gem 'sorcery' http://railscasts.com/episodes/283-authentication-with-sorcery 看看 sorcery 自己定制会挺简单的
习惯习惯就好了,虽然现在没看多少 devise 的代码,但能用能改了。
目前在改 ruby-china 的代码,为了防注册机,加入社交元素,现已禁用注册,只允许用户通过 Omniauth( Google, Fackbook, weibo,douban, QQ) 注册。
用户在 callback 的时候填写在本站的用户名和密码,如果像 weibo 那样的没有返回 email,还要让用户填写 email, 同时用 devise 发 comfirmation 的 email, 改动有点大,不过埋头看代码,过一段时间还是可以搞定的。
各位大神,我是初学者,因为学校要求时间太紧张,用 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
我翻到了一些 扩展控制器的一些逻辑 Devise:Controller 的模块方法,但不太清楚,如果这些方法是如何运行时绑定到自己的控制器中的。在 Java 中可以使用继续,代理。