【问题标题】:Rails RESTful controller action to create UserRails RESTful 控制器操作以创建用户
【发布时间】:2016-07-23 18:21:09
【问题描述】:

为了清楚起见,我第二次重新阅读railstutorial。我试图理解 rails 提供的RESTful resources,它列出了各种 HTTP 请求以及相应的控制器操作:index、show、new、create、edit、update、destroy。

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

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

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

我问这个问题的原因直到现在,我仍然不能 100% 确定哪个代码行实际执行了所需的操作。 rails 真的足够聪明,可以识别这些特定的关键字indexnewcreatedestroyshoweditupdate,还是它们是任意的?如果 rails 足够聪明,可以检测到这七个关键字,只需列出方法 (def destroy; #<no code>; end),DELETE 用户方法是否会自动访问,或者我必须实际说 def destroy; User.find(params[:id]).destroy; end 才能使用 DELETE 用户方法?在 users_controller.rb 上,我最终从 railstutorial 获得了这个精心设计的代码。

...
  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,或者更多代码来创建新用户?

【问题讨论】:

    标签: ruby-on-rails rest controller railstutorial.org


    【解决方案1】:

    您需要创建用户的第一件事是在您的 UsersController 中创建一个“新”操作,如下所示:

    class UsersController < ApplicationController
    
      def new
          @user = User.new
      end
    
    end
    

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

    注意:我将继续假设您不想这样做,但如果您这样做了,您将在“新”方法的末尾添加 render 'other'(其中“其他”是文件'other.html.erb'):

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

    假设您具备上述条件,下一步是添加一个位置,以便在您单击表单的“提交”按钮后发送表单数据。这就是“创建”操作的作用。换句话说,“新建”动作负责在浏览器中显示表单,“创建”动作负责处理该表单提交的数据。此时您需要添加的最少代码如下:

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

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

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

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

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

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

    def show
    end
    

    此外,您需要告诉 Rails 在“创建”操作完成后重定向到“显示”页面。将此添加到“创建”方法的末尾:

      redirect_to @user
    

    由于您传递了 User 类的单个实例,Rails 推断您希望重定向到 User 控制器的“显示”操作(而不是“索引”或其他操作)。根据您传递给“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
    

    【讨论】:

    • 非常感谢@toomanyrichies。这是我需要知道的。巧合的是,其他回答者提到了路由。通过这 2 个信息,我了解了有关资源的大量信息
    【解决方案2】:

    您必须了解 Rails 是基于 MVC 和 REST 构建的。 MVC 是一种分配项目责任的架构模式。

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

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

    C - 控制器,基本上是 M 和 V 之间的沟通桥梁。

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

    config/routes.rb 中的默认路由器

    root to: 'controller#action'
    

    同样,rails 理解 5 种 HTML 方法,即 GET、POST、PUT、DELETE 和 PATCH。因此,一旦您创建了一个控制器并将 routes.rb 中的引用设置为 resources [controller_name],那么 rails 路由将为控制器中的 8 个默认操作中的每一个创建 8 个 url。例如,假设您的控制器是 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

    【讨论】:

    • 很好的解释!谢谢@Pragash。快速提问:路由只负责 URL 生成,对吗? users#create 响应 users_controller.rbcreate 方法。我对上表中的 create 的解释是在 Web 应用程序上生成 /users(.:format) 链接,它执行create 方法所说的任何操作,如 users_controller 的 create 方法中所定义。对吗?
    • 实际上路由可以将 URL 映射到控制器操作。所以,如果你调用 POST 方法 users_path 它将调用 users_controller.rb 文件中的创建操作。然后,您可以在create方法中编写代码来生成新用户。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多