ruby on rails 3 - Singularidad de los usuarios con idee y acts_as_tenant en rieles 3
ruby-on-rails-3 devise (3)
Estoy usando la gema acts_as_tenant para administrar multi-tenancy, y estoy usando el dispositivo para administrar usuarios.
Solo tengo que configurar el modelo de usuario y el modelo de cuenta para inquilinos. Puedo crear usuarios contra varios inquilinos; todo funciona bien, EXCEPTO cuando intento crear dos usuarios con el mismo correo electrónico contra diferentes ID de inquilino, obtengo un error de uniformidad. Estoy usando la opción validates_uniqueness_to_tenant como se describe.
Modelo de usuario
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
acts_as_tenant(:account)
validates_uniqueness_to_tenant :email
end
Modelo de cuenta
class Account < ActiveRecord::Base
attr_accessible :name
end
Controlador de aplicación
class ApplicationController < ActionController::Base
set_current_tenant_by_subdomain(:account, :subdomain)
protect_from_forgery
end
Parece que debería funcionar en función de toda la documentación en acts_as_tenant, ¿necesito reemplazar algo en el nivel del dispositivo?
EDITAR: después de algunos arañazos en la cabeza y un poco de descanso, creo que el problema es que, por defecto, Devise ha agregado un índice único a la columna Correo electrónico. Obviamente, esto no coincide con lo que los actuadores quieren hacer ... Trataré de eliminar el índice y ver si Viste vomita o no.
EDIT 2: OK, oficialmente me he dado por vencido por ahora. Tengo una autenticación automática para el sitio principal y esto funciona correctamente con acts_as_tenant. Solo puedo suponer cierta incompatibilidad entre acts_as_tenant y Devise en alguna capa, más allá de mí para encontrarla en esta etapa.
La única forma de hacerlo es eliminar el módulo validable de la aplicación y ejecutar sus propias validaciones de la siguiente manera:
class User < ActiveRecord::Base
acts_as_tenant :account
attr_accessible :email, :password, :remember_me
#remove :validatable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable
#run own validations
#I''ve omitted any emailformatting checks for clarity''s sake.
validates :email,
presence: true,
uniqueness: { scope: :account_id, case_sensitive: false }
validates :password,
presence: true,
length: { :in => 6..20 },
:if => :password_required?
protected
# copied from validatable module
def password_required?
!persisted? || !password.nil? || !password_confirmation.nil?
end
end
No lo he probado, pero me pregunto si cambiar el orden podría ayudar a los actuadores a hacer lo suyo antes de que el diseño tome el control.
class User < ActiveRecord::Base
acts_as_tenant(:account)
validates_uniqueness_to_tenant :email
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
end
Solo encontré esta pregunta. La solución de Sweam es bastante buena.
Pero prefiero no anular el comportamiento predeterminado. Así que se me ocurrió esta solución:
validate :remove_old_email_validation_error
validates_uniqueness_of :email, :allow_blank => true, :if => :email_changed?, :scope => [:account_id]
private
def remove_old_email_validation_error
errors.delete(:email)
end
Eliminamos el error de validación predeterminado para el correo electrónico, por lo tanto, ignoramos la verificación de validación y hacemos nuestra propia validación nuevamente. Lo que he agregado es del módulo Validatable, pero he agregado :scope
a él.
Es importante mantener el orden. Agregue el código anterior después del comando devise
.