Управление дочерними отношениями с помощью формы вложенного атрибута
-
11-09-2019 - |
Вопрос
Я пытаюсь сделать следующее:
В любой момент у пользователя может быть 1 активный профиль.Этот активный профиль должен быть авторизован администратором, чтобы убедиться в его соответствии правилам и положениям сайта.Когда пользователь редактирует свой профиль, его общедоступный профиль не затрагивается, пока администратор не подпишет его изменения.Если они вносят изменения, пока их профиль находится на проверке, их изменения применяются к профилю, ожидающему рассмотрения, и помещаются в конец очереди.
Мои модели выглядят примерно так:
class Profile < AR:B
belongs_to :user
end
class User < AR:B
has_many :profiles do
def active
...
end
def latest
end
end
def profile
self.profiles.active
end
end
Есть один маленький нюанс...пользователь не должен иметь возможность редактировать профиль напрямую, поскольку коллекция профилей не отображается.Вместо этого они редактируют своего пользователя, и там отображаются поля профиля.
Какой лучший способ справиться с этим?В настоящее время я использую:
accepts_nested_attributes_for :profiles
В пользователе, но это кажется довольно хакерским.В идеале большая часть этой логики должна присутствовать в модели, но еще одна вещь, с которой я заигрываю, — это использование презентатора.
Буду очень признателен за любые мысли, дайте мне знать, если вам нужна дополнительная информация, в виде комментария, и я соответствующим образом обновлю этот пост.
Решение
Возможно, вам стоит попробовать установить два отношения от пользователя к профилю.Один из них можно редактировать через ваш пользовательский интерфейс, а другой — тот, который одобрен администратором.
Это может работать примерно так:
class User < AB:B
has_one :profile #the user-editable one one
has_one :active_profile, :class_name=>"profile" #the one shown
end
Каждое изменение в профиле пользователя через форму затем будет отображаться для администратора (с использованием и наблюдателя или, может быть, просто фильтра «after_save»).Когда он это одобряет, изменения затем сбрасываются в файл active_profile и где-то отображаются.
Таким образом, вы можете иметь чистый интерфейс формы, и всякий раз, когда они снова его редактируют, они видят последний (но не утвержденный) профиль.Вы также можете упорядочить очередь, используя столбец update_at, чтобы получить функцию «их изменения применяются к выдающемуся профилю для проверки и помещаются в конец очереди».
Другие советы
Я бы сделал это, заставив модель пользователя иметь связь с двумя профилями, как предложено выше.Один «Одобренный» профиль и тот, который для редактирования попадает в вашу очередь администратора.
Однако, чтобы обрабатывать переходы между «ожидающими» профилями и «утвержденными» профилями, я бы предложил добавить конечный автомат для обработки переходов.Камень AASM пригодился мне в недавнем проекте.(http://github.com/rubyist/aasm/tree/master), и я считаю, что Edge Rails также только что внедрил State Machinage.(http://github.com/rails/rails/commit/aad5a30bf25d8a3167afd685fc91c99f4f09cc57)
Ваша модель может выглядеть примерно так:
class User < AR:B
has_one :active_profile
has_one :pending_profile
include ActiveRecord:: StateMachine
state_machine do
state :approved
state :pending
state :rejected
event :update_profile_pending do
transitions :to => :pending, :from => [:approved], :on_transition => :send_to_admin_queue
end
event :update_profile_approved do
transitions :to => :approved, :from => [:pending], :on_transition => :update_current_profile
end
event :update_to_rejected do
transitions :to => :rejected, :from => [:pending]
end
end
def send_to_admin_queue
//method to handlesending pending profiles to admin for approval
end
def update_current_profile
//method to handle updated profiles with changes
end
end
Затем вы можете вызвать ожидание профиля User.update!или Профиль User.update одобрен!для перехода между состояниями вашего профиля и использования обратных вызовов перехода для обработки отправки данных редактирования между вашим активным профилем и ожидающим профилем.
Что касается использованияnested_attributes_for с вашей реальной формой, я не думаю, что это хак, я также использовал его для обновления вложенных атрибутов, и все работает нормально.В этом случае вам это может и не понадобиться, поскольку у вас есть 2 профиля (один общедоступный, другой ожидающий).
Просто идея!Мысли вслух здесь!