Ruby on Rails 5: не удается сохранить запись, недопустимый параметр для многопоточной записи - PullRequest
0 голосов
/ 07 марта 2019

Ruby on Rails 5, простая форма

Продукт имеет много спецификаций через ProductSpecs

в Product # Edit, я хочу добавить новые спецификации.

если Specification.saveУспешный, обновленный продукт.Он повторно отображает продукты и отображает «успех», но новая спецификация не сохраняется.

В журнале указаны недопустимые параметры - не уверен, как исправить мои product_parameters.Я попытался {product_specs => []} безрезультатно.

Любая помощь будет принята с благодарностью!

Журнал:

Started PATCH "/products/2" for 127.0.0.1 at 2019-03-07 14:44:24 +0800
Processing by ProductsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"f/wU9o1Fi8jXlTDCiJF93xMXFlaRH6sKx9+lNyg4ZGthVGkhPMrLwES/bEgeeHTHXdXaoolj67FOnGqqULtysg==", "product"=>{"name"=>"Notebooks", "description"=>"Handheld military and medical devices are built to operate in a variety of environments and also built to last.asdfasdfasdf", "category_id"=>"1", "product_spec"=>{"specification"=>{"name"=>"COLD", "low_value"=>"1", "high_value"=>"22", "unit"=>"volts"}}}, "commit"=>"Add New Spec", "id"=>"2"}
  Product Load (0.1ms)  SELECT  "products".* FROM "products" WHERE "products"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
Setting the product: Notebooks
#<Product id: 2, name: "Notebooks", description: "Handheld military and medical devices are built to...", picture: nil, created_at: "2019-02-20 06:43:20", updated_at: "2019-03-07 05:53:37", iconblack: "icons/products/icon_IPC_black.png", iconwhite: nil, iconyellow: nil, category_id: 1>Unpermitted parameter: product_spec
   (0.1ms)  begin transaction
  Category Load (0.2ms)  SELECT  "categories".* FROM "categories" WHERE "categories"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.1ms)  commit transaction
SUPPOSEDLY UPDATING
Unpermitted parameter: product_spec
product parameters: <ActionController::Parameters {"name"=>"Notebooks", "description"=>"Handheld military and medical devices are built to operate in a variety of environments and also built to last.asdfasdfasdf", "category_id"=>"1"} permitted: true>Redirected to http://localhost:3000/products/2
Completed 302 Found in 7ms (ActiveRecord: 0.5ms)


Started GET "/products/2" for 127.0.0.1 at 2019-03-07 14:44:24 +0800
Processing by ProductsController#show as HTML

Контроллер продуктов:

class ProductsController < ApplicationController
  # before_action :set_category, only: [:new, :create]
  before_action :set_product, only: [:edit, :show, :update, :destroy]


  def index
    @products = Product.all
    @categories = Category.all
    @message = Message.new
    @message.build_company

  end

  def new
    @product = Product.new
    @categories = Category.all
    @message = Message.new
    @message.build_company
    @product.specifications.build

    # setting product stuff for testing
    @product.picture = "products/IPC_tablet.png"
    @product.iconblack = "icons/products/icon_IPC_black.png"

  end

  def create
    @message = Message.new
    @message.build_company
    @categories = Category.all

    @product = Product.new(product_parameters)
    @product.category_id = product_parameters[:category_id]

    @product_spec = ProductSpec.new
    @new_spec= Specification.new


    if @product.save!

      flash[:success] = "You have saved the #{@product.name} product"
      redirect_to product_path(@product)
    else
      flash.now[:error] = "Product was not saved"
      render "new"
    end
  end

  def show
    @product = Product.find(params[:id])
    @categories = Category.all
    @message = Message.new
    @message.build_company
    @product_specs = @product.product_specs
  end

  def edit
    @message = Message.new
    @message.build_company
    @categories = Category.all

    # To create a new specification through product spec
    @product_spec = ProductSpec.new
    @new_spec= Specification.new

    @product_spec.product = @product
    @product_spec.specification = @new_spec

  end

  def update
    # puts "in update product, product parameters: #{product_parameters}"
    # puts product_parameters
    if @product.update(product_parameters)

      flash[:success] = "You have updated the #{@product.name} product"
      puts "SUPPOSEDLY UPDATING"
      print "product parameters: #{product_parameters.inspect}"
      redirect_to product_path(@product)
    else
      # puts "SUPPOSEDLY NOT UPDATING"
      flash.now[:error] = "You have not updated #{@product.name}"
      render :edit
    end
  end

  private

  def build_company
    @message.build_company
  end

  def set_product
    @product = Product.find(params[:id])

    puts "Setting the product: #{@product.name}"
    print @product.inspect
  end

  def find_category
    @category = Category.find(params[:category_id])
  end


  def product_parameters

    params.require(:product).permit(
      :id,
      :name,
      :description,
      :picture,
      :category_id,
      category: [
        :id
      ],

      product_specs: [
        {:specification => [] } ]
    )
  end

