Полиморфные Запросы Таблицы Отношений в Rails - найти объект по нескольким
У меня есть таблица отношений в приложении рельсы под названием edit_privileges
, в котором User
"редактор" и ряд других классов "редактируемые". Скажем, два из этих классов Message
а также Comment
,
мой EditPrivilege
Модель использует следующий код:
belongs_to :editor, :class_name => "User"
belongs_to :editable, :polymorphic => true
А также User
, конечно
has_many :edit_privileges, :foreign_key => "editor_id"
Чтобы определить, есть ли у пользователя права на редактирование для определенной модели, я не могу выполнить обычный запрос:
user.edit_privileges.find_by_editable_id(@message.id)
потому что, если у пользователя есть права на редактирование комментария с тем же идентификатором, что и @message
запрос вернет истину с неверной записью прав на редактирование из таблицы.
Итак, я попытался сделать эти варианты:
user.edit_privileges.find(:all, :conditions => ["editable_id = ? AND editable_type ?", @message.id, @message.class.to_s])
user.edit_privileges.where(:editable_id => @message.id, :editable_type => @message.class.to_s)
который отлично работает при поиске нужной записи, но возвращает массив вместо объекта (пустой массив []
если нет прав на редактирование). Это особенно проблематично, если я пытаюсь создать метод уничтожения прав на редактирование, поскольку вы не можете передать .destroy
на массиве.
Я фигура дополняет .first
к двум вышеупомянутым решениям возвращается первый объект и nil
если результат запроса пустой, но действительно ли это лучший способ сделать это? Есть ли проблемы с этим? (например, вместо использования динамических искателей на основе атрибутов, таких как find_by_editabe_id_and_editable_type
)
1 ответ
Использование find(:first, ...)
вместо find(:all, ...)
чтобы получить одну запись (обратите внимание, что она может вернуть nil, в то время как find вызовет исключение RecordNotFound). Итак, для вашего примера:
user.edit_privileges.find(:first, :conditions => { :editable_id => @message.id, :editable_type => @message.class.to_s })
Кстати, если вы находитесь на более краевых рельсах версии (3.x), Model.where(...).first
это новый синтаксис:
user.edit_privileges.where(:editable_id => @message.id, :editable_type => @message.class.to_s).first