我正在学习Rails,并希望能够在同一页面上使用相同的表单来添加元素(此处为“剂量”)或通过预填充表单来编辑现有元素(刷新页面后,我不需要动态地进行操作。)
这是页面的屏幕截图(views / cocktails / show.html.erb)
创建新的“剂量”效果很好,但是尝试编辑Rails时会出现“ DosesController#edit缺少此请求格式和变体的模板” 错误。
当我试图真正理解路线逻辑时,我这样做只是为了学习,即使这可能是一个不好的做法,我也只想通过Rails来实现。
>视图/剂量/_form.html.erb:
我将逻辑放入部分表单中,以决定是创建还是更新@dose:
<% if @dose.new_record? %>
<%= simple_form_for [@cocktail, @dose] do |f| %>
<%= f.input :description %>
<%= f.association :ingredient %>
<%= f.button :submit %>
<% end %>
<% else %>
<%= simple_form_for @dose, url: url_for("doses#update") do |f| %>
<%= f.input :description %>
<%= f.association :ingredient %>
<%= f.button :submit %>
<% end %>
<% end %>
视图/鸡尾酒/show.html.erb:
我正在调用“新的或编辑的”路径助手,将剂量ID和剂量ID传递给它,因为剂量属于一种鸡尾酒。
<% @cocktail.doses.each do |dose| %>
<li>
<h4><%= dose.description %> - <%= dose.ingredient.name %></h4>
<%= link_to "<i class=\"fas fa-pencil-alt\"></i>".html_safe, new_or_edit_dose_path(@cocktail.id, dose.id) %>
<%= link_to "<i class=\"far fa-trash-alt\"></i>".html_safe, dose_path(dose.id), method: :delete, data: {confirm: "Are you sure?"} %>
</li>
<% end %>
</ul>
<%= render "doses/form" %>
<%= link_to "Back", cocktails_path %>
</div>
routes.rb
此路径帮助程序绑定到GET路径,该路径与剂量控制器的编辑操作相关联。因此,我根本不会使用“ doses#new”路线操作。
root to: "cocktails#index"
resources :cocktails, only: [:index, :show, :new, :create] do
resources :doses, only: [ :create]
end
resources :doses, only: [ :update, :destroy]
get "cocktails/:id/doses/:dose_id", to: "doses#edit", as: :new_or_edit_dose
doses_controller.rb
def edit
@cocktail = Cocktail.find(params[:id])
@dose = Dose.find(params[:dose_id])
end
def update
if @dose.update(set_params)
redirect_to cocktail_path(@dose.cocktail)
else
render(:edit)
end
end
def set_params
params.require(:dose).permit(:description, :ingredient_id)
end
我对问题的理解
我想问题是我正在使用鸡尾酒/:id /剂量/:id途径,但是在鸡尾酒/:id /显示视图上显示表格。我已经尝试在dose#edit的末尾使用redirect_to并将其传递给params,但是它没有用。
有人可以告诉我是否可行,并提示我应该寻找什么?
答案 0 :(得分:2)
关于
...但是在尝试编辑Rails时会引起DosesController#edit缺少此请求格式和变体的模板
...表示您缺少文件app/views/doses/edit.html.erb
。因此,只需创建该文件,或...因为您说过...
我想问题是我正在使用鸡尾酒/:id /剂量/:id路线,但是在鸡尾酒/:id /显示视图上显示表单
...,如果正确理解,您希望此URL cocktails/:id/doses/:id
显示与您的cocktails/:id/
完全相同的页面(大概映射到您的cocktails#show
页面,那么您可以请执行以下操作:
app / controllers / doses_controller.rb:
# ...
def edit
@cocktail = Cocktail.find(params[:id])
@dose = Dose.find(params[:dose_id])
render 'cocktails/show'
# rails by default has an invisible line at the end of the actions, unless `render` is called manually like line above. But removing the line above, you'll get something like below
# render 'CONTROLLER_NAME/ACTION_NAME.FORMAT.TEMPLATE_ENGINE'
# so in this specific case:
# CONTROLLER_NAME == doses
# ACTION_NAME == edit
# FORMAT == html
# TEMPLATE_ENGINE == erb
# which translates to:
# render 'doses/edit.html.erb'
# which you can also do like the following
# render 'edit.html.erb' # because same controller name as the template being called
# which you can also do like the following
# render 'edit' # because it automatically identifies what format using the value of `request.format`, and what default template engine your Rails app is configured to use
# ... and this is the reason why you got that error "DosesController#edit is missing a template...", because app/views/doses/edit.html.erb does not exist, which by default is being rendered
请首先说明为什么要使用以下路线,我认为我是否有更好的解决方案:
get "cocktails/:id/doses/:dose_id", to: "doses#edit", as: :new_or_edit_dose
...我之所以这样问,是因为通常会针对某些唯一的属性标识符来路由“创建或更新” /“新建或编辑”请求。例如,在您的情况下,唯一属性标识符似乎是:dose_id
,因为如果Dose
还不存在,则您“创建”了一个新的:dose_id
记录,或者您进行了“更新” Dose
记录(如果已存在)且其id
值等于:dose_id
。现在,这是我的意见,但是我认为从手动设置的“ id”创建Dose
记录不是一个好主意,因为通常您会让数据库自动分配主键{{1} }值。
...要说明我的观点,例如,模拟上述路由,请说我在浏览器中打开以下网址:id
,到目前为止,假设"/cocktails/1/doses/1"
已经存在,那么我只会在页面上看到更新Dose(id: 1)
的表单。但是,假设我打开Dose
,并假设"/cocktails/1/doses/9999999999"
,那么我将看到一个创建Dose(id: 9999999999) does not exist yet
...的表单,此刻仍然有效。当您已经删除Dose
记录时,就会发生此问题。假设Dose
已被删除,然后我再次尝试打开Dose(id: 1)
,因为它已被删除,那么我将看到创建"/cocktails/1/doses/1"
的表单(仍然可以),但是会出现问题,因为您正在重用Dose
值,这些值应该是“主键”,并且应该唯一地标识资源,因为依赖于此唯一id值的关联/模型可能会混乱:例如,我有一个id
属性Car
的记录,该记录属于一个具有属性{name: 'Porsche', category_id: 23}
的{{1}}记录,然后以某种方式变色了Category(23)
已被销毁,然后使用相同的ID重新创建!但这一次创建的属性已经变成{name: 'vehicle'}
。现在,我的保时捷车变成了水果!
但是,我可以想到一些您有意执行此操作的原因(例如,如果您想将Category(23)
的值视为{name: 'fruit'}
,则可能永远无法以编程方式重用),但是我的想法是以防万一您还没有意识到这些可能的后果。