在同一页面上使用相同的表单进行新操作和编辑操作(simple_form&Rails)

时间:2018-08-09 19:35:00

标签: ruby-on-rails routes simple-form

我正在学习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,但是它没有用。

有人可以告诉我是否可行,并提示我应该寻找什么?

1 个答案:

答案 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'},则可能永远无法以编程方式重用),但是我的想法是以防万一您还没有意识到这些可能的后果。