You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails报错:创建Invoice时出现ActiveModel::MissingAttributeError

创建Invoice时自动生成InvoiceAppCollection报缺失属性错误

ActiveModel::MissingAttributeError in InvoicesController#create
can't write unknown attribute app_collection_id

创建Invoice时尝试自动生成InvoiceAppCollection,触发上述报错。查资料得知这类问题通常与模型关联有关,但我认为自身模型关联配置正确。生成InvoiceAppCollection的方法写在Invoice控制器中:

def create_invoice_app_collection    
    InvoiceAppCollection.create(
      po_number: @invoice.po_number,
      app_collection: @invoice.app_collection
    )
end

相关代码

模型代码

class AppCollection < ApplicationRecord
  belongs_to :company
  acts_as_tenant(:company)
  has_many :invoice_app_collections
  has_many :invoices, through: :invoice_app_collections
  
  validates :name, uniqueness: true
end

class Invoice < ApplicationRecord
  belongs_to :company
  acts_as_tenant(:company)  
  has_many :invoice_app_collections
  has_many :app_collections, through: :invoice_app_collections

  validates :expiration, on: [:create, :update, :save], :presence => true
end

class InvoiceAppCollection < ApplicationRecord
  belongs_to :app_collection
  belongs_to :invoice
  belongs_to :company
  acts_as_tenant(:company)    

  accepts_nested_attributes_for :app_collection
end

AppCollectionController代码

class AppCollectionsController < ApplicationController
  before_action :set_app_collection, only: %i[ show edit update destroy ]

  def index
    AppCollections = app_collection.all
  end

  def create
    @app_collection = app_collection.new(app_collection_params)

    respond_to do |format|
      if @app_collection.save
        format.html { redirect_to app_collection_url(@app_collection), notice: "App collection was successfully created." }
        format.json { render :show, status: :created, location: @app_collection }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @app_collection.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @app_collection.update(app_collection_params)
        format.html { redirect_to app_collection_url(@app_collection), notice: "App collection was successfully updated." }
        format.json { render :show, status: :ok, location: @app_collection }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @app_collection.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @app_collection.destroy

    respond_to do |format|
      format.html { redirect_to app_collections_url, notice: "app collection was successfully destroyed." }
      format.json { head :no_content }
    end
  end

  private
    def set_app_collection
      @app_collection = app_collection.find(params[:id])
    end

    def app_collection_params
      params.require(:app_collection).permit(:app_collection_type_id, :name, :company_id)
    end
end

InvoicesController代码

class InvoicesController < ApplicationController
  before_action :set_invoice, only: %i[ show edit update destroy ]
  prepend_before_action :set_tenant
  after_action :create_invoice_app_collection, only: [:create, :update]

  def new
    @invoice_app_collection = Invoice.new
  end
  def create
    @invoice = Invoice.new(invoice_params)
    respond_to do |format|
      if @invoice.save
        format.html { redirect_to invoice_url(@invoice), notice: "Invoice was successfully created." }
        format.json { render :show, status: :created, location: @invoice }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @invoice.errors, status: :unprocessable_entity }
      end
    end
  end
  def update
    respond_to do |format|
      if @invoice.update(invoice_params)
        format.html { redirect_to invoice_url(@invoice), notice: "Invoice was successfully updated." }
        format.json { render :show, status: :ok, location: @invoice }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @invoice.errors, status: :unprocessable_entity }
      end
    end
  end
  private

  def set_invoice
    @invoice = Invoice.find(params[:id])
  end

  def invoice_params
    params.require(:invoice).permit(:company_id, :po_number, :amount, :expiration, {:app_collection_id => []} )
  end

  def create_invoice_app_collection
    InvoiceAppCollection.create(
      po_number: @invoice.po_number,
      app_collection: @invoice.app_collection
    )
  end
end

InvoiceAppCollectionsController代码

class InvoiceAppCollectionsController < ApplicationController
  before_action :set_invoice_app_collection, only: %i[ show edit update destroy ]
  prepend_before_action :set_tenant
  
  def new
    @invoice_app_collection = InvoiceAppCollection.new
  end
  private
  def set_invoice_app_collection
    @invoice_app_collection = InvoiceAppCollection.find(params[:id])
  end

  def invoice_app_collection_params
    params.require(:invoice_app_collection).permit(:company_id, :po_number, {:app_collection => []} )
  end

end

发票表单中App Collection选择框代码

<div>
  <%= form.label :app_collection, style: "display: block" %>
  <label> Select multiple app collections by holding the command key </label>
  <%= form.select :app_collection, options_for_select(app_collection.all.map {|a| [a.name, a.name]}),{include_blank: false} , class:"form-select", multiple: true %>
</div>

数据库Schema

create_table "app_collections", charset: "latin1", force: :cascade do |t|
  t.integer "app_collection_type_id"
  t.string "name"
  t.integer "company_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

create_table "invoice_app_collections", charset: "latin1", force: :cascade do |t|
  t.integer "company_id"
  t.string "po_number"
  t.string "app_collection"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

create_table "invoices", charset: "latin1", force: :cascade do |t|
  t.integer "company_id"
  t.string "po_number"
  t.decimal "amount", precision: 10
  t.datetime "expiration"
  t.string "app_collection"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

已尝试的解决方法

  • 将参数设置为数组格式
  • 开启模型嵌套属性

问题仍未解决,寻求指导。


内容的提问来源于stack exchange,提问作者purplebentleyeater

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 00:55:18