ruby-on-rails Rails CRUD路由和控制器方法最佳实践

5ktev3wc  于 2023-10-21  发布在  Ruby
关注(0)|答案(1)|浏览(136)

CRUD代表创建、读取、更新和删除。这是四种方法(如果区分查看一条记录和查看所有记录,则是五种方法)。在Rails中,处理CRUD的规范方法似乎涉及七个方法。例如,使用resources :orders简写为Order对象创建路由会生成以下七个路由:

  • 指数
  • 创建
  • 显示
  • 编辑
  • 更新
  • 摧毁

这就是我困惑的根源。为new/createedit/update分别设置操作/路由有什么意义?使用单独的操作查看页面与在数据库中创建记录?我理解Rails中是如何做到这一点的,例如:

class OrdersController < ApplicationController
  def new
    @order = Order.new
    render
  end

  def create
    @order = Order.new(order_params)
    if @order.save
      redirect_to @order, notice: 'Successfully created an order.'
    else
      render :new
    end
  end
end

在使用Rails之前,我使用Yii(PHP),它有一个内置的CRUD生成器,可以生成这样的代码(翻译成Rails):

class OrdersController < ApplicationController

  def create

    if request.method == "POST"
      @order = Order.new(order_params)
      if @order.save
        redirct_to @order, notice: 'Successfully created an order.'
      end
    else
      @order = Order.new
    end

    render 

  end
end

我更喜欢这种模式的原因是,它避免了为不同的控制器动作呈现模板。在第一个代码示例中,用户访问orders/new并发布到orders/create。如果验证失败,用户仍然停留在orders/create,但查看orders/new的模板。这可能会让用户感到困惑,而且似乎也违背了将查看页面的操作与在数据库中创建记录。如果您重定向到orders/new而不是使用render :new,那么您将丢失所有验证错误消息。
我发现自己在Rails代码中下意识地回到了Yii的方式。谁能解释一下为什么标准方法是有利的?如果我偏离了规范的Rails模式,会遇到什么问题吗?
StackOverflow警告我,这个问题是主观的,可能会被关闭,所以让我澄清一下。我不想讨论Rails与Yii或确定组织CRUD代码的最佳理论方法。我想知道,如果我偏离了Rails处理CRUD的规范方式,Rails是否会有什么问题。

ao218c7q

ao218c7q1#

简单的解释是:
因为这是上帝和DHH的本意
Rails的CRUD约定非常实用,允许您避免许多与浏览器缓存和安全性相关的陷阱。
让我们举一个例子:

# config/routes.rb
resources :users, only: [:new, :create]

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      sign_in(@user)
      redirect_to root_path
    else
      render :new
    end
  end

  private 
    def user_params
      params.require(:user).permit(:email, :password, :password_confirmation)
    end
end

这里我们有两个独立的路由GET /users/newPOST /users
第一个路由是幂等的-它应该对任何访问者看起来都是一样的,并且可以被缓存。第二个不是-它应该显示创建或尝试创建资源的结果。
当用户访问/users/new时,我们将表单POST到不同的URI。这避免了客户端的历史问题。
如果输入无效,我们也会在同一个请求周期中呈现表单。这避免了在重定向中将表单数据传递回/users/new时可能出现的安全问题,并让我们返回语义正确的响应代码,而不是重定向。
它还确保我们的应用程序在REST意义上是无状态的,因为如果我们访问/users/new,前面的操作不会影响我们看到的内容。
在体系结构级别上,它允许您利用约定而不是配置。你可以这样做:

def new
  @user = User.new
end

它将呈现views/users/new.html.erb,因为Rails可以推导出新操作应该呈现新模板。从设计和测试的Angular 来看,让每个控制器动作执行一个任务要好得多,因为它消除了在同一方法中测试两个单独代码路径的需要。

相关问题