• 次奥,界面确实笑死人啊!哈哈

  • #3 楼 @williamherry save_and_open这是什么?没有见过,怎么用啊?

  • #1 楼 @williamherry 我在浏览器里访问是没有问题的,登陆后不能访问;没登陆则可以访问。逻辑是没有错。 我怀疑是在describe "as an admin user" do之前代码中的sign_in user对后面的测试用例有影响。不知这样猜是否正确?!

  • #21 楼 @Ryan 这部分验证在第九章中,第九章正在练习,完成后会提交到 Github 上。谢谢您的指点!哈哈

  • #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 我看了,没有发现哪里有错误。实在是郁闷啊!!

  • #7 楼 @Rei 好的!我试试!!

  • #5 楼 @Rei 发了,第一次认真看 Gemfile.lock。哈哈

  • #3 楼 @Rei 贴了,发帖的时候,还想着。后来忘了。Gemfile.lock 还需要吗?这个不是根据 Gemfile 生成的吗? 这里只有 Win7 下的,Ubuntu 下的我看看有没有生成出来啊。

  • #1 楼 @Rei 怎么升啊?!这里没有 ffi 的声明啊。

  • #14 楼 @jashawnpeng 没啥,晒晒吧。很多人是中国萌级别的配置,比如,LZ 我的就是意淫配置。哈哈

  • #1 楼 @dadadada2x pro 的也可以来晒晒。哈哈

  • 次奥,看来口袋里的银子又要阵亡一些!请问有电子版吗?@linlis 如果可以,建议出个电子版。

  • -------- at 2013年06月20日

    #8 楼 @chinakr 也不是,我觉得还好。主要是我还要看其他方面的书。哈哈

  • -------- at 2013年06月20日

    貌似不错,可惜 Ruby 不行。元编程看得懂,离写出来还有一定的差距。(我才刚自学 Rails 半年,而且学学停停,是不是进展太慢?)

  • 今年的 RubyConf China at 2013年06月14日

    这个必须顶!只要不是在外地出差,到时一定参加。

  • Rails 学习推荐书籍列表 at 2013年06月13日

    设计模式推荐 《大话设计模式》 ,国人写的,讲的也非常好,而且浅显易懂!

  • #26 楼 @leeboqiang 买了,让我弟弟玩,哈哈

  • 成功了!在 Billing 中看到可以了。哈哈

  • 添加信用卡,输入验证码,优惠的十刀果然出现。结果,添加失败,然后就木有优惠码输入框了!!哎…,还是感谢分享啊!

  • 下了 LZ 给的链接,发现只有第一章。啥时候放出全部啊?

  • 楼主好人啊!儿童节快乐!哈哈

  • #16 楼 @chankaward 我的 Email:leejun119[#]gmail.com