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 真的足够聪明,可以识别这些特定关键字 index
、new
、create
、destroy
、show
、edit
、和 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 时,表单的提交将触发创建动作。因此,在创建操作中,您应该编写触发模型保存记录所需的所有代码。
此外,也请阅读此文档,
我正在重新阅读 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 真的足够聪明,可以识别这些特定关键字 index
、new
、create
、destroy
、show
、edit
、和 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 时,表单的提交将触发创建动作。因此,在创建操作中,您应该编写触发模型保存记录所需的所有代码。
此外,也请阅读此文档,