Rails attr_accessible :as и пользовательский валидатор

У меня есть модель пользователя

class User < ActiveRecord::Base
    has_and_belongs_to_many :roles

    attr_accessible :login, :email, :password, :password_confirmation ...
    attr_accessible :role_ids, :active, :as => :super_admin

    validates :email, :presence => true,
                      :format => {:with => /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i},
                      :uniqueness => {:case_sensitive => false},
                      :restricted_email_domain => true
    ...
end

и два отдельных пользовательских контроллера для внешнего и внутреннего интерфейса. Первый очень тривиальный и работает хорошо, второй ниже

class Admin::UsersController < Admin::BaseController
    def create
        @user = User.new
        @user.assign_attributes(params[:user], :as => :super_admin)
        if @user.save
        ...
    end
    def update
        @user = User.find(params[:id])
        if @user.update_attributes(params[:user], :as => :super_admin)
        ...
    end
end

Я использую собственный валидатор, который проверяет, ограничен ли домен электронной почты пользователя или нет.

class RestrictedEmailDomainValidator < ActiveModel::EachValidator
    def validate_each(record, attr_name, value)
        if !value.include?("@") # this value is nil if I add ":as => :super_admin"
            record.errors.add(attr_name, :invalid, options.merge(:value => value))
        else
            domain = value.split("@")[1]
            record.errors.add(attr_name, :restricted_email_domain, options.merge(:value => value)) if ::RestrictedEmailDomain.where(:domain => domain).exists?
        end  
    end
end
module ActiveModel::Validations::HelperMethods
    def validates_restricted_email_domain(*attr_names)
        validates_with RestrictedEmailDomainValidator, _merge_attributes(attr_names)
    end
end

Действие обновления работает хорошо, но действие создания дает You have a nil object when you didn't expect it! ошибку в config/initializers/restricted_email_domain_validator.rb:3:in 'validate_each'. Без :as => :super_admin все ок, но естественно атрибуты role_ids и active не назначаются.

Я могу назначать значения вручную, но я думаю, что это не идеальное решение.


person Babur Ussenakunov    schedule 27.12.2011    source источник


Ответы (1)


Я могу ошибаться, так как у меня сейчас нет возможности проверить это, но я думаю, что когда вы пишете

attr_accessible :role_ids, :active, :as => :super_admin
  • только эти два атрибута доступны вам, когда вы изменяете их как super_admin. Таким образом, @user.assign_attributes(params[:user], :as => :super_admin) устанавливает только эти два поля, оставляя остальные в состоянии по умолчанию.

Вы пробовали что-то вроде

attr_accessible :login, :email, :password, :password_confirmation ...
attr_accessible :login, :email, :password, :password_confirmation ..., :role_ids, :active, :as => :super_admin
person Nox    schedule 16.05.2012
comment
Есть ли способ определить атрибуты attr_accessible по умолчанию, а затем добавить их в зависимости от роли, которую вы назначаете атрибутам? Таким образом, избегая повторения :login, :email,... - person Kevin Lawrence; 05.01.2013
comment
Вы можете определить attr_accessible [list_of_common_attributes], как: [:default, :superadmin], attr_accessible [list_of_admin_attrs], как: :superadmin - person Nox; 19.03.2013
comment
В @poc Nox есть лишняя запятая. Следует читать: attr_accessible list_of_common_attributes, as: [:default, :superadmin] <line break> attr_accessible list_of_admin_attrs, as: :superadmin - person varatis; 26.07.2013