I am developing a test application to learn Rails. While playing with associations I am getting ActiveModel::MissingAttributeError: can't write unknown attribute 'linked_section_id' error.
Let me first explain requirement. An User selects a Section of a Book for viewing. At the end of each section there will be few questions which is linked to some another sections. If user clicks on any question link, he will be redirected to associated section.
So the entities relation is as described below:
- A section can have multiple questions (one to many)
- A question belongs to a single section only (many to one – flip side of one to many)
- A question can be linked to a different section ( one to one)
Environment:
Ruby 1.9.3,
Rails 3.2.2
with all required gems
here are model classes:
class Section < ActiveRecord::Base
# Associations
has_many :questions
end
class Question < ActiveRecord::Base
belongs_to :section, :foreign_key => :section_id
has_one :linked_section, :class_name => "Section", :foreign_key => "linked_section_id"
end
db/schema.rb
.
.
create_table "sections", :force => true do |t|
t.string "name"
t.string "content"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "questions", :force => true do |t|
t.string "description"
t.integer "section_id"
t.integer "linked_section_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
.
.
Here are the Specs.
question_spec.rb
require 'spec_helper'
describe Question do
before do
@question = Question.new(description:'Test')
end
subject { @question }
# Check for attribute accessor methods
it { should respond_to(:description) }
it { should respond_to(:section) }
it { should respond_to(:linked_section) }
it { should respond_to(:linked_section_id) }
end
section_spec.rb
require 'spec_helper'
describe Section do
before do
@section = Section.new(name:'Test')
end
subject { @section }
# Check for attribute accessor methods
it { should respond_to(:name) }
it { should respond_to(:questions) }
# Sanity check, verifying that the @section object is initially valid
it { should be_valid }
describe "Question should have one action item while persisted" do
pending "This is broken after changing entity relationship"
before {
@section = Section.new(name: 'Section 2')
linked_section = Section.new(name: 'Action Section')
linked_section.save
question = Question.new(description: 'What next?')
question.linked_section = linked_section
@section.questions << question
@section.save
.
.
.
}
.
.
.
end
end
Now the question_spec.rb passes without any error but getting ActiveModel::MissingAttributeError: can't write unknown attribute 'linked_section_id' error on line question.linked_section = linked_section.
but if you notice, following examples of question_spec.rb
it { should respond_to(:linked_section) }
it { should respond_to(:linked_section_id) }
passes without any error. It means Question has ‘linked_section_id’. So why rspec panics?
I have doubt on the relation defined for linking a question to different section. Can anyone please guide me to design models properly?
Thanks, Amit Patel
Your specs are checking whether or not the question responds to :linked_section_id (a reader method), not whether or not it responds to :linked_section_id= (a writer method). All fields in a table will have reader methods associated with them, and since you added a linked_section_id field in the table, the reader method is there.
Whenever you add foreign keys to a table, it should be the *belongs_to* side of the association. Here, you used has_one. Switch that to belongs_to, and in the Section model, put
Hopefully this helps,