I am going through Michael Hartl's Tutorial on RoR 4.0 and am currently doing the first exercise in chapter 9.
I'm supposed to write a test that confirms that it's not possible to issue a PATCH request to edit the admin attribute on a user. To prevent mass-assignment, the tutorial introduces a user_params function that only permits certain attributes.
In the test, I am issueing
patch user_path(user), params
where params is a hash containing an a true value for admin (see below). After this request, I expect the attribute on the user to still be false.
Here's the problem
While the test (correctly) succeeds with my current code, it also (incorrectly) succeeds when I add the admin attribute to the list of allowed attributes in the user_params function.
Using curl to issue a PATCH request to /users/:id gives an error page that I don't quite understand yet. I've tried replacing PATCH by PUT, having read somewhere that support for this method is fairly new and thinking that I might not have the correct version for each and every gem. I'm using ruby 1.9.3, while the tutorial uses 2.x.
Is there anything I'm missing here? (Any hints on how to simulate these requests in the rails console would be helpful as well!)
I pasted the relevant parts of the code I am using below:
Code:
app/controllers/users_controller.rb
class UsersController < ApplicationController before_action :signed_in_user, only: [:edit, :update, :index, :destroy] before_action :correct_user, only: [:edit, :update] before_action :admin_user, only: :destroy ... def update @user = User.find(params[:id]) if @user.update_attributes(user_params) sign_in @user flash[:success] = "Profile updated" redirect_to @user else render 'edit' end end ... private def user_params params.require(:user).permit(:name, :email, :password, :password_confirmation, :admin) end ...
spec/features/users_pages_spec.rb
...
describe "edit page" do
let(:user) { FactoryGirl.create(:user) }
before do
sign_in user
visit edit_user_path(user)
end
...
describe "directly patch forbidden admin attribute" do
let(:params) do
{ user: { admin: true, password: user.password, password_confirmation: user.password } }
end
before {
patch user_path(user), params
}
specify { expect(user.reload).not_to be_admin }
end
...
app/models/user.rb
class User < ActiveRecord::Base
before_save { email.downcase! }
before_create :create_remember_token
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
validates :password, length: { minimum: 6 }
has_secure_password
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.encrypt(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
self.remember_token = User.encrypt(User.new_remember_token)
end
end
:admin
in the permitted params list, since that's the case that isn't behaving as you think it should. You also might share yourUser
model. – Peter Alfvin