Reputation: 13721
I have a Contract and a Task_Order model. I keep getting an unknown attribute error for contract_id
Each Contract has many Task Orders
. I have read other nested models unknown attribute error questions but they haven't been able to help me. Please keep in mind I am pretty new to Rails and would greatly appreciate any help I can get. I am using Rails 4.0
Contract Model:
has_many :task_orders
Contract schema:
create_table "contracts", force: true do |t|
t.string "contractId"
t.string "contractName"
end
Task Order Model:
belongs_to :contracts
Task Order Schema:
create_table "task_orders", force: true do |t|
t.string "contract_Id"
t.string "task_orderId"
t.string "task_orderName"
end
When I click Show Contract
, I get the error:
unknown attribute: contract_id
This is the line that gets highlighted:
<%= form_for([@contract, @contract.task_orders.new]) do |f| %>
I can tell that Rails is trying to print out contract_id
, which is not in my Contract
model... so how can I get it to print out contractId
instead - which is in my Contract
model?
Thanks!!
Upvotes: 2
Views: 1105
Reputation: 76774
Something you need to be aware of is the foreign_key
of Rails (and relational databases in general):
Foreign Key
Rails' standard foreign_key
is to use snake_case
(contract_id
), however, you can use non-conventional foreign_keys
like this:
#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
Primary Key
create_table "contracts", force: true do |t|
t.string "contractId" #-> don't need
t.string "contractName" #-> your current
t.string "name" #-> should be
end
Your primary_key
is almost always going to be the id
column. You should remove your contractId
column from the contracts
db!
You'll need to do this:
#app/models/order.rb
belongs_to :contracts
has_many :task_orders
You'll then need another model at app/models/task_order.rb
Form
Your form is showing the error. This is because you're trying to create an ActiveRecord in the view itself. You'll be much better using the standard accepts_nested_attributes_for
method of passing nested model data through a form:
#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| %>
Upvotes: 1
Reputation: 33542
Firstly,use singular names
for belongs_to
Class TaskOrder < ActiveRecord::Base
belongs_to :contract
end
Secondly,try changing your contract_Id
in your task_orders
table to contract_id
.
Rails by default look for model_name_id(in your case contract_id)
foreign key
unless if any of the custom foreign keys
defined in your model.
And finally,specify the data type integer
for default foreign key
.In your case it should be t.integer contract_id
However if you want contract_Id
as foreign key
,you should define it as custom foreign key
in the Contract
model itself like this
Class Contract < ActiveRecord:Base
has_many :task_orders,:foreign_key => "contract_Id"
end
Upvotes: 0
Reputation: 713
Task Order Model should have this line belongs_to contract
belongs_to association should be declared as a singular of corresponding model
Also there should be contract_id column within task_orders table.
Diagram below explains default behavior of belongs_to in Rails
Upvotes: 2