2011-02-07 15 views
6

estoy usando dinámica attr_accessible según este artículo:mass_assignment_authorizer y atributos anidados

http://asciicasts.com/episodes/237-dynamic-attr-accessible

Trabaja muy bien. Pero no he encontrado una forma elegante de hacerlo funcionar con atributos anidados. Aquí hay un código simplificado:

class Company < ActiveRecord::Base 
    has_many :employees 

    accepts_nested_attributes_for :employees 
end 

class Employee < ActiveRecord::Base 
    belongs_to :company 

    attr_protected :salary 

    attr_accessor :accessible 

    def mass_assignment_authorizer 
    if accessible == :all 
     ActiveModel::MassAssignmentSecurity::BlackList.new 
    else 
     super + (accessible || []) 
    end 
    end 
end 

Digamos que tengo una interfaz de administrador con un formulario RESTful para una empresa. En este formulario, tengo campos para employees_attributes, que incluyen campos en blanco para crear nuevos empleados. No puedo encontrar una manera de llamar al Employee#accessible= en este contexto. Al examinar el código fuente de ActiveRecord, parece que esto podría ser imposible: en la parte más remota de una pila de llamadas muy profunda, las asociaciones anidadas solo dan como resultado que se llame a Employee.new con los atributos.

Pensé en crear un atributo especial que podría pasarse a través de la asignación masiva. Si el valor del atributo fuera el correcto, la instancia Employee establecería @accessible en :all. Pero no creo que haya una forma de garantizar que este atributo se establezca antes de los atributos protegidos.

¿Hay alguna manera de hacer que los atributos protegidos dinámicos funcionen con atributos anidados?

Respuesta

1

Esto me parece algo que se puede configurar directamente desde el código de su controlador en la clase para esta solicitud. P.ej.

Employee.accessible = :all 
Company.create(params[:company]) 
Employee.accessible = nil 

que podrían ser extrae a un bloque como

def with_accessible(*types) 
    types.flatten! 
    types.each{|type| type.accessible = :all} 
    yield 
    types.each{|type| type.accessible = nil} 
end 

Así que su código del controlador última es

with_accessible(Employee, OtherClass, YetAnotherClass) do 
    Company.create(params[:company]) 
end 

Bastante expresiva de lo que está pasando en el caso de todos los atributos

Para el caso de solo ciertos atributos, podría modificarlo al siguiente

def with_accessible(*types, &block) 
    types.flatten! 
    return with_accessible_hash(types.first, &block) if types.first.is_a?(Hash) 
    types.each{|type| type.accessible = :all} 
    ret = yield 
    types.each{|type| type.accessible = nil} 
    ret 
end 

def with_accessible_hash(hash, &block) 
    hash.each_pair do |klass, accessible| 
    Object.const_get(klass).accessible = accessible 
    end 
    ret = yield 
    hash.keys.each{|type| type.accessible = nil} 
    ret 
end 

que le da

with_accessible(:Employee => [:a, :b, :c], :OtherClass => [:a, :b]) do 
    Company.create(params[:company]) 
end 
2

Soy nuevo a los rieles, y he tenido barcos cargados de problemas tratando de conseguir atributos anidados para trabajar, pero me encontré con que tenía que añadir los atributos anidados a mi lista accesible

class Company < ActiveRecord::Base 
    has_many :employees 

    accepts_nested_attributes_for :employees 

    attr_accessible :employees_attributes 
end 

Mi entendimiento es que crea que accepts_nested_attributes_for especial employees_attributes, pero cuando usted no cumple con todos los atributos a no accesible (que creo que la asciicast hace) no será capaz de utilizarlo.

Espero que ayude.

+0

Sí, tiene que agregar employees_attributes a su lista de atributos accesibles. Pero el verdadero problema es establecer el atributo "accesible" en los propios objetos del empleado. Tenga en cuenta que esto solo es relevante cuando utiliza atributos accesibles * dinámicos *, según el artículo citado al principio de la pregunta. – rlkw1024

Cuestiones relacionadas