如何使用相同的表单在 ruby​​ on rails 中创建和编辑

Posted

技术标签:

【中文标题】如何使用相同的表单在 ruby​​ on rails 中创建和编辑【英文标题】:How to use the same form for creating and editing in ruby on rails 【发布时间】:2015-08-14 11:02:41 【问题描述】:

我是红宝石新手。我有相同的表格,但我需要它在需要时执行创建/更新。我现在遇到的问题是,每当我调用编辑而不是编辑现有用户的详细信息时,我都会得到一个具有已编辑详细信息的新用户。简而言之,我认为每当我执行编辑时,都会调用 create 方法。

那么有什么方法可以同时使用单一表单来新建和编辑,而不是使用单独的表单。

以下代码用于编辑用户详细信息:

         <%= link_to 'Home', root_path %>
        <h2>Edit user</h2>
        <%= form_for :user, url: user_index_path do |f| %>
          <p>
            <%= f.label :name %><br>
            <%= f.text_field :name %>
          </p>

          <p>
            <%= f.label :address %><br>
            <%= f.text_area :address %>
          </p>
         <p>
            <%= f.label :email %><br>
            <%= f.text_field :email %>
          </p> 
         <p>
            <%= f.label :phone %><br>
            <%= f.text_field :phone %>
          </p>
          <p>
            <%= f.label :state %><br>
            <%= f.text_field :state %>
          </p>
          <p>
            <%= f.label :country %> 
            <%= f.collection_select(:country, Country.all, :name, :name) %>
          </p>
          <p>
            <%= f.submit %>
          </p>
        <% end %>

以下代码用于创建用户:

        <%= link_to 'Home', root_path %>
    <h2>Create new user</h2>
    <%= form_for :user, url: user_index_path do |f| %>
      <p>
        <%= f.label :name %><br>
        <%= f.text_field :name %>
      </p>

      <p>
        <%= f.label :address %><br>
        <%= f.text_area :address %>
      </p>
     <p>
        <%= f.label :email %><br>
        <%= f.text_field :email %>
      </p> 
     <p>
        <%= f.label :phone %><br>
        <%= f.text_field :phone %>
      </p>
      <p>
        <%= f.label :state %><br>
        <%= f.text_field :state %>
      </p>
      <p>
        <%= f.label :country %> 
        <%= f.collection_select(:country, Country.all, :name, :name) %>
      </p>
      <p>
        <%= f.submit %>
      </p>
    <% end %>

这是我的控制器:

      class UserController < ApplicationController
    def index
        @users = User.all

    end

    def show
    @user = User.find(params[:id])
  end

    def new
        @user = User.new
    end


    def create
    @user = User.new(user_params)
        if @user.save
            redirect_to @user
        else
            render 'new'
        end 
    end

  def edit

    @user = User.find(params[:id])


  end

    def update
    #@user = User.find(params[:id])
        if @user.update(user_params)
        redirect_to @user
    else
      render 'edit'
    end
    end

    def destroy
    @user = User.find(params[:id])
    @user.destroy
      redirect_to user_index_path
  end

    private
    def user_params
        params.require(:user).permit(:name, :address, :email, :phone, :state, :country)
    end

end

由于我是 ruby​​ 新手,我没有得到关于 http 请求如何在 ruby​​ 中运行的确切细节。

【问题讨论】:

你需要把&lt;%= form_for :user, url: user_index_path do |f| %&gt;改成&lt;%= form_for @user, url: user_index_path do |f| %&gt; 现在我收到一个错误。 "没有路由匹配 [PATCH] "/user"" 请粘贴您的routes 您需要在更新操作中取消注释此行@user = User.find(params[:id]) 带有操作帖子的方法索引将始终调用控制器的创建方法,因此请按照我在回答中所做的更改 【参考方案1】:

用户/_form.html.erb

  <%= link_to 'Home', root_path %>
  <%= form_for @user do |f| %>
  <p>
  <%= f.label :name %><br>
  <%= f.text_field :name %>
  </p>

  <p>
  <%= f.label :address %><br>
  <%= f.text_area :address %>
  </p>
  <p>
  <%= f.label :email %><br>
  <%= f.text_field :email %>
  </p> 
  <p>
  <%= f.label :phone %><br>
  <%= f.text_field :phone %>
  </p>
  <p>
  <%= f.label :state %><br>
  <%= f.text_field :state %>
  </p>
  <p>
  <%= f.label :country %> 
  <%= f.collection_select(:country, Country.all, :name, :name) %>
  </p>
  <p>
  <%= f.submit %>
  </p>
  <% end %>

用户/new.html.erb

<h2>Create new user</h2>
<%= render 'form' %>

用户/edit.html.erb

<h2>Edit user</h2>
<%= render 'form' %>

users_controller.rb

class UsersController < ApplicationController
  before_filter :find_user, only: [:show, :edit, :update, :destroy]
  def index
    @users = User.all
  end

  def show    
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user
    else
      render 'new'
    end 
  end

  def edit
  end

  def update
    if @user.update(user_params)
      redirect_to @user
    else
      render 'edit'
    end
  end

  def destroy
    @user.destroy
    redirect_to user_index_path
  end

  private
  def user_params
    params.require(:user).permit(:name, :address, :email, :phone, :state, :country)
  end

  def find_user
    @user = User.find(params[:id])
  end

end

当您有两个或多个方法的相同视图代码时,您应该创建相同视图代码的一部分并在这些方法中呈现它。这在 ruby​​ on rails 中称为 DRY 原则

【讨论】:

感谢您让我知道这件事。我会确保我以后不会重复代码。但我仍然需要解决我的问题。 你现在有什么问题? 每当我执行“编辑”时,都会创建一个新条目而不是编辑现有条目 我应该粘贴整个日志吗?? 开始 GET "/user/40/edit" for 127.0.0.1 at 2015-06-01 10:53:49 +0530 UserController#edit 作为 HTML 参数处理:"id"=> "40" [1m[36mUser Load (0.2ms)[0m [1mSELECT users.* FROM users WHERE users.id = 40 LIMIT 1[0m [1m[35mCountry Load (0.2ms)[ 0m SELECT countries.* FROM countries 渲染用户/_form.html.erb (6.2ms) 在布局/应用程序中渲染用户/edit.html.erb (7.5ms) 在 36ms 内完成 200 OK (查看: 34.7ms |活动记录:0.3 毫秒)

以上是关于如何使用相同的表单在 ruby​​ on rails 中创建和编辑的主要内容,如果未能解决你的问题,请参考以下文章

如何使用用户定义的字段数制作表单? - Ruby on Rails

如何使下拉表单在 Ruby On Rails 中工作

Ruby on Rails - 在填写表单时更新 collection_select

如何在 Ruby on Rails 中裁剪图像

如何使用 Ruby on Rails 5 将数据从 URL 提取到表单中

Angular.js 与 Ruby On Rails 表单的集成