В настоящее время я использую Rails 2.3.9. Я понимаю, что указание опции :joins
в запросе без явного :select
автоматически делает любые записи, которые возвращаются только для чтения. У меня есть ситуация, когда я хотел бы обновить записи, и пока я читал о различных способах подхода к ней, мне было интересно, какой путь является предпочтительным или "правильным".
В частности, моя ситуация заключается в том, что у меня есть следующая модель User
с областью имен с именем active
, которая выполняет JOIN с таблицей subscriptions
:
class User < ActiveRecord::Base
has_one :subscription
named_scope :active, :conditions => { :subscriptions => { :status => 'active' } }, :joins => :subscription
end
Когда я вызываю User.active.all
, возвращаемые пользователем записи доступны только для чтения, поэтому, если, например, я вызываю update_attributes!
для пользователя, ActiveRecord::ReadOnlyRecord
будет поднят.
С помощью чтения различных источников кажется популярным способом обойти это, добавив :readonly => false
к запросу. Однако мне было интересно следующее:
- Является ли это безопасным? Я понимаю, почему Rails устанавливает его только для чтения, потому что, согласно Документация Rails, "они будут иметь атрибуты, которые не соответствуют столбцам таблиц". Однако SQL-запрос, который генерируется из этого вызова, использует
SELECT `users`.*
в любом случае, что кажется безопасным, , так что Rails пытается защитить в первую очередь? Похоже, что Rails должен быть защищая от случая, когда:select
действительно явно указано, что является обратным действию, , так я не правильно понимаю цель автоматической установки флага только для чтения на:joins
? - Это похоже на взлом? Не похоже, чтобы определение именованной области должно заботиться о явной настройке
:readonly => false
. Я также боюсь побочных эффектов, если названная область скопирована с другими названными областями. Если я попытаюсь указать его вне области действия (например, выполнивUser.active.scoped(:readonly => false)
илиUser.scoped(:readonly => false).active
), он не работает.
Другим способом, который я прочитал, чтобы обойти это, является изменение :joins
на :include
. Я понимаю поведение этого лучше, но существуют ли какие-либо недостатки (кроме ненужного чтения всех столбцов в таблице subscriptions
)?
Наконец, я мог бы снова получить запрос с помощью идентификаторов записей, вызвав User.find_all_by_id(User.active.map(&:id))
, но я считаю, что это скорее обходное решение, чем возможное решение, поскольку оно генерирует дополнительный SQL-запрос.
Есть ли другие возможные решения? Каким будет предпочтительное решение в этой ситуации? Я прочитал ответ, указанный в qaru.site/info/32676/..., но он не кажется дать конкретное руководство относительно того, что будет считаться правильным.
Спасибо заранее!