2011-02-07 20 views
6

używam dynamicznego attr_accessible zgodnie z tym artykułem:mass_assignment_authorizer i zagnieżdżonych atrybuty

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

To działa dobrze. Ale nie znalazłem eleganckiego sposobu, aby działał z atrybutami zagnieżdżonymi. Oto uproszczony kod:

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 

Załóżmy, że mam interfejs administratora z formularzem RESTULT dla firmy. W tym formularzu mam pola dla employees_attributes, w tym puste pola do tworzenia nowych pracowników. Nie mogę znaleźć sposobu na wywołanie Employee#accessible= w tym kontekście. Przeglądając kod źródłowy ActiveRecord, wydaje się, że może to być niemożliwe: w najodleglejszej części bardzo głębokiego stosu wywołań, zagnieżdżone skojarzenia powodują, że wywoływane są Employee.new z atrybutami.

Zastanowiłem się nad stworzeniem specjalnego atrybutu, który mógłby zostać przekazany w ramach przydziału masy. Jeśli wartością atrybutu byłby właściwy kod, instancja Employee ustawiłaby @accessible na :all. Ale nie sądzę, że istnieje sposób zagwarantowania, że ​​ten atrybut zostanie ustawiony przed chronionymi atrybutami.

Czy istnieje sposób na to, aby atrybuty chronione dynamicznie działały z atrybutami zagnieżdżonymi?

Odpowiedz

1

To wydaje mi się jak coś, co można ustawić bezpośrednio z kodu kontrolera na klasie dla tego żądania. Na przykład.

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

Jakie mogą być wyodrębnione do bloku jak

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

Więc twój ostateczny kod kontrolera jest

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

Dość wyraziste, co się dzieje w przypadku wszystkich atrybutów

W przypadku tylko niektórych atrybutów mogę zmodyfikować go do następującego

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 

co daje

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

Jestem nowy na szynach i mieli boatloads kłopoty próbuje dostać zagnieżdżonych atrybuty pracować samodzielnie, ale okazało się, że muszę dodać zagnieżdżone atrybutów do mojej dostępnej listy.

class Company < ActiveRecord::Base 
    has_many :employees 

    accepts_nested_attributes_for :employees 

    attr_accessible :employees_attributes 
end 

moim rozumieniu jest to, że tworzy accepts_nested_attributes_for specjalnej employees_attributes, ale kiedy Domyślnie wszystkie atrybuty nie dostępne (które wierzę asciicast robi), że nie będzie mógł z niego korzystać.

Mam nadzieję, że to pomaga.

+0

Tak, musisz dodać employees_attributes do listy dostępnych atrybutów. Ale prawdziwym problemem jest ustawienie atrybutu "dostępny" na samych obiektach pracowników. Zauważ, że ma to znaczenie tylko wtedy, gdy używasz * dynamicznych * dostępnych atrybutów, zgodnie z artykułem cytowanym na początku pytania. – rlkw1024

Powiązane problemy