mass_assignment_authorizer и вложенные атрибуты - PullRequest
6 голосов
/ 07 февраля 2011

Я использую динамический attr_accessible согласно этой статье:

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

Работает нормально. Но я не нашел элегантного способа заставить его работать с вложенными атрибутами. Вот упрощенный код:

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

Допустим, у меня есть интерфейс администратора с формой RESTful для компании. В этой форме у меня есть поля для employees_attributes, включая пустые поля для создания новых сотрудников. Я не могу найти способ позвонить Employee#accessible= в этом контексте. Просматривая исходный код ActiveRecord, кажется, что это может быть невозможно: в самой удаленной части очень глубокого стека вызовов вложенные ассоциации просто приводят к вызову Employee.new с атрибутами.

Я думал о создании специального атрибута, который можно было бы передать через массовое назначение. Если значение атрибута было правильным кодом, экземпляр Employee установил бы @accessible в :all. Но я не думаю, что есть способ гарантировать, что этот атрибут будет установлен перед защищенными атрибутами.

Есть ли способ заставить динамически защищенные атрибуты работать с вложенными атрибутами?

Ответы [ 2 ]

2 голосов
/ 08 ноября 2012

Я новичок в rails, и у меня были проблемы с попытками заставить вложенные атрибуты работать самостоятельно, но я обнаружил, что мне пришлось добавить вложенные атрибуты в мой доступный список.Насколько я понимаю, accepts_nested_attributes_for создает это специальное employees_attributes, но когда вы по умолчанию все атрибуты недоступны (что, я считаю, asciicast), вы не сможете его использовать.это помогает.

1 голос
/ 25 сентября 2011

Мне кажется, это что-то, что можно установить прямо из кода вашего контроллера в классе для этого запроса.Например,

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

Который может быть извлечен в блок типа

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

Итак, ваш окончательный код контроллера равен

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

Довольно выразительно, что происходитрегистр всех атрибутов

Для случая только определенных атрибутов я мог бы изменить его на следующий

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

, что дает вам

with_accessible(:Employee => [:a, :b, :c], :OtherClass => [:a, :b]) do
  Company.create(params[:company])
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...