Help with the has_one model implementation

I keep getting the following error:
NoMethodError in Students#show
undefined method `student_accounts_path’ for
#<#Class:0x007ffe2bf6d688>:0x007ffe2c5e5628>

I am trying to implement a has_one model. I followed the rails guide
that used the :post has_many :comments example and tweaked it a bit.

my routes.rb file looks like this:
resources :students do
resource :account
end

My Students.controller, Account.controller files are attached.
Along with the /app/views/students/show.html.erb file

I have no idea what I’m doing wrong.
Can anyone please help me?

Try

rake routes

  • and you will see, there really isn’t defined a student_acounts_path

Try:
resources :students do
resources :accounts
end

or alternatively in your show (if you want to add a show, edit or
update-action in your accounts_controller without an :id param)

form_for [@student, @student.build_account], :url =>
student_account_path(@student)

best,
B. Pieck

Thanks for your tips Bente,

I ran rake routes, and this is what I got:
student_account POST /students/:student_id/account(.:format)
accounts#create

I thought my routes.rb file HAD to be like this:
resources :students do
resource :account
end

because my Student model only ‘has_one’ Account (not a has_many)

I changed my form_for to:
form_for ([@student, @student.build_account], :url =>
student_account_path(@student))

And I am no longer getting the ‘NoMethodError’ BUT the account
information is not being saved to the accounts table.

What key concept am I not understanding?

Hi Ayesha,

it might be a typo in your routes:

resource :accounts insted of resourceS :accounts

Also please if you want to connect these tables you need a couple of
things, not only nested routes.
You also need:

  • has_many relationship in student.rb
  • belongs_to relationship in account.rb
  • you need to add 1-1 table column to both tables which refers to each
    others. Best way to do it with migrations like “rails generate
    migration AddStudentIdForAccounts” and AddAccountIdForStudents. Follow
    this http://guides.rubyonrails.org/migrations.html
    Fill these, then run “rake db:migrate”
    Finally you need the proper nested routes you mentioned above, also
    controllers and views in place with well-named methods.

So in short way:
2 tables refers to each other (with 2 migrations),
2 model files refers to each other,
routes.rb,
controllers,
views.

HTH!
YogiZoli

PS. Highly recommend you this tutorial instead of Guides first:
http://ruby.railstutorial.org/ruby-on-rails-tutorial-book?version=3.2
this helped me a lot in understanding full MVC in action!

I think I figured it out.
It was to do with my @student.build_account in the students#show method.
(And as per my original post, I think I had that in my form_for tag).

Because I’m returning to the same page, the foreign key was continually
being ‘built’.

My students controller looks likes this:
def show
@student = Student.find(params[:id])
@account = @student.account
if @account.nil?
@account = @student.build_account
end

respond_to do |format|
  format.html # show.html.erb
  format.json { render json: @student }
end

end

And my accounts controller looks like this:
def create
@student = Student.find(params[:student_id])
@account = @student.create_account(params[:account])
redirect_to student_path(@student)
end
end

And my app/views/students/show.html.erb is attached.

Hi YogiZoli,

Thanks for your post.

I think you meant has_one instead of ‘has_many’ (in your first bullet
point for student.rb).
I tried what you suggested, and my routes.rb file has
resource :accounts

I also went back to my original “form_for” text as per my attachment and
I no longer see that NoMethodError (YAY!) that I first posted up.

I figured out why (at least i think i did) my ‘insert into accounts’
would delete when I rendered the show.html.erb file after creating an
account… I had the text “:dependent => :destroy” in the model.rb file

I’ve updated my models to have that 1-1 relationship.
While I was testing it out, I noticed the following in my server logs…


Started POST “/students/4/accounts” for 127.0.0.1 at 2012-04-01 21:16:19
+1000
Processing by AccountsController#create as HTML
Parameters: {“utf8”=>“✓”,
“authenticity_token”=>“FEdjo1+qRJ1cIQpwIbpRnvJ51esPgd/K8s9Hb4MOylQ=”,
“account”=>{“name”=>“acname1”, “number”=>“1111”}, “commit”=>“Create
Account”, “student_id”=>“4”}
Student Load (0.4ms) SELECT students.* FROM students WHERE
students.id = 4 LIMIT 1
(0.4ms) BEGIN
SQL (0.5ms) INSERT INTO accounts (created_at, name, number,
student_id, updated_at) VALUES (‘2012-04-01 11:16:20’, ‘acname1’,
‘1111’, 4, ‘2012-04-01 11:16:20’)
(0.7ms) COMMIT
Account Load (0.3ms) SELECT accounts.* FROM accounts WHERE
accounts.student_id = 4 LIMIT 1
(0.1ms) BEGIN
(0.1ms) COMMIT
Redirected to http://localhost:3000/students/4
Completed 302 Found in 11ms (ActiveRecord: 2.4ms)

Started GET “/students/4” for 127.0.0.1 at 2012-04-01 21:16:20 +1000
Processing by StudentsController#show as HTML
Parameters: {“id”=>“4”}
Student Load (0.3ms) SELECT students.* FROM students WHERE
students.id = 4 LIMIT 1
Account Load (0.4ms) SELECT accounts.* FROM accounts WHERE
accounts.student_id = 4 LIMIT 1
(0.1ms) BEGIN
(0.3ms) UPDATE accounts SET student_id = NULL, updated_at =
‘2012-04-01 11:16:20’ WHERE accounts.id = 4
(28.6ms) COMMIT
Rendered students/show.html.erb within layouts/application (36.4ms)
Completed 200 OK in 46ms (Views: 14.5ms | ActiveRecord: 29.8ms)


After entering the account details I make it redirect to the
app/views/student/show.html.erb view because I basically want to just
update the “show” page. BUT I can see that the student_id is being
updated to NULL - why is that?