ruby-on-rails - Ruby on Rails Controller 设计

标签 ruby-on-rails

当我查看 Rails Controller 的示例时,我通常会看到如下内容:

class WidgetController < ActionController::Base

  def new
    @widget = Widget.new
  end

  def create
    @widget = Widget.new(params[:id])
    if @widget.save
      redirect_to @widget
    else
      render 'new'
    end
  end
end

这可行,但有几个问题:

路线

如果我将小部件添加到我的routes.rb 文件中:

Example::Application.routes.draw do
  resources :widgets
end

GET/widgets/new 将路由到 newPOST/widgets 将路由到 create

如果用户在新的小部件页面上输入不正确的信息并提交,他们的浏览器将显示带有 /widgets 的 URL,但将呈现新模板。如果用户为页面添加书签并稍后返回或刷新页面,则将调用索引操作而不是新操作,这不是用户所期望的。如果没有索引操作或者用户没有查看它的权限,则响应将为 404。

代码重复

作为一个人为的例子,假设我的新方法中有一些棘手的逻辑:

def new
  @widget = Widget.new
  do_something_tricky()
end

使用当前方法,我会在 newcreate 中复制该逻辑。我可以从 create 调用 new,但随后我必须修改 new 来检查 @widget 是否为定义:

def new
  @widget ||= Widget.new
  do_something_tricky()
end

另外,这感觉不对,因为它降低了 Controller 操作的正交性。

做什么?

那么解决这个问题的Rails 方式是什么呢?我应该重定向到 new 而不是渲染新模板吗?我应该在 create 内部调用 new 吗?我应该忍受它吗?有更好的办法吗?

最佳答案

我不认为这在“rails 方式”中是一个问题,并且没有内置功能可以在不弄脏您的手的情况下允许这样做。当用户为刚刚提交且有错误的表单添加书签时,他们期望什么?用户不知道更多,他们不应该为失败的表单添加书签。

我认为重定向到 new_widget_path 是最干净的解决方案。但是,您应该保留错误并将其显示在表单上。为此,我建议您将参数保留在 session 中(我希望它比序列化的 Widget 对象小)。

def new
  @widget = widget_from_session || Widget.new 
end

def widget_from_session
  Widget.new(session.delete(:widget_params)) if session[:widget_params].present?
end
private :widget_from_session

# Before the redirect
session[:widget_params] =  params

代码是不言自明的,只有当 widget_from_session 返回 nil 时才会调用 Widget.new ,此时 session[:widget_params] 存在。对哈希调用 delete 将返回删除的值并将其从原始哈希中删除。

更新选项 2 使用ajax提交表单怎么样?您的 Controller 可以受益于:

  respond_to :html, :json

  ...

  def create
    @widget = Widget.new params[:widget]
    @widget
    respond_with @widget, location: nil
  end

根据响应代码(由 Rails 设置:201 Created 或 422 Unprocessable Entity),您可以显示错误(验证失败时在响应正文中可用)或将用户重定向到 @widget

这就是 StackOverflow 的做法:https://stackoverflow.com/questions/ask 。他们异步提交表单。

关于ruby-on-rails - Ruby on Rails Controller 设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15193081/

相关文章:

ruby-on-rails - 如何为 Rails 上的 Stripe 结账编写集成测试?

javascript - 用于需要数据输入和存储为数据库表的 Web 应用程序的 JS/Ruby

ruby-on-rails - 选择带有预加载的特定列

ruby-on-rails - 在运行时编译 SCSS?

javascript - 如何创建一个可以从 Javascript 数组中选择的选择选项?

ruby-on-rails - 从事件记录中的数据库中删除线程评论的有效方法是什么?

ruby-on-rails - Rails 多对多 SQLite3 错误

jquery - 用于 JS 和 HTML 渲染的 Rails 布局

ruby-on-rails - rails POST on/objects 调用索引方法

javascript - 如果在 Handlebars.js 中预编译自定义助手,如何注册自定义助手?