0

我有类别(父母),其中列出了Products (Children)

我希望能够直接从导航栏、应用程序的任何位置创建新产品,然后在创建过程中将其分配给类别。

但是,我得到了当前的错误:

NoMethodError in Products#new
Showing /Users/istvanlazar/Mobily/app/views/products/new.html.erb where line #9 raised:

undefined method `products_path' for #<#<Class:0x00007febaa5aec98>:0x00007febae0f9e38>
Did you mean?  product_show_path 

## product_show_path is a custom controller that has nothing to do with this one, 
enabling show and clean redirection from newest_products index bypassing categories nesting.

Extracted source (around line #9):
9  <%= form_for [@product] do |f| %>
10   <div class="form-styling">
11     <div>
12       <%= f.label :name %>

我的应用程序是这样工作的:

楷模

class Category < ApplicationRecord
  has_many :products, inverse_of: :category
  accepts_nested_attributes_for :products

  validates :name, presence: true
end


class Product < ApplicationRecord
  belongs_to :user, optional: true
  belongs_to :category, inverse_of: :products

  validates :category, presence: true
end

路线

get 'products/new', to: 'products#new', as: 'new_product'

resources :categories, only: [:index, :show, :new, :edit] do
  resources :products, only: [:index, :show, :edit]
  # resources :products, only: [:index, :show, :new, :edit]
end

控制器

class ProductsController < ApplicationController
  before_action :set_category, except: :new

  def index
    @products = Product.all
    @products = policy_scope(@category.products).order(created_at: :desc)
  end

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

  def new
    @product = Product.new
    @product.user = current_user
  end

  def create
    @product = Product.new(product_params)
    @product.user = current_user
    if @product.save!
      redirect_to category_product_path(@category, @product), notice: "Product has been successfully added to our database"
    else
      render :new
    end
  end

  private

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

  def product_params
    params.require(:product).permit(:name, :price, :description, :category_id, :user, :id)
  end
end


class CategoriesController < ApplicationController
  def index
    @categories = Category.all    
  end

  def show
    @category = Category.find(params[:id])
  end

  def new
    # Non-existant created in seeds.rb
  end

  def create
    # idem
  end

  def edit
    # idem
  end

  def update
    # idem
  end

  def destroy
    # idem
  end

  private

  def category_params
    params.require(:category).permit(:name, :id)
  end
end

意见

# In shared/navbar.html.erb:

<nav>
  <ul>
    <li>Some Link</li>
    <li>Another Link</li>
    <li><%= link_to "Create", new_product_path %></li>
  </ul>
</nav>

# In products/new.html.erb:

<%= form_for [@product] do |f| %>
    <div class="form-styling">
      <div>
        <%= f.label :name %>
        <%= f.text_field :name, required: true, placeholder: "Enter product name" %>

        <%= f.label :price %>
        <%= f.number_field :price, required: true %>
      </div>
      <div>
        <%= f.label :description %>
        <%= f.text_field :description %>
      </div>
      <div>
        <%= f.label :category %>
        <%= f.collection_select :category_id, Category.order(:name), :id, :name, {prompt: 'Select a Category'}, required: true %>
      </div>
      <div>
        <%= f.submit %>
      </div>
    </div>
  <% end %>

你知道哪里出错了吗?或者在将其分配给父级之前创建一个子级是不可能的......?

提前致谢。

最好的,伊斯特

4

2 回答 2

1

您还没有定义任何路线来处理您的新产品表单的 POST。您已经定义了new_product路径,但是这种安排打破了 Rails 的约定,并且您没有提供解决方法。

您可以定义另一个自定义路由,例如post 'products', to: 'products#create', as: 'create_new_product',然后在您的表单中设置它,例如form_for @product, url: create_new_product_path do |f|.

但是,您应该考虑更改结构,以便产品路线不会嵌套在类别下。在以这种方式打破惯例之前,请三思。

于 2020-04-09T15:45:18.483 回答
0

编辑:我误读了意图,忽略这一点。与杰里米天气的答案一起去。

或者在将其分配给父级之前创建一个子级是不可能的......?

通过您建立关系和验证的方式:是的,是的。产品需要一个类别,通过validates :category, presence: true. 如果您使用的是 Rails 5+,则默认情况下已经需要关联(这意味着这validates实际上是多余的)。这意味着如果您尝试创建没有类别的产品,它将失败,并且产品将不会保存到数据库中。

有了这个约束,我建议尝试以下方法:

  • 删除自定义/products/new路由
    • 消除get 'products/new', to: 'products#new', as: 'new_product'
  • 添加 :new 和 :create 路由以允许嵌套在类别下的产品创建
    • :createand :new, 添加到:only数组的resources :products嵌套下resources :categories
  • 将文件移动views/products/new.html.erb到(如有必要,在其中views/categories/products/new.html.erb创建一个新categories目录)。views
  • 在该文件中,更改 以form_for使表单发布到嵌套的 :create 路由:
    • form_for [@category, @product] do |f|
  • 访问 URL /categories/[insert some Category ID here]/products/new,填写一些数据,看看是否可行。

您的 routes.rb 应该如下所示:

resources :categories, only: [:index, :show, :new, :edit] do
  resources :products, only: [:index, :show, :new, :create, :edit]
end
于 2020-04-09T15:50:13.993 回答