Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community!
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Matthew Hartwig
3,941 PointsEp:What is a Join Table? Test Failure
As per the video I have the following test:
test "should create status when for the current user when logged in" do
sign_in users(:jason)
assert_difference('Status.count') do
post :create, status: {content:@status.content, user_id: users(:jim).id}
end
assert_redirected_to status_path(assigns(:status))
assert_equal assigns(:status).user_id, users(:jason).id
end
I have updated my statuses_controller to the following:
def create
@status = current_user.statuses.new(params[:status])
respond_to do |format|
if @status.save
format.html { redirect_to @status, notice: 'Status was successfully created.' }
format.json { render json: @status, status: :created, location: @status }
else
format.html { render action: "new" }
format.json { render json: @status.errors, status: :unprocessable_entity }
end
end
end
And I still get the following failure:
1) Failure: test_should_create_status_when_for_the_current_user_when_logged_in(StatusesContr ollerTest) [test/functional/statuses_con
troller_test.rb:51]:
<1027431151> expected but was
<149087659>.
I have removed the user select box from the _form.html so only the current_user can post their own status and it works. Problem is the test still doesn't pass.
Any help appreciated
24 Answers

Frederic TETARD
1,970 PointsI Fix the issue for me by putting
post :create, status: { content: @status.content, user_id: @status.user.id }
instead of
post :create, status: { content: @status.conten }

Riley Hilliard
Courses Plus Student 17,771 PointsIn your test you are signing in the user "Jason", but are posting with the user "Jim" and then you are trying to assert that you will be redirected to the status' path and that it's Jasons, but the status isnt being saved because a user that isnt signed in is trying to post it. (So technically your test is working correctly) You need to post with "Jason" if you are asserting that it's Jason's post.
should be
post :create, status: {content:@status.content, user_id: users(:jason).id}
Let me know if this works. I am not entirely sure if my logic is correct, but it makes sense that that is your issue.

Matthew Hartwig
3,941 PointsThanks for the help Riley. Your logic is correct. So I've updated the test as follows:
test "should create status when for the current user when logged in" do
sign_in users(:jason)
assert_difference('Status.count') do
post :create, status: {content:@status.content}
end
assert_redirected_to status_path(assigns(:status))
assert_equal assigns(:status).user_id, users(:jason).id
end
Now I'm testing: a) is the status count updated when Jason posts a status b) If I post a status I am preperly redirected c) If I'm logged in as Jason my status is associated with Jason's id
Good but I'm no longer testing if I can post a status for Jason when I'm logged in as Jim. I think by modifying the _form.html that this is no longer possible to do but I'm curious if there's a test to prove it.
Also, still doesn't explain how Jason get's a positive assertion for
assert_equal assigns(:status).user_id, users(:jason).id"
In the "What is Join Table" lesson his code matches the test in my first post????

Riley Hilliard
Courses Plus Student 17,771 PointsEditing the _form.html.erb does not change the ability to perform the action, which is what the lesson is testing for. The changes you made to the statuses_controller.rb ensure that only the logged in user can post a status from their account by auto selecting the signed in user when the status is created, and therefor that form field isnt necessary/would create a save error anyway.
In your statuses_controller.rb have you completed all the code in the lesson, such as the update? it should be working for you as it appears you have all the same code as I have in mine, and All my tests are passing. Here is some of my code
<pre><code> test "should create status when logged in" do sign_in users(:riley)
assert_difference('Status.count') do
post :create, status: { content: @status.content }
end
assert_redirected_to status_path(assigns(:status))
end
test "should create status for the current user when logged in" do sign_in users(:riley)
assert_difference('Status.count') do
post :create, status: { content: @status.content, user_id: users(:john).id }
end
assert_redirected_to status_path(assigns(:status))
assert_equal assigns(:status).user_id, users(:riley).id
end </code></pre> Statuses Controller: <pre><code> def update @status = current_user.statuses.find(params[:id]) if params[:status] && params[:status].has_key?(:user_id) params[:status].delete(:user_id) end </code></pre> <pre><code> def create @status = current_user.statuses.new(params[:status]) </code></pre>

