【问题标题】:rails nested resource unknown attribute errorrails嵌套资源未知属性错误
【发布时间】:2014-05-23 01:50:19
【问题描述】:

我有一个 Contract 和一个 Task_Order 模型。我不断收到unknown attribute error for contract_id 每个Contract has many Task Orders。我已阅读其他嵌套模型未知属性错误问题,但它们无法帮助我。请记住,我对 Rails 还很陌生,如果能得到任何帮助,我将不胜感激。我正在使用 Rails 4.0

合约模型:

has_many :task_orders

合约架构:

create_table "contracts", force: true do |t|
   t.string   "contractId"
   t.string   "contractName"
 end

任务顺序模型:

belongs_to :contracts

任务顺序架构:

create_table "task_orders", force: true do |t|
t.string   "contract_Id"
t.string   "task_orderId"
t.string   "task_orderName"
end

当我点击Show Contract 时,我得到了错误:

unknown attribute: contract_id

这是突出显示的行:

<%= form_for([@contract, @contract.task_orders.new]) do |f| %>

我可以看出 Rails 正在尝试打印出contract_id,这不在我的Contract 模型中......那么我怎样才能让它打印出contractId 而不是在我的Contract 中型号?

谢谢!!

【问题讨论】:

    标签: ruby-on-rails ruby nested


    【解决方案1】:

    任务顺序模型应该有这行belongs_to contract

    belongs_to关联应声明为对应模型的单数

    task_orders 表中还应该有 contract_id 列。

    下图解释了 Rails 中 belongs_to 的默认行为

    【讨论】:

    • 嗨 - 我试过了,但我仍然遇到同样的错误......@cvibha
    • 我想知道为什么task_order模式没有contract_id而不是t.string "contract_Id。默认情况下,如果您的模型中有belongs_to model_name,那么该表中应该有model_name_id 列和type as integer
    • 嗨 - 在我的合同模型中,我有 t.string "contractId",在我的任务订单模型中,我有 t.string "contract_Id" @cvibha
    • 嗨,你能在你的 task_orders 表中添加一列 contract_id,类型为整数
    【解决方案2】:

    您需要注意的是 Rails 的 foreign_key(以及一般的关系数据库):


    外键

    Rails 的标准 foreign_key 是使用 snake_case (contract_id),但是,您可以像这样使用非常规的 foreign_keys

    #app/models/order.rb
    belongs_to :contract, foreign_key: "contract_Id"
    
    #schema SHOULD be:
    create_table "orders", force: true do |t|
       t.integer "contract_id" #-> should
       t.string "contract_Id" #-> your current
    end
    

    主键

    create_table "contracts", force: true do |t|
       t.string   "contractId" #-> don't need
    
       t.string   "contractName" #-> your current
       t.string "name" #-> should be
     end
    

    您的primary_key 几乎总是会成为id 列。您应该从 contracts db 中删除您的 contractId 列!


    Task Orders

    您需要这样做:

    #app/models/order.rb
    belongs_to :contracts
    has_many :task_orders
    

    然后,您将需要另一个模型 app/models/task_order.rb


    表格

    您的表单显示错误。这是因为您试图在视图本身中创建 ActiveRecord。使用通过表单传递嵌套模型数据的标准 accepts_nested_attributes_for 方法会更好:

    #app/models/contract.rb
    def new
        @contract = Contract.new
        @contract.task_orders.build
    end
    
    #app/views/contracts/new.html.erb
    <%= form_for @contract do |f| %>
    

    【讨论】:

    • 嗨 - 感谢您的洞察力。我将contract_Id 字段设为字符串,因为我需要它是字符串,而不是整数。有没有办法解决这个问题?
    • 如果是id,肯定是integer??为什么你需要它成为string
    • 例如,我有一个名为“COPD-2340”的合同ID,它是一个字符串,而不是一个整数......
    • 好吧,对不起!应该考虑多一点:D
    【解决方案3】:

    首先,使用singular names作为belongs_to

    Class TaskOrder < ActiveRecord::Base
    
    belongs_to :contract
    
    end
    

    其次,尝试将task_orders 表中的contract_Id 更改为contract_id

    Rails 默认查找model_name_id(in your case contract_id) foreign key,除非您的模型中定义了任何custom foreign keys

    最后,为default foreign key指定data type integer。在您的情况下,它应该是t.integer contract_id

    但是,如果您希望 contract_Idforeign key,则应在 Contract 模型本身中将其定义为 custom foreign key,如下所示

    Class Contract < ActiveRecord:Base
    
    has_many :task_orders,:foreign_key => "contract_Id"
    
    end
    

    【讨论】: