使用浅层路由时,不同的路由需要不同的form_for参数 [英] When using shallow routes, different routes require different form_for arguments

查看:89
本文介绍了使用浅层路由时,不同的路由需要不同的form_for参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里使用简单表单,但这也是普通的Rails表单的问题.使用浅层路由时,form_for需要使用不同的参数,具体取决于所使用的上下文.

I'm using Simple Form here, but this is an issue with normal Rails forms, too. When using shallow routes, form_for needs different arguments depending in what context it's used.

示例:要进行编辑(http://localhost:3000/notes/2/edit),_ form.html.erb必须具有simple_form_for(@note).但是要创建新笔记(http://localhost:3000/customers/2/notes/new)_form.html.erb需要simple_form_for([@customer, @note]).如果任何一个接收到错误的参数,我都会得到方法未找到的错误.

Example: For editing (http://localhost:3000/notes/2/edit), _form.html.erb needs to have simple_form_for(@note). But for creating a new note (http://localhost:3000/customers/2/notes/new) _form.html.erb needs simple_form_for([@customer, @note]). If either receives the wrong arguments, I'll get a method not found error.

处理此问题的最佳方法是什么?

What's the best way to deal with this?

  • 我可以制作两个单独的表格,但这看起来很混乱.
  • 我必须为反向链接设置@customer,但是我可以在表单中使用其他变量(例如@customer_form),而不必在edit和update方法中进行设置,但这是不一致的,并且有些混乱,因为我必须在新方法中同时设置@customer_form和@customer.
  • 我可以做这家伙所做的事情并将表格拆分为多个文件.到目前为止,它似乎是最好的选择,但我真的不太喜欢它,因为您不能只打开_form.html.erb并查看正在发生的情况.
  • I could make two separate forms, but that seems messy.
  • I have to set @customer for the back link, but I could use a different variable in the form (say, @customer_form) and just not set it in the edit and update methods, but that's inconsistent and slightly confusing, since I'd have to set both @customer_form and @customer in the new method.
  • I could do what this guy did and split the form up across multiple files. It looks like the best option so far, but I don't really like it much, since you can't just open _form.html.erb and see what's happening.

这些是我唯一的选择吗?

Are these my only options?

示例如下:

config/routes.rb

Billing::Application.routes.draw do
  resources :customers, :shallow => true do
    resources :notes
  end
end

耙路| grep note

    customer_notes GET    /customers/:customer_id/notes(.:format)         notes#index
                   POST   /customers/:customer_id/notes(.:format)         notes#create
 new_customer_note GET    /customers/:customer_id/notes/new(.:format)     notes#new
         edit_note GET    /notes/:id/edit(.:format)                       notes#edit
              note GET    /notes/:id(.:format)                            notes#show
                   PUT    /notes/:id(.:format)                            notes#update
                   DELETE /notes/:id(.:format)                            notes#destroy

app/views/notes/_form.html.erb

#                      v----------------------------- Right here
<%= simple_form_for (@note), html: { class: 'form-vertical'} do |f| %>
  <%= f.input :content %>

  <%= f.button :submit %>
<% end -%>

app/views/notes/new.html.erb

<h1>New note</h1>

<%= render 'form' %>

<%= link_to 'Back', customer_path(@customer) %>

app/views/notes/edit.html.erb

<h1>Editing note</h1>

<%= render 'form' %>

<%= link_to 'Show', @note %>
<%= link_to 'Back', customer_path(@customer) %>

app/controllers/notes_controller.rb

class NotesController < ApplicationController

def show
  @note = Note.find(params[:id])
  @customer = Customer.find(@note.customer_id) 

  respond_to do |format|
    format.html
    format.json {render json: @note }
  end
end

  # GET /notes/new
  # GET /notes/new.json
  def new
    @note = Note.new
    @customer = Customer.find(params[:customer_id])

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @note }
    end
  end

  # GET /notes/1/edit
  def edit
    @note = Note.find(params[:id])
    @customer = Customer.find(@note.customer_id)
  end

  # POST /notes
  # POST /notes.json
  def create
    @customer = Customer.find(params[:customer_id])
    @note = @customer.notes.build(params[:note])

    respond_to do |format|
      if @note.save
        format.html { redirect_to @customer, notice: 'Note was successfully created.' }
        format.json { render json: @note, status: :created, location: @note }
      else
        format.html { render action: "new" }
        format.json { render json: @note.errors, status: :unprocessable_entity }
      end
    end
  end

  # PUT /notes/1
  # PUT /notes/1.json
  def update
    @note = Note.find(params[:id])
    @customer = Customer.find(@note.customer_id)

    respond_to do |format|
      if @note.update_attributes(params[:note])
        format.html { redirect_to @customer, notice: 'Note was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @note.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /notes/1
  # DELETE /notes/1.json
  def destroy
    @note = Note.find(params[:id])
    @note.destroy

    respond_to do |format|
      format.html { redirect_to :back }
      format.json { head :no_content }
    end
  end
end

推荐答案

如果您通过表单构建器传递的数组中的第一个对象是nil,Rails将仅发布到第二个对象.因此,只需不要在控制器的编辑操作中设置 @customer 对象.如果需要访问客户对象,请通过@note调用它.

If the first object in the array you pass the form builder is nil, Rails will POST to the second object only. For this reason simply don't set your @customer object in your controller's edit action. If you need access to the customer object, call it through @note.

如果您要对新建和编辑使用相同的部分,则需要在控制器的新操作中设置@note.customer(编辑时不会设置@customer).

If you're using the same partial for new and edit, you'll want to set @note.customer in the controller's new action (@customer won't be set when editing).

我认为这是Rails团队希望其工作的方式.

I think this is how the Rails team intended it to work.

这篇关于使用浅层路由时,不同的路由需要不同的form_for参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