如何创建一个表单来更新所选记录的字段值?

How do I create a form that will update the value of a field for selected records?

我正在使用来自索引页的 link,该页有一组我需要一次全部更新的嵌套记录(行)。 link 转到我需要更新嵌套记录(棱镜)属性的编辑操作。

  1. 我尝试对嵌套模型使用 simple_form gem 方法。当我只希望一个字段为所有对象输入一个值时,它为我提供了一个用于所有对象的字段。该构建器看起来可用,但我不知道如何使用它来更新字段。不管怎样,表格都不对。

  2. 我已经尝试了 form_for 和 fields_for 我能在 Google 上找到的所有变体来开发编辑表单。看来我是地球上唯一一个试图解决这个问题的人。

这是我设置路线的方式:

resources :gardens, shallow: true do
    resources :prisms
    resources :rows

这是我的花园模型现在的样子:

class Garden < ApplicationRecord
  mount_uploader :picture, ImageUploader
  belongs_to :user
  has_one :photo
  has_many :rows, :dependent => :destroy
  has_many :prisms
  geocoded_by :address
  after_validation :geocode
  after_commit :populate_garden!

def id
    self[:id]
  end

  def populate_garden!
    # row 0
    (0..length-1).each do |i|
      Row.create(row_num: i, garden_id: id)
    end
  end
end

花园模型通过 populate_garden 创建我的行!方法。

这是行模型:

class Row < ApplicationRecord
  belongs_to :garden
  has_many :prisms, :dependent => :destroy
  accepts_nested_attributes_for :prisms
  after_commit :populate_rows

  def id
    self[:id]
  end


  def populate_rows
    # row 0
    (0..garden.width-1).each do |i|
        Prism.create(:row_id => self.id, :row_num => self.row_num, :col_num => i, :garden_id => self.garden_id)
    end
  end
end

行模型在 populate_rows 方法中创建棱柱。

棱镜模型如下:

class Prism < ApplicationRecord
  belongs_to :row
  belongs_to :garden

  include RankedModel
  ranks :column_order
end

这是我 index.html.erb 中的 table,我点击它打开了编辑操作。

<table>

    <% @rows.each_with_index do |gardenrow, index| %>
      <% @rows.select { | row | row.row_num == index}.each do |row| %>

        <td class="prism-cols">
          <%= link_to 'Edit Row', edit_row_path(row), class:"dark-link" %>
          <br /><i class="fas fa-arrow-down"></i>
        </td>

      <% end %>
    <% end %>
</table>

该行很好地传递到编辑操作中,但我目前的格式不正确:

<h1>The row brought into this form page is: </h1>
<%= @row.inspect %>

<div class="container">
  <%= simple_form_for @row do |m| %>
    <%= m.simple_fields_for :prisms do |p| %>
      <%= p.input :crop_name %>
    <% end %>
    <%= m.button :submit %>
  <% end %>
</div>

rows_controller 更新方法如下所示:

def update
    @row = Row.find(params[:row_id])
    @row.prisms.build
    redirect_to root_path
end

我需要一个用于 crop_name 的表单字段,它将通过一次提交更改所选行中的所有棱镜。通过棱镜上的编辑操作,我一次更新一个棱镜没有任何问题。我遇到的困难是在特定行内嵌套棱镜。

在我下面的导师的帮助下,我能够开发一个与控制器一起工作的表单来完成这项工作。这是更新后的代码,供以后解决此类问题使用。

表单数据如下:

<%= form_tag({controller: "rows", action: "update"}, method: "patch") %>
    <%= label_tag(:crop_name, "Crop Name") %>
    <%= text_field_tag(:crop_name) %>
    <%= hidden_field_tag(:row_id, @row.id) %>
    <%= submit_tag("submit") %>

控制器更新方法如下:

def update
    @row = Row.find(params[:id])
    @garden = Garden.find_by_id(:garden_id)
    @row.prisms.each do |p|
      p.crop_name = params[:crop_name]
      p.save!
    end
    redirect_to :controller => 'gardens', :action => 'show', id: @row.garden_id
  end

感谢您的帮助。我认为我无法仅从文档中弄清楚这一点。

如果我理解正确,我认为 simple_form 可能限制了您。一个基本的 ruby 表单可以满足您的需求。我不是 100% 确定在嵌套字段上执行 simple_form 的最佳方法是什么,但 this Whosebug answer 可能会提供更多帮助。

使用基本的 ruby 形式 您想要一个只有一个字段的表单。提交时,它将从提交的表单中获取值并更新该行所有棱镜的字段。对于这种情况,我建议深入研究 basics of ruby forms,然后执行类似的操作。

// html.erb

<%= form_tag({controller: "rows", action: "update_prism_crop_name"}, method: "post", class: "nifty_form") %>
  <%= label_tag(:crop_name, "Crop name") %>
  <%= text_field_tag(:crop_name) %>
  <%= hidden_field_tag(:row_id, @row.id) %>
  <%= submit_tag("Submit") %>
<% end %>


// rows_controller

def update_prism_crop_name
   @row = Row.find(params[:row_id])
   @row.prisms.each do |prism|
      prism.crop_name = params[:crop_name]
      prism.save!
   end
   # other redirect stuff
end

form_tag 明确调用了一个操作,但我不得不想象您还需要为这个自定义操作构建一个路由。

我还没有测试过这些,我对 rails 有点生疏,但我相信这样的事情会奏效。