Как передать account_id через вложенную форму в Rails - PullRequest
0 голосов
/ 29 мая 2019

Я пытаюсь настроить вложенную форму в rails, и у родительских и дочерних объектов в форме должен быть «Идентификатор учетной записи», чтобы они оба были привязаны к учетной записи текущего пользователя, но я не могувыяснить, как передать идентификатор учетной записи текущего пользователя для дочернего объекта через вложенную форму.Я получаю сообщение об ошибке «Идентификатор учетной записи должен присутствовать» для вложенного объекта.

Родительская форма - «Продукт», и я пытаюсь вложить «Опции» в форму Product.new.

Я пытаюсь сделать что-то вроде этого:

@product.options.account_id = current_user.account.id

Но это не работает.

Вот модель продукта:

class Product < ApplicationRecord
  belongs_to :account
  has_many :options, dependent: :destroy

  accepts_nested_attributes_for :options, allow_destroy: true

  validates :account_id,  presence: true
  validates :name,        presence: true, length: { maximum: 120 }
end

И модель опций:

class Option < ApplicationRecord
  belongs_to :account
  belongs_to :product

  has_many :option_values, dependent: :destroy

  validates :account_id,  presence: true
  validates :name,        presence: true,
                          length: { maximum: 60 }
end

Вот как я вкладываю «Опции» в форму продукта:

<%= form.fields_for :options do |builder| %>
    <fieldset class='form-group'>
      <%= builder.label :name, 'Add option(s)' %>
      <%= builder.text_field :name %>
      <small id="optionHelp" class="form-text text-muted">
        (e.g. "Sizes" or "Color")
      </small>
    </fieldset>
  <% end %>

А вот мой ProductsController:

class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]
  before_action :restrict_access

  def index
    @products = Product.where(:account_id => current_user.account.id).all
  end

  def show
  end

  def new
    @product = Product.new
    @product.options.build
  end

  def edit
  end

  def create
    @account = current_user.account
    @product = @account.products.build(product_params)

    respond_to do |format|
      if @product.save
        format.html { redirect_to @product, notice: 'Product was successfully created.' }
      else
        format.html { render :new }
      end
    end
  end

  def update
    respond_to do |format|
      if @product.update(product_params)
        format.html { redirect_to @product, notice: 'Product was successfully updated.' }
      else
        format.html { render :edit }
      end
    end
  end

  def destroy
    @product.destroy
    respond_to do |format|
      format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
    end
  end

  private
    def set_product
      if Product.find(params[:id]).account_id == current_user.account.id
        @product = Product.find(params[:id])
      else
        redirect_to dashboard_path
      end
    end

    def restrict_access
      if index
        authorize @products
      else
        authorize @product
      end
    end

    def product_params
      params.require(:product).permit(:account_id, :name,
                                      options_attributes: [:id, :account_id, :name ])
    end
end

Как правильно это сделать?

Ответы [ 2 ]

2 голосов
/ 29 мая 2019

Кроме того, вы можете передать скрытое поле с формой и nested_form, как указано ниже: -

<%= form_for @product do |form|%>
  <%= form.fields_for :options do |builder| %>
      <fieldset class='form-group'>
        <%= builder.label :name, 'Add option(s)' %>
        <%= builder.text_field :name %>
        <small id="optionHelp" class="form-text text-muted">
          (e.g. "Sizes" or "Color")
        </small>
        <%=builder.hidden_field :account_id, value: current_user.account.id%>
      </fieldset>
  <% end %>
  <%= form.hidden_field :account_id, value: current_user.account.id%>
<%end%>

Кроме этого вы можете установить account_id на контроллере

  def new
    #@product = Product.new
    @product = current_user.account.products.new
    @product.options.build(account_id: current_user.account.id)
  end
0 голосов
/ 29 мая 2019

Самый простой вариант - добавить скрытое поле в обе формы:

https://apidock.com/rails/ActionView/Helpers/FormHelper/hidden_field

Так что в вашем случае для формы параметров что-то вроде:

  <%= form.fields_for :options do |builder| %>
    <fieldset class='form-group'>
      <%= builder.label :name, 'Add option(s)' %>
      <%= builder.hidden_field :account_id, value: current_account.id %>
      <%= builder.text_field :name %>
      <small id="optionHelp" class="form-text text-muted">
        (e.g. "Sizes" or "Color")
      </small>
    </fieldset>
  <% end %>

Это даст вам доступ к параметру [:option][:account_id], который будет соответствовать текущему пользователю.

...