I am using the Rolify Gem on a Rails application. This has worked well until today. I was installing webpacker and stimulus and while doing that ran Bundle Update. This appears to have broken my Rolify functionality.
Examined User model carefully and compared to another app where Rolify is still working. Checked Role model, checked database schema to ensure users_roles table is intact.
Is there anything in a polymorphic relationship that could cause that Argument error?
I apologize if this question is not well formulated, this is my first time asking a question here.
u=User.find(1)
=> #<User id: 1, email: "admin@admin.com", created_at: "2019-04-27 17:13:17", updated_at: "2019-06-08 16:24:03", roles_mask: nil, first_name: "admin", last_name: "administrator", authentication_token: "V9rJdmKrhvZxVzBH55wk", email_frequency: nil, last_emailed: nil>
u.roles
Traceback (most recent call last):
ArgumentError (wrong number of arguments (given 3, expected 2))
I get the following error: ArgumentError (wrong number of arguments (given 3, expected 2))
User:
class User < ApplicationRecord
validate :password_complexity
validates :last_name, presence: true
validates :first_name, presence: true
validates :email, presence: true
#default_scope { order("last_name, first_name")}
rolify
#has_and_belongs_to_many :roles, :join_table => :users_roles
has_many :cohorts_users, inverse_of: :user, dependent: :destroy
has_many :cohorts, :through => :cohorts_users
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
acts_as_token_authenticatable
devise :invitable, :database_authenticatable, #:registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessor :skip_password_validation, :admin, :student, :rater, :author, :preceptor, :teacher, :auditor
attribute :email, :string
after_create :assign_default_role
def self.import(file, cohort)
cohort = Cohort.find(cohort.to_i)
spreadsheet = open_spreadsheet(file)
header = spreadsheet.row(1)
(2..spreadsheet.last_row).each do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
user = new
user.attributes = row.to_hash
user.skip_password_validation = true
user.cohorts << cohort
user.save!
#user.invite!
end
end
def self.open_spreadsheet(file)
case File.extname(file.original_filename)
when ".csv" then Roo::CSV.new(file.path)
when ".xls" then Roo::Excel.new(file.path)
when ".xlsx" then Roo::Excelx.new(file.path)
else raise "Unknown file type: #{file.original_filename}"
end
end
def password_required?
return false if skip_password_validation
super
end
def full_name
"#{last_name}, #{first_name}"
end
def assign_default_role
self.add_role(:candidate) if self.roles.blank?
end
private
def self.ransortable_attributes(auth_object = nil)
column_names - ['password_digest']
end
# Whitelist the User model attributes for search, except +password_digest+,
# as above. The +full_name+ ransacker below is included via +_ransackers.keys+
#
def self.ransackable_attributes(auth_object = nil)
ransortable_attributes + _ransackers.keys
end
def password_complexity
# Regexp extracted from https://stackoverflow.com/questions/19605150/regex-for-password-must-contain-at-least-eight-characters-at-least-one-number-a
return if password.blank? || password =~ /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,70}$/
errors.add :password, 'Complexity requirement not met. Length should be 8-70 characters and include: 1 uppercase, 1 lowercase, 1 digit and 1 special character'
end
# Demonstration of using a "ransacker" (a virtual, searchable "column") to
# allow searching via the full name from concatenated first and last names.
#
ransacker :full_name do |parent|
Arel::Nodes::InfixOperation.new('||',
Arel::Nodes::InfixOperation.new('||',
parent.table[:first_name], Arel::Nodes.build_quoted(' ')),
parent.table[:last_name])
end
end
Role:
class Role < ApplicationRecord
has_and_belongs_to_many :users, :join_table => :users_roles
belongs_to :resource,
:polymorphic => true,
:optional => true
validates :resource_type,
:inclusion => { :in => Rolify.resource_types },
:allow_nil => true
def self.defined_roles
self.all.map { |role| role.name }
end
scopify
end