Как передать account_id через вложенную форму в 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

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

Может быть, этот ответ может помочь вам. stackoverflow.com/a/55476498/10895713

Max Vinicius 29.05.2019 19:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
192
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

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], который будет соответствовать текущему пользователю.

Ответ принят как подходящий

В качестве альтернативы вы можете передать hidden_field с формой и вложенной_формой, как показано ниже: -

<%= 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

Кажется, что установка идентификатора на контроллере, а не в представлении, является лучшим способом сделать это, но я не смог заставить это работать. Однако добавление <%= form.hidden_field :account_id, value: current_user.account.id%> к форме сработало!

Lee McAlilly 29.05.2019 21:44

Другие вопросы по теме