Rails的新手,试图弄清楚如何将参数从视图传递到表单,然后传递到控制器,或者很可能是找到一种为新对象分配外键的更好方法。我有一个链接到特定插座对象的按钮,该按钮允许用户创建与该插座关联的新设备对象。我的设备表上有一个外键指向插座ID。
<%= button_to 'Add Device', new_device_path, :method => :get, params: {:oulet_id => outlet.id} %>
在new_device_path
随后经历new.html.erb
:
<h1>Add New Device to Outlet</h1>
<%= render 'form' %>
<%= button_to 'Back', grows_path, :method => :get %>
然后继续 _form.html.erb:
<%= form_with model: @device, local: true do |form| %>
<% if @device.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(device.errors.count, "error") %> prohibited this device from being saved:</h2>
<ul>
<% @device.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= form.label :title %><br />
<%= form.text_field :title %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
问题是,new.html.erb
我收到的params[:oulet_id]
不是表格,而是我的表格,因此我无法将其传递给控制器,在控制器上我可以将oulet_id
新设备上的条目设置为特定的插座。
以前,我已经能够直接从表单传递自定义参数,并在控制器上处理它们,并完成我的要求。但是,在这种情况下,我想尝试将参数传递给多个页面,因为这不是正确的方法……我应该如何做到这一点?
这是简单的解决方案,在您当前的应用程序中需要最少的更改。
您可以在设置属性#新的方法DevicesController并把它传递到形式,像这样的隐藏字段:
class DevicesController < ApplicationController
def new
@device = Device.new(outlet_id: params[:outlet_id])
end
end
现在将一个隐藏字段添加到窗体。这对于保留和发送outlet_id
到表单路径(在这种情况下POST /devices/:id
)是必要的。为了简单起见,我省略了错误处理部分。
<%= form_with model: @device, local: true do |form| %>
<%= form.hidden_field :outlet_id %>
<p>
<%= form.label :title %><br />
<%= form.text_field :title %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
不要忘记在DevicesController#device_params方法中将新参数列入白名单,否则它将无法保存。
注意:如果下面的“ Rails指南”链接没有跳到正确的锚点。命中Ctrl+L比Enter访问该网站时。他们在某些网络浏览器中的锚点发生了一些奇怪的事情。
更好的方法是使用嵌套资源,但这需要进行结构上的更改。首先在routes.rb
文件中添加嵌套路由:
resources :outlets do
resources :devices, shallow: true
end
这将创建以下路线:
+-----------+---------------------------------+-------------------+------------------------+
| HTTP Verb | Path | Controller#Action | Named Helper |
|-----------|---------------------------------|-------------------|------------------------|
| GET | /outlets | outlets#index | outlets_path |
| GET | /outlets/:id | outlets#show | outlet_path |
| GET | /outlets/new | outlets#new | new_outlet_path |
| GET | /outlets/:id/edit | outlets#edit | edit_outlet_path |
| POST | /outlets | outlets#create | outlets_path |
| PATCH/PUT | /outlets/:id | outlets#update | outlet_path |
| DELETE | /outlets/:id | outlets#destroy | outlet_path |
| GET | /outlets/:outlet_id/devices | devices#index | outlet_devices_path |
| GET | /devices/:id | devices#show | device_path |
| GET | /outlets/:outlet_id/devices/new | devices#new | new_outlet_device_path |
| GET | /devices/:id/edit | devices#edit | edit_device_path |
| POST | /outlets/:outlet_id/devices | devices#create | outlet_devices_path |
| PATCH/PUT | /devices/:id | devices#update | device_path |
| DELETE | /devices/:id | devices#destroy | device_path |
+-----------+---------------------------------+-------------------+------------------------+
现在before_action
,在控制器中添加一个回调,以及为#new
和构建新实例的新方法#create
:
class DevicesController < ApplicationController
before_action :set_device, on: %i[show edit update delete] # already present
before_action :set_outlet, on: %i[index new create] # new
def new
# for outlet has_many devices
@device = @outlet.devices.build
# for outlet has_one device
@device = @outlet.build_device
end
def create
# for outlet has_many devices
@device = @outlet.devices.build(device_params)
# for outlet has_one device
@device = @outlet.build_device(device_params)
# followed by your normal create stuff
end
# code...
private
def set_devise # already present
@device = Device.find(params[:id])
end
def set_outlet # new
@outlet = Outlet.find(params[:outlet_id])
end
# code ...
end
现在删除params param并将按钮的路径更改为:
<%= button_to 'Add Device', new_outlet_device_path(outlet), method: :get %>
现在,最后要做的是更改表单的url,使其指向#create和#update的正确路径。为此,将表单创建行更改为:
<%= form_with model: [@outlet, @device].compact, local: true do |form| %>
在Rails中将数组传递给表单助手通常会设置嵌套路径。我调用#compact以确保表单在编辑时能正常工作。因为在编辑设备时@outlet
未设置导致[nil, #<Device...>]
。调用#compact时,nil
值将从数组中删除。
这将导致以下请求:
POST /outlets/:outlet_id/devices
对于新设备PUT /devices/:id
对于现有设备本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句