Как отслеживать образцовую историю с таблицей отображения в Ruby on Rails?

мечта

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

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

возможная схема

users (
  id
  username
  email
  ...
)

user_addresses (
  id
  label
  line_1
  line_2
  city
  state
  zip
  ...
)

user_addresses_map (
  user_id
  user_address_id
  start_time
  end_time
)

orders (
  id
  user_id
  user_address_id
  order_status_id
  ...
  created_at
  updated_at
)

в sql это могло бы посмотреть что-то как: [sql]

select ua.*

from  orders    o

join  users     u
  on  u.id = o.user_id

join  user_addressses_map   uam
  on  uam.user_id = u.id
  and uam.user_address_id = o.user_address_id

join  user_addresses        ua
  on  ua.id = uam.user_address_id
  and uam.start_time < o.created_at
  and (uam.end_time >= o.created_at or uam.end_time is null)
;

править: Решение

@KandadaBoggu отправил отличное решение. Плагин Версий Девственницы является отличным решением.

отрывок ниже взятого из http://github.com/laserlemon/vestal_versions

Наконец, управление версиями DRY ActiveRecord!

acts_as_versioned технососиской был большим запуском, но ему не удалось не отставать от введения ActiveRecord грязных объектов в версии 2.1. Кроме того, для каждой имеющей версию модели нужна ее собственная таблица версий, которая копирует большинство столбцов исходной таблицы. Таблица версий затем заполняется с записями, которые часто копируют большинство атрибутов исходной записи. В целом, не очень DRY.

vestal_versions требует только одной таблицы версий (полиморфно связанный с ее родительскими моделями) и никакие изменения вообще в существующих таблицах. Но это идет одна СУШИЛКА шага путем хранения сериализированного хеша только изменений моделей. Думайте современные системы управления версиями. Путем пересечения записи изменений модели могут вернуться к любому моменту времени.

И это, что делает vestal_versions. Мало того, что модель может вернуться к предыдущему номеру версии, но также и на дату или время!

9
задан maček 22 March 2010 в 15:30
поделиться

4 ответа

Используйте плагин Vestal versions для этого:

См. этот экран для более подробной информации.

class Address < ActiveRecord::Base
  belongs_to :user
  versioned
end


class Order < ActiveRecord::Base
   belongs_to :user

   def address
     @address ||= (user.address.revert_to(updated_at) and user.address)
   end
end
13
ответ дан 4 December 2019 в 08:00
поделиться

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

... когда заказ будет размещен, он будет { {1}} всегда может ссылаться на адрес пользователя , который использовался во время размещения заказа .

... вы просто копируете адрес человека в модель Заказа. Элементы будут в модели OrderItem. Я бы переформулировал проблему следующим образом: «Заказ происходит в определенный момент времени. OrderHeader включает в себя все соответствующие данные в этот момент времени».

Это ненормально?

Нет, потому что OrderHeader представляет собой момент времени, а не текущая «правда».

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

- Придерживайтесь решения, которое решает настоящую проблему, а не возможные проблемы - кому-нибудь нужна история изменений пользователя? Или вам просто нужны заголовки заказа, чтобы отразить реальность самого заказа?

Добавлено: Обратите внимание, что вам нужно знать , на какой адрес в конечном итоге был отправлен заказ / счет. Вы не хотите смотреть на старый заказ и видеть текущий адрес пользователя, вы хотите увидеть адрес, который заказ использовал при отправке заказа. См. Мой комментарий ниже, чтобы узнать больше об этом.

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

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

4
ответ дан 4 December 2019 в 08:00
поделиться

Я думаю, это будет так просто:

Users:
  id
  name
  address_id

UserAddresses:
  id
  user_id
  street
  country
  previous_address_id

Orders
  id
  user_id #to get the users name
  user_address_id #to get the users address

Затем, когда пользователь меняет свой адрес, вы выполняете своего рода «логическое удаление» на старом data, создав новый UserAddress и установив поле "previous_address_id" как указатель на старые данные. Это устраняет необходимость в вашей таблице карты и создает своего рода связанный список . Таким образом, всякий раз, когда размещается заказ, вы связываете его с определенным UserAddress, который гарантированно никогда не изменится.

Еще одним преимуществом этого является то, что он позволяет вам отслеживать изменения адреса пользователей, что-то вроде рудиментарного регистратора.

0
ответ дан 4 December 2019 в 08:00
поделиться

Вы ищете плагин acts_as_audited. Он предоставляет таблицу аудитов и модель для использования вместо вашей карты.

Чтобы установить его, запустите миграцию и добавьте следующее в модель адресов пользователей.

class UserAddress < ActiveRecord::Base
  belongs_to :user
  acts_as_audited
end

После того, как вы настроите это, все, что вам нужно сделать, это определить метод адреса в заказе. Что-то вроде этого:

class Order < ActiveRecord::Base
   belongs_to :user
   attr_reader :address

   def address
     @address ||= user.user_address.revision_at(updated_at)
   end
end

И вы сможете получить доступ к адресу пользователя в момент завершения заказа с помощью @order.address

revision_at - это метод, добавленный в модель аудита с помощью acts_as_audited. Он берет временную метку и восстанавливает модель в том виде, в котором она была в этот момент времени. Я полагаю, что он собирает ревизию из аудитов, проведенных в этой конкретной модели до указанного времени. Поэтому не имеет значения, совпадает ли updated_at в заказе с точным временем.

2
ответ дан 4 December 2019 в 08:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: