2009-04-17 5 views
2

В моем текущем приложении rails я вытаскиваю много данных из базы данных в память, чтобы начать многолетнюю фоновую задачу, которую я не хочу ударять по базе данных каждый 5 секунд.Обновление загруженных ассоциаций в памяти

Это все работает отлично, но у меня есть неэлегантный код, с которым я бы хотел избавиться, если это возможно.

Для примера у меня есть ситуация, когда у меня есть модель пользователя, и что модель пользователя может ссылаться на другие модели пользователей в виде контактов, которые, в свою очередь, могут ссылаться на первую модель пользователя и так далее. Это моделируется следующим образом (благодаря Милан Novota для его ранней помощи): -

class User < ActiveRecord::Base 
    has_many :contact_records, :foreign_key => :owner_id 
    has_many :contacts, :through => :contact_records, :class_name => "User" 
end 

class ContactRecord < ActiveRecord::Base 
    belongs_to :owner, :class_name => "User" 
    belongs_to :user 
end 

Так что теперь я могу ввести

user_a_contacts = user_a.contact_records 
=> [user_b, user_c] 

и получить все контакты для пользователя а. Теперь предположим, что я хочу, чтобы получить контакты пользователя B через пользователя А (не могу понять, почему я бы, но это только пример!)

user_b_contacts = user_a_contacts.first.contact_records 
=> [user_a, user_c] 

Теперь я могу получить имя пользователя А (в свернутой, кольцевой, никогда -use-in-the-real-world)

user_a_name = user_b_contacts.first.name 
=> "Jamie" 

Пока что так хорошо. Теперь я могу изменить имя пользователя А

user_a.name = "Sandy" 
=> "Sandy" 

Если доступ к имени пользователя А снова, как и раньше из базы данных я получаю

user_a_name = user_b_contacts.first.name 
=> "Sandy" 

Однако, если я готов нагруженным и сохранил это значение в памяти я получаю

user_a_name = user_b_contacts.first.name 
=> "Jamie" 

но делает следующее дает мне правильный ответ

user_a.name 
=> "Sandy" 

Справедливо, что при желании загрузка создает различные пользовательские объекты для оригинальных пользователей и тех, кто загружен с объектов ContactRecord.

Итак (наконец-то!) Мой вопрос заключается в следующем: -

На данный момент, я bodged вокруг этого, используя

@users.each.detect{|user| user == user_b_contacts.first} 

(где @users является нетерпеливый загруженным список объектов пользователя). Есть ли способ, чтобы я мог обновлять загруженные пользователем объекты User?

Пожалуйста, обратите внимание: -

а) Я готов заряжания с помощью следующей

User.find(:all, :include => [ {:contact_records => :contacts] } ]) 

б) Очевидно, что это не реальный код, что я работаю с, но было бы еще больше объяснение и изложение, чтобы показать этот код, и я думаю, что вам надоело! Поверьте мне, что реальный пример, который я использую DOES, требует этой структуры, чтобы работать правильно, как причудливо, как может выглядеть!;)

c) Возможно, я ввел опечатки и ошибки при восстановлении примера, но, пожалуйста, проигнорируйте их. Все, что мне нужно знать, - это возможность перезагрузки пользователей с нетерпением, без попадания в базу данных.

Большое спасибо заранее!

ОБНОВЛЕНИЕ: Как указано ниже, данные модели не будут сохранены в базе данных до самого конца процесса, так что перезагрузка не будет работать, поскольку данные в базе данных не будут изменены.

ответ

4

OK. Я собираюсь сконденсировать ваш вопрос в новый вопрос и ответить на этот вопрос. Простите меня, если я неправильно понял, и это не то, о чем вы просите.

Вопрос

Если user является модель ActiveRecord, где я загрузил ассоциацию contacts загодя с User.first(:include => :contacts), как я обновить contacts ассоциацию, когда она изменилась в базе данных?

Ответ

Вы можете аннулировать кэш ассоциации двумя способами, которые я знаю. Сначала вы можете сделать:

user.reload 

, который перезагрузит всю модель пользователя с нуля. Несколько менее радикальный способ сделать это, чтобы сделать

user.clear_association_cache 

, который не будет перезагружать все user, но очистит кэш-ассоциации.

В любом случае, в следующий раз, когда вы сделаете user.contacts, он будет загружать их заново из базы данных.

0

Большое спасибо за ваш ответ, Даниэль. Хотя у вас не совсем правильный вопрос, вы заставили меня понять, что я пропустил важный момент! Запись базы данных не будет обновлена, так как я не делаю сохранения! в любой момент.

Суть того, что я делаю, это вытащить данные модели из переменных экземпляра, чтобы ускорить фоновый процесс. Таким образом, данные, загруженные в первый раз, не будут возвращены в базу данных до самого конца процесса.

На что я надеялся, это был способ, который вы могли бы указать при загрузке, когда значение одного столбца относится к другой уже загруженной модели.

Например,

User.find(:all, :include => [ {:contact_records => (:contacts as User)] } ]) 

или аналогичный.

Насколько я знаю, такого синтаксиса в Rails нет, однако я надеюсь, что я ошибаюсь! :)

Надеюсь, это немного улучшится, и еще раз спасибо за ответ.

 Смежные вопросы

  • Нет связанных вопросов^_^