Devise error: undefined method `current_sign_in_ip

2019-08-06 10:51发布

问题:

I just installed Devise into my Rails 4.0.10 app. I wanted by users to be trackable, but I decided I didn't need :current_sign_in_ip and :last_sign_in_ip, so I removed those attributes.

My migration:

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

After I tried to make my first user, I got this error:

NoMethodError in Devise::RegistrationsController#create
undefined method `current_sign_in_ip' for #<User:xxxxxxxxx>

I don't understand why current_sign_in_ip is even being called. Here's the "Create" action, which definitely doesn't include that method:

def create
  build_resource(sign_up_params)

  resource.save
  yield resource if block_given?
  if resource.persisted?
    if resource.active_for_authentication?
      set_flash_message :notice, :signed_up if is_flashing_format?
      sign_up(resource_name, resource)
      respond_with resource, location: after_sign_up_path_for(resource)
    else
      set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
      expire_data_after_sign_in!
      respond_with resource, location: after_inactive_sign_up_path_for(resource)
    end
  else
    clean_up_passwords resource
    set_minimum_password_length
    respond_with resource
  end
end

Why is current_sign_in_ip even being called at all?

回答1:

The error is caused because you've not got the :current_sign_in_ip and :last_sign_in_ip attributes in your data table.

This is the reason why:

 # t.inet     :current_sign_in_ip
 # t.inet     :last_sign_in_ip

Commenting out those in your original migration has prevented them from being appended. You know this.

The way to fix, as mentioned in the answer by mentanco is to either put them back into the table, or to remove the :trackable reference from Devise...

Here's how to get the migration to add the extra data:

$ rails g migration AddTrackingToUsers

#db/migrate/add_tracking_to_users_________.rb
class AddTrackingToUsers
   def change
      add_column :users, :current_sign_in_ip, :string
      add_column :users, :last_sign_in_ip, :string
   end
end

$ rake db:migrate

If you run this, it will add the attributes to the table and get the functionality working again, alternatively, you can remove :trackable from your Devise model to allow it to skip the process entirely.



回答2:

you can't just not use them but if you remove them it will throw error because devise look for those attributes to update them after each sign_in:

 module Trackable
  def update_tracked_fields!(request)
    old_current, new_current = self.current_sign_in_at, Time.now
    self.last_sign_in_at = old_current || new_current
    self.current_sign_in_at = new_current

    old_current, new_current = self.current_sign_in_ip, request.remote_ip
    self.last_sign_in_ip = old_current || new_current
    self.current_sign_in_ip = new_current

    self.sign_in_count ||= 0
    self.sign_in_count += 1

    save(:validate => false)
  end
end

so you have 2 options:

  1. bring them back!

  2. remove :trackable from the model then it won't call this module.