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?