Подтвердить что ты не робот

При использовании неглубоких маршрутов разные маршруты требуют разных аргументов form_for

Я использую Simple Form здесь, но это проблема с обычными формами Rails. При использовании неглубоких маршрутов form_for нужны разные аргументы в зависимости от того, в каком контексте он использовался.

Пример: для редактирования (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]). Если либо принимает неправильные аргументы, я получаю метод, который не найден.

Какой лучший способ справиться с этим?

  • Я мог бы сделать две отдельные формы, но это кажется беспорядочным.
  • Мне нужно установить @customer для обратной ссылки, но я мог бы использовать другую форму в форме (например, @customer_form) и просто не устанавливать ее в методах редактирования и обновления, но это противоречиво и немного запутывает, поскольку В новом методе мне нужно будет установить как @customer_form, так и @customer.
  • Я мог бы сделать то, что этот парень сделал и разделил форму на несколько файлов. Пока это лучший вариант, но мне это не очень нравится, поскольку вы не можете просто открыть _form.html.erb и посмотреть, что происходит.

Являются ли эти мои варианты?

Пример:

конфигурации /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

приложение/просмотров/примечания/_form.html.erb

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

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

приложение/просмотров/примечания/new.html.erb

<h1>New note</h1>

<%= render 'form' %>

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

приложение/просмотров/примечания/edit.html.erb

<h1>Editing note</h1>

<%= render 'form' %>

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

приложение/контроллеры/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
4b9b3361

Ответ 1

Если первый объект в массиве, который вы передаете построителю формы, nil, Rails будет отправлять POST только второму объекту. По этой причине просто не устанавливайте свой @customer объект в действии редактирования контроллера. Если вам нужен доступ к объекту клиента, вызовите его через @note.

Если вы используете одно и то же частичное для нового и редактируете, вам нужно установить @note.customer в новое действие контроллера (@customer не будет задано при редактировании).

Я думаю, именно так команда Rails намеревалась работать.

Ответ 2

Я хотел бы предложить небольшую модификацию решения Джеймса:

# app/helpers/application_helper.rb
def shallow_args(parent, child)
  child.try(:new_record?) ? [parent, child] : child
end

Вместо того, чтобы полагаться на действие контроллера, называемое "новым", хотя оно, вероятно, будет в 95% случаев - это просто проверяет, является ли ребенок новой записью.

Ответ 3

Вот что я придумал:

приложение/хелперы/application_helper.rb

module ApplicationHelper

  # Public: Pick the correct arguments for form_for when shallow routes 
  # are used.
  #
  # parent - The Resource that has_* child
  # child - The Resource that belongs_to parent.
  def shallow_args(parent, child)
    params[:action] == 'new' ? [parent, child] : child
  end

end

приложение/просмотров/примечания/_form.html.erb

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

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

Я не знаю, что это лучшее решение, но, похоже, все в порядке.