路由 
在 config/routes 里添加 resources :sessions, only: [:create, :destroy] 只需要这两个 API 
 
Modal 
手动创建 app/modal/session.rb,因为 session 并不需要存在数据库中,内容1 2 3 4 5 6 7 8 9 class  Session   include  ActiveModel::Model // 不能像 user  那样继承 ActiveRecord,但是我们又需要用到 Rails 提供的 class  里面的便利方法,所以这里需要引入模块 ActiveModel   attr_accessor :email, :password    validates_presence_of :email, :password    validates_format_of :email, with : /.+@.+/, if : :email   validates_length_of :password , minimum: 6 , on : [:create ], if : :password  end 
 
 
Controller 
使用命令创建 controller ,bin/rails g controller sessions,追加两个方法1 2 3 4 5 6 7 8 9 10 11 12 13 class  SessionsController < ApplicationController  def create      session  = Session .new  create_params     session .validate      render_resource session    end    def destroy   end    def create_params     params.permit(:email, :password )   end  end 
 
 
追加一个自定义的验证,验证邮箱是否存在 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class  Session   include  ActiveModel::Model   attr_accessor :email, :password , :user    validates_presence_of :email, :password    validate  :check_email_present, if : :email   validates_format_of :email, with : /.+@.+/, if : :email   validates_length_of :password , minimum: 6 , if : :password    validate  :check_email_password_match, if : Proc.new  {|s| s.email.present? and  s.password .present?}   def check_email_present     user  ||= User .find_by_email email     if  user .nil?       errors.add  :email, :not_present     end    end    def check_email_password_match     user  ||= User .find_by_email email     if  user  and  not  user .authenticate(password )       errors.add  :password , :not_match     end    end  end 
 
attr_accessor :xxx 做了啥 
@xxx 
 
 
def xxx 获取 @xxx 的值 
 
 
def xxx= 赋值给 @xxx 
 
 
 
为了避免出错,完善一下上面的代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Session    include ActiveModel ::Model    attr_accessor :email , :password , :user    validates_presence_of :email , :password    validate :check_email_present , if:  :email    validates_format_of :email , with:  /.+@.+/, if:  :email    validates_length_of :password , minimum:  6 , if:  :password    validate :check_email_password_match , if:  Proc .new {|s| s.email.present? and  s.password.present?}   def  check_email_present      @user  ||= User .find_by_email email     if  @user .nil?       errors.add :email , :not_present      end    end    def  check_email_password_match      @user  ||= User .find_by_email email     if  @user  and  not  @user .authenticate(password)       errors.add :password , :not_match      end    end  end 
 
增加 session 中间件 config/application.rbhttps://edgeguides.rubyonrails.org/api_app.html 
1 2 3 config.session_store  :cookie_store, key: '_monery_session_id'  config.middleware .use  ActionDispatch::Cookies config.middleware .use  config.session_store , config.session_options 
 
增加 session
1 2 3 4 5 6 def create      s = Session .new  create_params     s.validate      render_resource s     session [:current_user_id] = s.user .id   end  
 
再给 user 增加一个根据 session_id 获取当前用户的路由 config/routes
1 get  '/current_user_info' , to : 'user#current_user_info' 
 
app/controllers/users_controller.rb
1 2 3 4 5 def  current_user_info   @user_id  = session[:current_user_id ]   @user  = User .find_by_id @user_id    render_resource @user  end 
 
记住密码 切记不可把用户密码直接存在 localStorage  Rails 官方没有提供最佳实践 因为做法各不相同思路 :
当用户记住密码时,带上相关字段发给服务器 
服务器接受以后,下发一个随机数(r)并存在数据库和 session 
当过了一段时间,session 过期以后,只剩下 r 被带上发送给服务器 
服务器检查 r 是否有效且正确(比如记住密码7天有效),有效中就直接派发一个新的 session, 
而数据库需要在 user 表中多增加两个字段 login_token 和 login_token_expired_at 即可 
但是如果需要做多个设备的记住密码,上面方案就不够用了,因为新设备登陆,会覆盖数据库,所以我们就需要新增一张 user 的关联表,用来记录多个 login_token 
 
三句话实现注销功能 config/routes,由于 Rails 定义的 destory 方法需要传一个 id,所以我们需要重新定义一个方法
1 delete  'sessions' , to : 'sessions#destroy' 
 
1 2 3 4 def  destroy     session[:current_user_id ] = nil      head 200    end