Matthew Hartwig
3,941 PointsMy code looks identical to yours:
statuses_controller.rb
def create
@status = current_user.statuses.new(params[:status])
respond_to do |format|
if @status.save
format.html { redirect_to @status, notice: 'Status was successfully created.' }
format.json { render json: @status, status: :created, location: @status }
else
format.html { render action: "new" }
format.json { render json: @status.errors, status: :unprocessable_entity }
end
end
end
def update
@status = current_user.statuses.find(params[:id])
if params[:status] && params[:status].has_key?(:user_id)
params[:status].delete(:user_id)
end
respond_to do |format|
if @status.update_attributes(params[:status])
format.html { redirect_to @status, notice: 'Status was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @status.errors, status: :unprocessable_entity }
end
end
end
statuses_controller_test.rb
test "should create status when for the current user when logged in" do
sign_in users(:jason)
assert_difference('Status.count') do
post :create, status: {content:@status.content, user_id: users(:jim).id}
end
assert_redirected_to status_path(assigns(:status))
assert_equal assigns(:status).user_id, users(:jason).id
end
test "should update status for the current user when logged in" do
sign_in users(:jason)
put :update, id: @status, status: {content: @status.content, user_id: users(:jim).id}
assert_redirected_to status_path(assigns(:status))
assert_equal assigns(:status).user_id, users(:jason).id
end
But I still get a failure
1) Failure:
test_should_create_status_when_for_the_current_user_when_logged_in(StatusesContr ollerTest) [test/functional/statuses_con
troller_test.rb:51]:
<1027431151> expected but was
<149087659>.

Matthew Hartwig
3,941 PointsNOTE: when I test
assert_equal assigns(:status).user_id, users(:jim).id
I don't get any failure. Which leads me to believe Jim is able to post for Jason. But this shouldn't be possible because of the scope change in the statuses_controller.rb

Alexander Lynham
5,996 PointsMatthew - re-add the drop-down field to your form, boot the server and try it, you'll probably find that it is causing an error. I've had an almost identical problem as this and I think the problem is with the devise object current_user. A few days ago (though I notice this has now been updated) on their GitHub the build was marked as 'failing', so I wonder if there's some sort of issue there.
Testing the current_user using a different model or a view on my app showed it was sporadically available to models, but for some reason always accessible to views. Not sure why.

Matthew Hartwig
3,941 PointsI've re-added the drop-down menu. If I post a new status without selecting a name from the drop-down the app uses the logged in user - Jason. However, I can still post as Jim when I'm signed in as Jason (even with the proper scope change in the controller).
But when I try to edit one of Jim's statuses logged in as Jason, I get a Controller Exception (i.e. the desired response).
Couldn't find Status with id=2 [WHERE "statuses"."user_id" = 3]
Like you said Alex it seems like current_user helper is working sporadically....

Alexander Lynham
5,996 PointsIn that case maybe the solution is a bundle install? Presumably that will download and update the devise gem....?

Jason Seifer
Treehouse Guest TeacherHi Matthew, the reason that error is coming up is because the update action is trying to find the status based on the user scope. The status doesn't exist scoped to the current user which is why the error is thrown. We haven't gotten to disabling the edit form for other user's statuses yet.

Matthew Hartwig
3,941 PointsThanks for the reply Jason. I follow you on why I'm getting error on the update action. I believe that's the response we're looking for.
The problem I'm having is that I'm still able to create a status for another user even with it properly scoped in the create method.

Doug Macklin
Courses Plus Student 5,453 PointsThis thread got sidetracked, but I have the same problem as the initial post (which hasn't been solved). Let me break it down:
First, at 4:01 in the video, Jason gets two failures, but I only get the first one (no error about Status.count not changing).
Ignoring that for the time being, I followed the video's advice to change line 45 in statuses_controller.rb to:
@status = current_user.statuses.new(params[:status])
At 5:00, Jason runs the test again and it passes (no failures). When I run the test again, I still have the same failure as before:
1) Failure:
test_should_create_status_for_the_current_user_when_signed_in(StatusesControllerTest) [test/functional/statuses_controller_test.rb:50]:
<855667630> expected but was
<902541635>.
In other words, this assertion on line 50 fails for me, but passes for Jason in the video:
assert_equal assigns(:status).user_id, users(:jason).id
That is, the test:
test "should create status for the current user when signed in" do
sign_in users(:jason)
assert_difference('Status.count') do
post :create, status: { content: @status.content, user_id: users(:jim).id }
end
assert_redirected_to status_path(assigns(:status))
assert_equal assigns(:status).user_id, users(:jason).id
end
is failing for me. This means the signed in user (Jason), is able to call the Statuses Controller create action and pass a status with Jim's id, but even though it should ignore Jim's id and post the status under the signed in user (Jason), it posts the status as Jim.
Matthew, if you ever figured this out, let me know. Otherwise, if anyone can explain why I'm not getting the same behavior as Jason in the video, that would be greatly appreciated.
P.S. I'm using Rails 3.2.1 and Ruby 1.9.3p392. Does anyone know what they are using in the video? If they use older versions, is it possible that a Ruby or Rails update changed the behavior to cause this issue? If so, could someone explain how I need to change the code to make this test pass?

