Rails RESTful 创建用户的控制器操作

Rails RESTful controller action to create User

我正在重新阅读 rails 提供的 railstutorial the second time for clarity. I was trying to understand RESTful resources,其中列出了具有相应控制器操作的各种 HTTP 请求:index、show、new、create、edit、update、销毁.

我从来没有真正完全理解 rails 控制器是如何工作的,我想澄清一下。如果我创建一个 users_controller.rb 并想创建新用户, 就是这样 。我不关心重定向、即时消息和其他技巧。我只想创建新用户并将其保存在我的数据库中。

我想User.create(name: "Iggy1", email: "letsmail@iggy.com")。假设我进行了迁移并且我在数据库架构上有 name(字符串)和 email(字符串)。

users_controller.rb 上创建用户所需的最少代码行是多少?

我问这个问题的原因到现在为止,我仍然不能 100% 确定哪一行代码实际执行了所需的操作。 rails 真的足够聪明,可以识别这些特定关键字 indexnewcreatedestroyshowedit、和 update,还是它们是任意的?如果 rails 足够聪明,仅通过列出方法 (def destroy; #<no code>; end) 就能检测到这七个关键字,是否可以自动访问 DELETE 用户方法,或者我实际上必须说 def destroy; User.find(params[:id]).destroy; end 才能使用 DELETE user方法?在 users_controller.rb 上,我从 rails 教程中得到了这个详尽的代码。

...
  def create
    @user = User.new(user_params)
    if @user.save
      @user.send_activation_email
      flash[:info] = "Please check your email to activate your account."
      redirect_to root_url
    else
      render 'new'
    end
  end
...

仅 Users_controller 上的 def create 是否足以让 rails 创建用户?

def create
end

或者我至少需要 User.new,或更多代码才能创建新用户?

您需要创建用户的第一件事是在您的 UsersController 中执行 'new' 操作,如下所示:

class UsersController < ApplicationController

  def new
      @user = User.new
  end

end

当您声明上述方法定义时,Rails 将期望一个名为 'new.html.erb' 的文件,除非您告诉它呈现另一个模板。

注意:我会假设您不想这样做,但如果您这样做了,您可以将 render 'other' 添加到 'new' 方法的末尾(其中'other' 是文件 'other.html.erb'):

由于您的目标是创建一个新的用户实例,此视图模板将需要一个表单来添加名称和电子邮件字段。虽然并非所有 Rails 表单都需要,但创建用户的一种常见方法是创建一个 'new'(即未保存)用户实例并将其传递给表单,以便表单知道用户的哪些属性已。 Rails 将这个实例变量传递给视图,它也知道要渲染哪个视图文件(因为你定义的 'new' 方法应该与包含的 'new.html.erb' 视图模板同名表格)。这也是 Rails 知道表单的 'submit' 按钮应该显示为 'Create user'.

的方式

假设您已完成上述操作,下一步是为单击表单的 "Submit" 按钮后要发送的表单数据添加一个位置。这就是 'create' 动作的作用。换句话说,'new' 动作负责在浏览器中显示表单,而 'create' 动作负责处理该表单提交的数据。此时您需要添加的最少代码如下:

def create
  @user = User.create(user_params)
end

Rails 执行此操作的方式是通过它实现的一种特殊方法,称为 'params'。在幕后,Rails 接受您提交表单时发生的 HTTP 请求,并将某些数据存储在 ActionController::Parameters 对象中。然后,此数据由 'user_params' 方法(您需要声明;见下文)处理,并且只有您在该方法定义中列入白名单的参数(即 'name' 和 'email' ) 被返回。

这意味着您需要实现 'user_params' 方法定义。这通常作为 UsersController 底部的私有方法完成,因为您不希望此方法在控制器外部可用。所以你要添加以下内容:

private

def user_params
  params.require(:user).permit(:name, :email)
end

从安全的角度来看这很重要,因为恶意用户可能会在他们的浏览器中添加新的表单元素(例如,名为 'admin' 的元素)并单击 'submit'。如果您的用户模型确实包含 'admin' 属性,则该恶意用户刚刚创建了一个管理员用户(具有相应的管理员权限)。

最后,由于表单发送的请求是 POST 请求(不是获取请求),Rails 希望您提供一个视图,以便在用户提交表单后发送给他们.此视图通常是您刚创建的用户的 'show.html.erb' 模板,因为 'create' 没有自己的模板(请记住,我们讨论的表单是'edit' 操作,而不是 'create' 操作)。 'show' 视图通过以下方法呈现:

def show
end

此外,您需要告诉 Rails 在 'create' 操作完成后重定向到 'show' 页面。将此添加到 'create' 方法的末尾:

  redirect_to @user

由于您传递了用户 class 的单个实例,Rails 推断您想要重定向到 'show' 操作(与 'index' 或某些其他操作)的用户控制器。根据传递给 "redirect_to" 方法的内容,您可以将用户发送到任意数量的目的地。有关详细信息,请参阅 these docs

所以总而言之,除了 'edit.html.erb' 和 'show.html.erb' 视图模板以及 'config/routes.rb' 文件中的路由声明(我没有详细讨论,因为问题范围仅限于 UsersController),您的 UsersController 应具有的最少代码量如下:

class UsersController < ApplicationController

    def new
        @user = User.new
    end

    def create
        @user = User.create(user_params)
        redirect_to @user
    end

    def show
    end

    private

    def user_params
        params.require(:user).permit(:name, :email)
    end
end

您必须了解 rails 是建立在 MVC 和 REST 之上的。 MVC 是一种分配项目责任的架构模式。

M - 模型,与数据库交互,是实现业务逻辑的理想场所。

V - 视图,HTML 渲染发生的地方

C - 控制器,基本上桥接 M 和 V 之间的通信。

所以,基本上当最终用户访问您的域时,请求会到达网络服务器,然后到达 rails API。 rails API 会知道传输请求的默认控制器,默认控制器操作会 return html 输出。

config/routes.rb

中的默认路由器
root to: 'controller#action'

同样 rails 理解 5 个 HTML 方法,它们是 GET、POST、PUT、DELETE 和 PATCH。因此,一旦您创建了控制器并将 routes.rb 中的引用设置为 resources [controller_name],那么 rails 路由将为您的 8 个默认操作中的每一个创建 8 个 urls控制器。举个例子,假设你的控制器是 users_controller.rb 然后,你在 routes.rb 中将它设置为 resources :users 这将允许以下方法,

users     GET    /users(.:format)                        users#index
          POST   /users(.:format)                        users#create
new_user  GET    /users/new(.:format)                    users#new
edit_user GET    /users/:id/edit(.:format)               users#edit
user      GET    /users/:id(.:format)                    users#show
          PATCH  /users/:id(.:format)                    users#update
          PUT    /users/:id(.:format)                    users#update
          DELETE /users/:id(.:format)                    users#destroy

因此,当您构建视图并将 form_for url 设置为 users_path 并将 http 方法设置为 POST 时,表单的提交将触发创建动作。因此,在创建操作中,您应该编写触发模型保存记录所需的所有代码。

此外,也请阅读此文档,

http://guides.rubyonrails.org/routing.html