次奥,界面确实笑死人啊!哈哈
#3 楼 @williamherry
save_and_open
这是什么?没有见过,怎么用啊?
#1 楼 @williamherry
我在浏览器里访问是没有问题的,登陆后不能访问;没登陆则可以访问。逻辑是没有错。 我怀疑是在describe "as an admin user" do
之前代码中的sign_in user
对后面的测试用例有影响。不知这样猜是否正确?!
#15 楼 @Ryan #16 楼 @xuncheng #17 楼 @blacktulip #7 楼 @andor_chen #5 楼 @reyesyang #6 楼 @cqcn1991
谢谢各位!问题貌似解决了。原因是,我在加入 remember_token 前,创建了俩个用户。所以已有用户中 remember_token 就为空。然后使用rake db:reset
重新生成数据库表结构。重新注册,就有了 remember_token。再次登陆就正常了。退出也没有问题了。
不过,还是有疑问。
先从创建用户说起,表单不提,只展示一下,创建 remember_token 的代码,如下(以下代码第一行是代码的路径。):
# /app/models/user.rb
class User < ActiveRecord::Base
# …
before_save :create_remember_token
# …
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
登陆表单如下:
<!-- /app/views/sessions/new.html.erb -->
<%= form_for(:session, url: sessions_path) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit "Sign in", class: "btn bin-large btn-primary" %>
<% end %>
登陆的 Action 代码如下:
# /app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
def create
user = User.find_by_email(params[:session][:email])
if user && user.authenticate(params[:session][:password])
sign_in user
redirect_to user
else
flash.now[:error] = 'Invalid email/password combination' # Not quite right!
render 'new'
end
end
end
登录的辅助方法:
# /app/helpers/sessions_helper.rb
module SessionsHelper
def sign_in(user)
cookies.permanent[:remember_token] = user.remember_token
self.current_user = user
end
def current_user=(user)
@current_user = user
end
end
登陆之后,在页面 header 中判断是否登陆的代码入下:
<!-- /app/views/layouts/_header.html.erb -->
<% if signed_in? %>
<li><%= link_to "Users", '#' %></li>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Account <b class="caret"></b></a>
<!--#……-->aa
<% else %>
<li><%= link_to "Sign in", signin_path %></li>
<% end %>
判断是否登陆的辅助方法 signed_in?代码如下:
# /app/helpers/sessions_helper.rb
module SessionsHelper
def signed_in?
!current_user.nil?
end
def current_user
@current_user ||= User.find_by_remember_token(cookies[:remember_token])
end
#……
end
疑问一:即使表中有俩个记录 remember_token 一样时,登陆之后,还是现实“Sign in”链接。(原来都为空,我刚刚测试了拷贝成一样的,测试结果一样。),在rails console
中可以可以使用User.find_by_remember_token('i1twSVTRkMLHLk1wIX2rVA')
可以查出来(具体如下)。为啥在页面是否登陆的判断中,获取当前用户的方法却查询不出数据呢?又测试了几次,又可以正常登陆了。很诡异。
irb(main):002:0> User.find_by_remember_token('i1twSVTRkMLHLk1wIX2rVA')
User Load (1.0ms)
SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'i1twSVTRkMLHLk1wIX2rVA' LIMIT 1
=> #<User id: 1, name: "Dgg", email: "lee*****@gmail.com", created_at: "2013-07-08 08:20:43", updated_at: "2013-07-08 08:20:43", password_digest: "$2a$10$.J5oTtqmFWBi4C7nxdn4huE9QvJBUBqD9/ROm/jniKJ...", remember_token: "i1twSVTRkMLHLk1wIX2rVA">
#…因为会输出一些诡异字符,这里贴的结果做了简单调整
下面再说说退出时的诡异现象。
退出时,路由设置如下:
# /config/routes.rb
resources :sessions, only: [:new, :create, :destroy]
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
# …
退出的 Action 方法:
# /app/helpers/sessions_helper.rb
class SessionsController < ApplicationController
def destroy
sign_out
redirect_to root_path
end
end
退出的辅助方法sign_out
如下:
# /app/helpers/sessions_helper.rb
module SessionsHelper
def sign_out
self.current_user = nil
cookies.delete(:remember_token)
end
# …
end
退出之后,在页面 header 中判断是否登陆的代码入下:
<!--/app/views/layouts/_header.html.erb-->
<% if signed_in? %>
<li><%= link_to "Users", '#' %></li>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Account <b class="caret"></b></a>
<!--#……-->aa
<% else %>
<li><%= link_to "Sign in", signin_path %></li>
<% end %>
判断是否登陆的辅助方法signed_in?
代码如下:
# /app/helpers/sessions_helper.rb
module SessionsHelper
def signed_in?
!current_user.nil?
end
def current_user
@current_user ||= User.find_by_remember_token(cookies[:remember_token])
end
end
疑问二:为啥在上面的退出辅助方法sign_out
中已经将self.current_user = nil
,而在判断是否登陆的辅助方法signed_in?
中却可以得出true
的结果?我刚刚又特意把remember_token
设置成空或者同样的值,试了试,却又正常了。诡异
求各位继续解答。谢谢!
#13 楼 @blacktulip 谢谢!我看看啊!
#7 楼 @andor_chen
查看了浏览器中的 Cookie,remember_token
竟然为空。这个何解啊?!
#8 楼 @leonworld 我试了试,重视失败,搞不成单步调试!很郁闷!!
#7 楼 @andor_chen
干嘛要执行User.all.each { |user| user.save(validate: false) }
这个呢?在哪里执行啊?
我查看一下浏览器的 Cookie 啊。
#5 楼 @reyesyang
我查看了一下 SQLite,remember_token 那列是空。但是,我看代码和没错。
在/app/models/user.rb
中的生成 remember_token 的代码没有错啊!如下:
class User < ActiveRecord::Base
attr_accessible :email, :name, :password, :password_confirmation
has_secure_password
before_save { |user| user.email = email.downcase }
before_save :create_remember_token
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\-.]+\.[a-z]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 6 }
validates :password_confirmation, presence: true
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
#3 楼 @apprentice 测试都通过了。要不你 clone 下来,试一下?哈哈
#1 楼 @apprentice 我看了,没有发现哪里有错误。实在是郁闷啊!!
#14 楼 @jashawnpeng 没啥,晒晒吧。很多人是中国萌级别的配置,比如,LZ 我的就是意淫配置。哈哈
#1 楼 @dadadada2x pro 的也可以来晒晒。哈哈
次奥,看来口袋里的银子又要阵亡一些!请问有电子版吗?@linlis 如果可以,建议出个电子版。
貌似不错,可惜 Ruby 不行。元编程看得懂,离写出来还有一定的差距。(我才刚自学 Rails 半年,而且学学停停,是不是进展太慢?)
这个必须顶!只要不是在外地出差,到时一定参加。
设计模式推荐 《大话设计模式》 ,国人写的,讲的也非常好,而且浅显易懂!
#26 楼 @leeboqiang 买了,让我弟弟玩,哈哈
成功了!在 Billing 中看到可以了。哈哈
添加信用卡,输入验证码,优惠的十刀果然出现。结果,添加失败,然后就木有优惠码输入框了!!哎…,还是感谢分享啊!
下了 LZ 给的链接,发现只有第一章。啥时候放出全部啊?
楼主好人啊!儿童节快乐!哈哈
#16 楼 @chankaward 我的 Email:leejun119[#]gmail.com