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?

Attachments:
http://www.ruby-forum.com/attachment/7210/students_controller.rb
http://www.ruby-forum.com/attachment/7211/accounts_controller.rb
http://www.ruby-forum.com/attachment/7212/show.html.erb

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!

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...

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.

Attachments:
http://www.ruby-forum.com/attachment/7216/show.html.erb