简体   繁体   中英

Rails - NoMethodError (undefined method `collation' for nil:NilClass)

When I create User in my Rails app I get the following error...

NoMethodError (undefined method `collation' for nil:NilClass)

I've been banging my head on a wall with rails trying to figure out what the problem is.

I'm not quite sure what is wrong with my code, as it is pretty much boilerplate as you can see below...

user.rb

class User < ApplicationRecord
  has_secure_password

  before_create do
    self.username = 'user-' + SecureRandom.hex(8)
  end

  validates :email, presence: true, uniqueness: true, length: { within: 4..255 }
  validates :username, uniqueness: true, length: { is: 13 }
  validates :password, presence: true, uniqueness: true, length: { within: 8..255 }
end

user_controller.rb

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  def index
    @users = User.all
  end

  def show; end

  def new
    @user = User.new
  end

  def edit; end

  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
      else
        format.html { render :new }
      end
    end
  end

  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
      else
        format.html { render :edit }
      end
    end
  end

  def destroy
    @user.destroy
    respond_to do |format|
      format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
    end
  end

  private

  def set_user
    @user = User.find(params[:id])
  end

  def user_params
    params.fetch(:user).permit(:username, :email, :password, :password_confirmation)
  end
end

_form.html.erb

<%= form_for(@user, local: true) do |form| %>
  <div class="field">
    <%= form.label :email %>
    <%= form.text_field :email %>
  </div>

  <div class="field">
    <%= form.label :password %>
    <%= form.password_field :password %>
  </div>

  <div class="field">
    <%= form.label :password_confirmation, 'Password Confirmation' %>
    <%= form.password_field :password_confirmation %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

I have changed the encoding on the database as well, nothing seems to be working.

UPDATE I'm not quite sure what was wrong, I reverted to my 'initial commit' of the project and regenerated everything, and it works fine, it uses the same code. I'll mark this as solved, but I have no proper solution other than regenerating.

validates :password, presence: true, uniqueness: true, length: { within: 8..255 }

Here, remove uniqueness: true

You don't want to force a password to be unique, and as far as I know, if you use has_secure_password , bcrypt gem will save a digest of the user password to your database, making it almost impossible to verify if two users' passwords are the identical.

As said printfinn you have to remove uniqueness validation on password. His answer should be the accepted one.

I had the same error message as you.

I was trying to validate a field (presence and uniqueness) with a mistake in the name. The name was the name of a function. Rails could validate the presence, but not the uniqueness.

It's telling you what the error is. You're calling .collation on something—I'd guess on @user . The log will tell you which line is causing the error. What does that line look line?

For example, if the error contained a line like this:

app/views/layouts/application.html.erb:16

Then something like @user.collation would be called there. But given that the second part of the error says on nil:NilClass it means that @user isn't set.

Update

So that line points to your create method which has an error in it. It should be User.create(user_params) , not User.new(user_params) . Although, you are calling .save afterwards, so it should work.

Also, maybe make the callback after_create and change it to this:

after_create do
  update(:username, "user-#{SecureRandom.hex(8)}"
end

No downside to that, and it might expose what's going on. before_create I find to be real treacherous.

I'm not quite sure what was wrong, I reverted to my 'initial commit' of the project and regenerated everything, and it works fine, it uses the same code. I'll mark this as solved, but I have no proper solution other than regenerating.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM