activemodelruby-on-rails-7

Active Record: NameError (undefined local variable or method `attributes' for nil:NilClass Did you mean? attribute_names)


I recently migrated from Rails 6.1 to 7.0 and I keep getting the error when I try to sign up a user.

NameError (undefined local variable or method `attributes' for nil:NilClass
Did you mean?  attribute_names):
  
activemodel (7.0.2.2) lib/active_model/serialization.rb:153:in `attribute_names'
actionpack (7.0.2.2) lib/action_controller/metal/params_wrapper.rb:118:in `block in include'
/Users/axel/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/mutex_m.rb:78:in `synchronize'
/Users/axel/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/mutex_m.rb:78:in `mu_synchronize'
actionpack (7.0.2.2) lib/action_controller/metal/params_wrapper.rb:112:in `include'
actionpack (7.0.2.2) lib/action_controller/metal/params_wrapper.rb:278:in `_extract_parameters'

Something tells me I need to implement some attribute in the User model maybe because I have validation for email. I have tried

include ActiveModel::Serialization

  attr_accessor :email

  def attributes
    {'email' => nil}
  end

But nothing works.

Here is my User model

require 'druuid'

class User < ApplicationRecord

  before_create :downcase_email
  before_update :downcase_email

  # No confirmations or password resets in Development
  if Rails.env.production?
    devise :database_authenticatable, :registerable, :confirmable,
           :recoverable, :rememberable, :validatable, :lockable,
           :omniauthable, omniauth_providers: [:google_oauth2],
           authentication_keys: [:email]
  else
    devise :database_authenticatable, :registerable,
           :recoverable, :rememberable, :validatable,
           :omniauthable, omniauth_providers: [:google_oauth2],
           authentication_keys: [:email]
  end

  # ------------- validations -------------

  validates :email,
            presence: { message: "can't be empty"},
            :uniqueness =>  {:case_sensitive => false}

  def downcase_email
    self.email = self.email.downcase
  end

  # ------------- Omniauth -------------

  # Check Omniauth Controller
  def self.from_omniauth(auth)

    user = User.where(email: auth.info.email).first

    if user
      # record.update() returns a boolean value, user is automatically updated
      user.update(refresh_token: auth.credentials.refresh_token,
                  access_token: auth.credentials.token,
                  provider_uid: auth.uid,
                  provider: auth.provider,
                  )
    else
      user = User.create(email: auth.info.email,
                         provider_uid: auth.uid,
                         provider: auth.provider,
                         refresh_token: auth.credentials.refresh_token,
                         access_token: auth.credentials.token,
                         password: Devise.friendly_token[0, 20],
                         firstname: auth.info.first_name,
                         lastname: auth.info.last_name,
                         )
    end
    user
  end

end

Here is my serializer with ActiveModelSerializers

class UserSerializer < ActiveModel::Serializer
              # Basic
  attributes :id, :email, :uid, :firstname, :lastname
end


Solution

  • You need to include Active Model Serialization wherever you're initializing the serializer.

    For instance, in your /application_controller.rb:

    class ApplicationController < ActionController::API
        include ActiveModel::Serialization
    end