ruby on rails - ActiveRecord::RecordNotFound: Couldn't find Hotel without an ID -
i`ve got these errors while testing ratings_controller.
1) ratingscontroller create action creates rating if validations pass failure/error: post :create, rating: {value: 4, user_id: user, hotel_id: hotel} activerecord::recordnotfound: couldn't find hotel without id # ./app/controllers/ratings_controller.rb:6:in `create' # ./spec/controllers/ratings_controller_spec.rb:12:in `block (4 levels) in <top (required)>' # ./spec/controllers/ratings_controller_spec.rb:11:in `block (3 levels) in <top (required)>' 2) ratingscontroller create action not create rating if validations fail failure/error: post :create, rating: {value: 3} activerecord::recordnotfound: couldn't find hotel without id # ./app/controllers/ratings_controller.rb:6:in `create' # ./spec/controllers/ratings_controller_spec.rb:17:in `block (3 levels) in <top (required)>' 3) ratingscontroller update action updates rating if validations ok failure/error: patch :update, value: 3, user_id: user.id, hotel_id: hotel.id actioncontroller::urlgenerationerror: no route matches {:action=>"update", :controller=>"ratings", :hotel_id=>"1", :user_id=>"2", :value=>"3"} # ./spec/controllers/ratings_controller_spec.rb:25:in `block (3 levels) in <top (required)>'
i dont know come from. me please if can. ratings_controller:
class ratingscontroller < applicationcontroller #before_action :signed_in_user before_filter :authenticate_user! def create @hotel = hotel.find(params[:hotel_id]) @rating = rating.new(params[:rating]) @rating.hotel_id = @hotel.id @rating.user_id = current_user.id if @rating.save redirect_to hotel_path(@hotel), :notice => "your rating has been saved" end end def update @hotel = hotel.find(params[:hotel_id]) #@rating = current_user.ratings.find(@hotel.id) @rating = rating.find_by_hotel_id(@hotel.id) if @rating.update_attributes(params[:rating]) redirect_to hotel_path(@hotel), :notice => "your rating has been updated" end end end
my ratings_controller_spec.rb:
require "spec_helper" describe ratingscontroller let(:rating) { factorygirl.create(:rating) } let(:user) { factorygirl.create(:user) } let(:hotel) { factorygirl.create(:hotel) } describe "create action" before { sign_in rating.user } "creates rating if validations pass" expect { post :create, rating: {value: 4, user_id: user, hotel_id: hotel} }.to change(rating, :count).by(1) end "does not create rating if validations fail" post :create, rating: {value: 3} expect(response).to redirect_to(hotel_path(hotel)) end end describe "update action" before { sign_in hotel.user } "updates rating if validations ok" patch :update, value: 3, user_id: user.id, hotel_id: hotel.id rating.reload expect(rating.value).to eq(3); end "updates rating if validations fail" end end end
especially third error confusing me because rake routes
shows me avaible route ratings update action.
patch /hotels/:id(.:format) hotels#update put /hotels/:id(.:format) hotels#update
thanks!
rails - 4.0.8
ruby - 1.9.3p551
update 1: sorry routes. mystake. copied wrong lines.
rating patch /ratings/:id(.:format) ratings#update put /ratings/:id(.:format) ratings#update
seems ok me , works fine if start server , test manually.
about id problem:
@hotel = hotel.find(params[:hotel_id])
expects params
hash have top-level hotel_id
key. when call create
method test, nest hotel_id
inside ratings
key:
post :create, rating: {value: 4, user_id: user, hotel_id: hotel}
thus params[:hotel_id]
nil. need add hotel_id
top-level key:
post :create, rating: {value: 4, user_id: user, hotel_id: hotel}, hotel_id: hotel
alternatively, can pass nested hotel_id
directly find
method:
@hotel = hotel.find(params[:rating][:hotel_id])
about route problem:
your route mapped hotelscontroller
(as seen in rake routes
output hotels#update
), testing ratingscontroller
,
no route matches {:action=>"update", :controller=>"ratings", :hotel_id=>"1", :user_id=>"2", :value=>"3"}
.
update routes route ratingscontroller
's update
method instead of hotelscontroller
, have ratings#update
route.
update:
in case, route expecting id
parameter in url: /ratings/:id
, not providing:
patch :update, value: 3, user_id: user.id, hotel_id: hotel.id
either provide specific rating id want update, or change routes not require id
parameter since finding rating through hotel anyway, like
patch '/ratings', 'ratings#update'
instead of
patch '/ratings/:id', 'ratings#update'
.
if defined routes resources :ratings
, can put specific route above it, hit first router. idea exclude too: resources :ratings, except: :update
. or use collection routes. see this question more info.
Comments
Post a Comment