end

Характеристики продукта Контроллер:

class ProductSpecsController < ApplicationController
  before_action :find_product, only: [:new, :create, :destroy, :set_product_spec]
  before_action :set_product_spec, only: [:destroy, :show]

def new
  @product_spec = ProductSpec.new(:product_id => params[:product_id])
end

def create

end

def destroy
  @product = Product.find(params[:product_id])
  if @product_spec.destroy
    flash[:success] = "Product Specification Deleted"
    redirect_to product_path(@product.id)
  else
    flash[:error] = "Oops! Something went wrong"
    redirect_to product_path
  end
end

private

def find_product
  @product = Product.find(params[:product_id])
end

def set_specification

end

def set_product_spec
  @product_spec = ProductSpec.find_by(params[:product_id])
end
end

Технические характеристики контроллера:

class SpecificationsController < ApplicationController

before_action :set_specification, only: [:edit, :show, :update, :destroy]

def new
end

def create

end


def destroy

end

private

def set_specification
  @specification = Specification.find(params[:id])
end

end

Продукты # Редактировать форму / представление:

<%= simple_form_for @product do |product| %>
<h4 class="product_name">
  <%= product.input :name, placeholder: "Product Name" %>
</h4>
  <div class="product_picture">
    <%= image_tag("products/IPC_tablet.png") %>
  </div>

  <div class="product_description">
    <strong>Description</strong>
    <p class="font-size-12">
      <%= product.input :description, label: false %>
    </p>
    <%= product.association :category, prompt: "Select Category" %>
  </div>

  <div class="product_specifications">
    <strong>Specifications</strong>

    <!-- RENDER THRU PRODUCT SPECS, EACH EXISTING SPECIFICATION  -->
    <% if @product_specs %>
      <%= product.simple_fields_for :product_specs do |ps| %>
      <%= ps.simple_fields_for :specification do |spec| %>
      <div class="add_specification">
        <div class="specification_fields">
          <%= spec.input :name, label: false, input_html: { class: 'spec_input_name' }, placeholder: "Spec" %>
          <%= spec.input :low_value, input_html: { class: 'spec_input_values' }, label: false, placeholder:"Lowest Value" %>
          <%= spec.input :high_value, input_html: { class: 'spec_input_values' }, label: false, placeholder: "Highest Value" %>
          <%= spec.input :unit, label: false, input_html: { class: 'spec_input_values' }, placeholder:"Unit" %>
          <%= spec.button :submit, "Save Spec" %>
        </div>
      </div>
      <% end %>
    <% end %>
     <div>
        <strong>Add A New Specification</strong>
      </div>
    <% end %>


       <!-- - - - - - ADD A NEW SPECIFICATION -->
      <%= product.simple_fields_for @product_spec do |newps| %>


      <%= newps.simple_fields_for @new_spec do |newspec| %>
    <div class="add_specification">
      <div class="specification_fields">
          <%= newspec.input :name, label: false, input_html: { class: 'spec_input_name' }, placeholder: "Spec Name" %>
          <%= newspec.input :low_value, label: false, input_html: { class: 'spec_input_values' }, placeholder: "Lowest Value" %>
          <%= newspec.input :high_value, label: false, input_html: { class: 'spec_input_values' }, placeholder: "Highest Value" %>
          <%= newspec.input :unit, label: false, input_html: { class: 'spec_input_values' }, placeholder: "Unit" %>
          <%= newspec.button :submit, "Add New Spec" %>
        <% end %>
      </div>
      <% end %>
    </div>

    <div class="product_admin_actions">
      <%= product.button :submit, "Save This Product" %>
    </div>
    <% end %>

1 Ответ

0 голосов
/ 07 марта 2019

Мне кажется, проблема в понимании того, как accepts_nested_attributes_for работает в Rails. Я постараюсь объяснить это ясно.

связь между моделями также еще одна важная часть. Если мы примем такую ​​реальность, как: Product -> ProductSpec -> Specification решение должно быть таким.

# models/product.rb
class Product < ApplicationRecord
  has_many :product_specs
  accepts_nested_attributes_for :product_specs
end
# models/product_spec.rb
class ProductSpec < ApplicationRecord
  has_many :specifications
  accepts_nested_attributes_for :specifications
end
# controllers/products_controller.rb
class ProductsController < ApplicationController
  ...
  def create
    @proudct = Product.create(product_params)
  end

  private
  def product_params
    params.require(:product).permit(
      :id,
      :name,
      :description,
      :picture,
      :category_id,
      product_specs_attributes: [:id, 
                                 specifications_attributes: [:id, :name, :low_value, :high_value]
                                 ])

  end
end

Ваши поля просмотра выглядят правильно.

...