Jason Seifer
Treehouse Guest TeacherHey Doug, that's pretty strange. Would you mind zipping up your code and emailing it to help@teamtreehouse.com so I can take a look?

Doug Macklin
Courses Plus Student 5,453 PointsSure thing. Sent

Doug Macklin
Courses Plus Student 5,453 PointsFollow up:
I looked into this some more and noticed that you guys have the line:
attr_accessible :content, :user_id
in models/status.rb, which was initially:
attr_accessible :content, :name
way back when you first generated the status model.
I, on the other hand, don't have any attr_accessible line in the status.rb file (I think it either wasn't there when I initially generated the status model, or it got deleted later, possibly when I removed the name attribute from the status model). However, if I add in that line, I still get the same failed test as before, and I also get this error:
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: id, created_at, updated_at
in test_should_create_status_when_signed_in and test_should_update_status_when_signed_in. I think I understand the mass assignment error, but now I'm wondering why you guys didn't get that error in the video since id, created_at, and updated_at aren't in your attr_accessible either. Regardless, adding the attr_accessible line only introduced these mass assignment errors; as mentioned, it did not fix the failing test (so I have removed the line).
Moreover, wouldn't you not want :user_id in your attr_accessible to prevent people from modifying the user_id of a status?
Update: I figured out that you guys are using Rails 3.2.6. As mentioned, I've been using Rails 3.2.1. I changed my Gemfile to use 3.2.6, and the test passes (though if I add in the attr_accessible line I still get the mass assignment errors, so I'm still confused why you guys don't get those errors). Any idea what changes in Rails cause this (only the patch version changed, not the major or minor version)?

Jason Seifer
Treehouse Guest TeacherHey Doug,
Rails 3.2.1 is a bit old, it would be best to stay with the most current version of rails 3.2.x, or the version the videos are using.
You're right in that you wouldn't want user_id in attr_accessible to prevent people from modifying it. We fix that later on in the lessons. However, in my opinion, it makes it much easier to learn the concepts by getting something working quickly and then modifying it later. Regarding the created_at, updated_at, and id fields -- those are handled by rails automatically.
As far as why things are different from the point releases -- the rails core team will do security updates for minor versions of point releases. In the case of what we're seeing, requiring attr_accessible was a decision made in between point releases for enhanced security.

Mark Swan
1,158 PointsHi Jason,
I am also having difficulty with the same video.
I get the two failures that you do:
1) Failure:
test_should_post_status_for_the_current_user_when_logged_in(StatusesControllerTest[test/functional/statuses_controller_test.rb:50]:
<975247844> expected but was
<645198450>.
2) Failure:
test_should_post_status_when_logged_in(StatusesControllerTest) [test/functional/statuses_controller_test.rb:35]:
"Status.count" didn't change by 1.
<4> expected but was
<3>.
But when I make the fix to statuses_controller.rb, I still have this error:
1) Failure:
test_should_post_status_for_the_current_user_when_logged_in(StatusesControllerTest) [test/functional/statuses_controller_test.rb:50]:
<975247844> expected but was
<645198450>.
I was using Rails 3.2.1, but I upgraded to Rails 3.2.13 and I still have this issue.

Mark Swan
1,158 PointsOK. I fixed the problem.
I had initially just run 'gem install rails' on the command line, in order to update Rails.
But it seems that I also needed to change the actual rails version in my Gemfile and then run 'bundle update'.

Jason Seifer
Treehouse Guest TeacherGreat work, Mark! Let us know if you have any more problems.

Itay Banner
1,922 PointsHi Jason,
Sorry but this is still an issue for me. I have the same symptoms as Mark Swan here, but I'm on the latest rails version (3.2.13). What's going on?

Jason Seifer
Treehouse Guest TeacherI'm not sure, Itay Banner . Can you email your code to help@teamtreehouse.com and we'll try and get it sorted out?

Itay Banner
1,922 PointsSent. thanks!

Itay Banner
1,922 PointsI feel so moronic. My problem was on that line at the end of the test:
assert_equal assigns(:status).user_id, users(:jason).id
Where it says :jason
(The current_user) I had the other user.... :-/
Thanks, @Jason Seifer for noticing that.
Having said that, I'd really urge you to make all the params[:status]
business clearer. I can't remember where earlier you explained how this works, and the only reason my tests are now passing is because I successfully copied the code I saw in the video...

Frederic TETARD
1,970 PointsI Fix the issue for me by putting
post :create, status: { content: @status.content, user_id: @status.user.id }
instead of
post :create, status: { content: @status.conten }