简体   繁体   中英

devise: undefined method `user=' for nil:NilClass

I'm trying to implement the devise gem into my web app - everything with user login and registration is working, but when a user tries to actually leave a prediction (the only thing you need to be logged in for), I get this error message: undefined method `user=' for nil:NilClass. I can't seem to figure out what's causing this problem. Might anyone know?

_login_items.html.erb:

<ul>
<% if user_signed_in? %>
  <li>
  <%= link_to('Logout', destroy_user_session_path, :method => :delete) %>
  </li>
<% else %>
  <li>
  <%= link_to('Login', new_user_session_path)  %>
  </li>
<% end %>

<% if user_signed_in? %>
  <li>
  <%= link_to('Edit registration', edit_user_registration_path) %>
  </li>
<% else %>
  <li>
  <%= link_to('Register', new_user_registration_path)  %>
  </li>
<% end %>
</ul>

prediction model:

class Prediction < ActiveRecord::Base
  belongs_to :student
  belongs_to :user
end

user model:

class User < ActiveRecord::Base
  has_many :predictions
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable
end

predictions migration:

class CreatePredictions < ActiveRecord::Migration
  def change
    create_table :predictions do |t|
      t.string :prediction
      t.belongs_to :student, index: true
      t.belongs_to :user
      t.timestamps
    end
  end
end

user migration:

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
  ## Database authenticatable
  t.string :email,              null: false, default: ""
  t.string :encrypted_password, null: false, default: ""

  ## Recoverable
  t.string   :reset_password_token
  t.datetime :reset_password_sent_at

  ## Rememberable
  t.datetime :remember_created_at

  ## Trackable
  t.integer  :sign_in_count, default: 0, null: false
  t.datetime :current_sign_in_at
  t.datetime :last_sign_in_at
  t.inet     :current_sign_in_ip
  t.inet     :last_sign_in_ip

  ## Confirmable
  # t.string   :confirmation_token
  # t.datetime :confirmed_at
  # t.datetime :confirmation_sent_at
  # t.string   :unconfirmed_email # Only if using reconfirmable

  ## Lockable
  # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
  # t.string   :unlock_token # Only if unlock strategy is :email or :both
       # t.datetime :locked_at


      t.timestamps
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

predictions controller:

class PredictionsController <ApplicationController
def create
    @prediction.user = current_user
    Prediction.create(prediction_params)
    redirect_to :back
end

def new
    @prediction = Prediction.new(student_id: params[:student_id])
end

def destroy
    Prediction.find(params[:id]).destroy
    redirect_to :back
end

private
def prediction_params
    params.require(:prediction).permit(:prediction) #, :student_id
end

end

The problem is in your PredictionsController. You have to create the prediction and assign it to a variable first. Change your create action to this:

def create
    @prediction = Prediction.create(prediction_params)
    @prediction.user = current_user
    redirect_to :back
end

You were trying to assign a user to a non existing prediction. This correction creates the prediction first then assigns the user to it.

Edit: I noticed one other problem: Your prediction_params method is incorrect. The arguments you pass to the permit method must be the attributes of your prediction model which you want to mass assign. The :prediction key in the params is the one you want to require but within that nested hash you want to permit attributes of the prediction model. So, hypothetically, if your prediction model has :name , :value and :student_id attributes, your prediction_params method should look like this:

def prediction_params
    params.require(:prediction).permit(:name, :value, :student_id)
end

This will work with a params hash that looks like:

{
  prediction: {
    name: 'something',
    value: 'stuff',
    student_id: 1
  }
}

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