对待生命,不妨大胆一点,因为我们终将失去它

分类: rails


  • Rails的helper_method和Concern

    今天在做用户认证时,在控制器中一直用authenticated?来判断用户是否登陆,但一直不成功。

    查了下,发现authenticated?Authentication Concern的helper_method方法,
    而helper_method是暴露给view层使用的,在其它控制器中是不能直接使用的,
    需要在控制器的class下include Authentication才可以使用


    Conern是Rails非常有用的一个概念,在以前,我经常会写多重继承的代码,
    比如“大象”类继承“哺乳动物”类,而“哺乳动物”类又继承自“动物园”类,
    这时候为了兼容,很容易出现“动物园”类里有很多“大象”类和“哺乳动物”类所不需要的方法,
    这就造成代码重用性的问题,而且也不容易维护。
    而Conern允许将共享的代码逻辑封装到单独的可重用的模块中,通常存放在 app/models/concernsapp/controllers/concerns 目录下,
    然后在需要使用这个 Concern 的类中,使用 include关键字导入就行了

    class SomeController < ApplicationController
      include Authentication
    
      # 现在可以使用 Authentication 中定义的方法和回调
    end

    比如“哺乳动物”类就可以作为一个Conern,“大象”类直接继承自“动物园”类,但可以在“大象”类里include “哺乳动物”类来使用需要的方法。

    有点像 接口/协议 的概念,但接口/协议主要是定义/签名,不一定有方法的实现,而Conern直接提供方法的实现,更注重代码的重用性,其它不用考虑


  • Rails 8的Authentication模块

    如果你像我一样刚开始学习Rails,则建议直接开始使用Rails 8.0.0.beta版本,因为该版本更新优化了很多功能,最重要的是加入了身份验证模块抽象层,不用像7之前的版本那样麻烦。
    在这里记录下我的相关笔记

    • 一键生成身份验证系统: bin/rails generate authentication
      该命令会创建User、Current、Session三个模型,并且会在app/controllers/conerns下添加Authentication模块
    • 只有认证模块,没有注册模块
    • 默认使用邮箱和密码进行认证
    • Authentication模块的方法,建议直接打开该模块文件,就55行代码,非常的简洁明了
    • 查看三个模型对应的的controller文件,也非常简洁明了。。。
    • 认证流程(via):
      file
    • 重置密码流程(via):
      file
    • 添加注册流程

      1. 创建Users Controller: bin/rails g controller Users

        # File: app/controllers/users_controller.rb
        class UsersController < ApplicationController
        allow_unauthenticated_access only: %i[ new create ]
        def new
        end
        
        def create
        @user = User.new(user_params)
        if @user.save
          redirect_to root_path, notice: "User was successfully created."
        else
          render :new
        end
        end
        
        private
        def user_params
        params.require(:user).permit(:email_address, :password, :password_confirmation)
        end
        end
      2. 创建view文件
        #File: app/views/users/new.html.erb
        <%= tag.div(flash[:alert], style: "color:red") if flash[:alert] %>
        <%= tag.div(flash[:notice], style: "color:green") if flash[:notice] %>
        

        Sign Up

        <%= form_with(model:User) do |form| %> <%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address] %>
        <%= form.password_field :password, required: true, placeholder: "Enter your password", maxlength: 72 %>
        <%= form.password_field :password_confirmation, required: true, placeholder: "Confirm your password", maxlength: 72 %>
        <%= form.submit "Sign up" %> <% end %>
      3. 添加route
        #File: config/routes.rb
        resources :users

  • params.fetch和params.require的区别

    这两种方式用于在 Rails 控制器中处理参数,但它们的用法和目的有所不同:

    params.fetch(:article, {})

    • 功能:fetch 方法尝试从 params 中获取 :article 的键值对。如果 :article 存在,它返回对应的值;如果不存在,则返回一个空的哈希 {},而不会抛出异常。
    • 用途:这种方式通常用于你不确定参数是否存在的情况,并且你希望在参数缺失时提供一个默认值。

    params.require(:articles).permit({})

    • 功能:require 方法确保 :articles 参数存在于 params 中。如果不存在,Rails 将抛出 ActionController::ParameterMissing 异常。permit({}) 方法用于指定哪些属性是允许的(在这个例子中,没有任何属性被允许)。
    • 用途:这种方式用于强制性地确保某些必需的参数存在,并用于强参数(Strong Parameters)以指定允许的属性,从而防止批量赋值漏洞。

    总结

    • fetch 用于在找不到参数时提供默认值,而不会引发错误。
    • require 是用于确保参数存在,并与 permit 结合使用以过滤允许的参数。

    在实际开发中,如果你需要控制和验证输入参数的存在和安全性,通常使用 require 和 permit 组合。而 fetch 常用于需要灵活处理参数的情况。