Какая польза от has_one: здесь (пример из руководства по Rails) - PullRequest
4 голосов
/ 26 мая 2010

Пример скриншота http://guides.rubyonrails.org/images/has_one_through.png

Почему они используют has_one: здесь. Мы можем сделать то же самое только с has_one. Что нужно сделать новый класс. Можете ли вы дать мне хороший пример?

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

EDIT

Мы можем сделать то же самое таким образом, какой смысл делать его has_one: через

  class Supplier < ActiveRecord::Base
     has_one :account  
  end

  class Account < ActiveRecord::Base 
    belongs_to :supplier    // add a another column credit_rating in accounts table
  end

Ответы [ 4 ]

2 голосов
/ 26 мая 2010

Используется has_one :through ассоциация, потому что модель соединения (AccountHistory) содержит дополнительную информацию, связанную с ассоциацией между Supplier и Account, т.е. кредитный рейтинг.

Этот пример в руководстве по Rails довольно плохо выбран, поскольку он не дает понять, почему использование has_one :through лучше, чем использование has_one с атрибутом credit_rating в модели Account.

Вы должны использовать ассоциации has_one :through или has_many :through, когда вам нужны дополнительные атрибуты в модели соединения, которые логически не принадлежат другим моделям, которые формируют ассоциацию. Классическим примером является моделирование предоставления книг пользователям в библиотеке. Дата и продолжительность заимствования книги принадлежат модели соединения (заимствования), поскольку логически они не являются атрибутами, которые принадлежат пользователю или книге. В этом случае целесообразно использовать has_many :through ассоциацию.

1 голос
/ 26 мая 2010

Я думаю, что в этом случае все зависит от того, как вы создадите модель базы данных.Преимущество Rails в том, что, если вы работаете с какой-либо устаревшей базой данных, она может работать практически со всеми типами отношений.И в этом случае вы должны использовать: has_one: through, потому что таблицы вашей базы данных смоделированы таким образом.

Преимущества использования трех предлагаемых моделей: существует чистое разделение между Account и AccountHistory.,Хотя вы можете смоделировать Account и AccountHistory как одну комбинированную модель, в этом нет необходимости.Это может показаться не таким полезным в таком небольшом примере, но, например:

  • предположим, что к AccountHistory подключено много журналов, чтобы можно было рассчитать, является ли какая-то учетная запись надежной (или что угодно);в этой настройке обе модели не нужно загружать одновременно: теперь вы можете использовать только код учетной записи или AccountHistory
  • код, относящийся к любой из моделей (история или нет), теперь разделен, что делает ваши намерениямодели уборщика
1 голос
/ 26 мая 2010

В некоторых случаях вы можете не захотеть добавлять определенное поле в таблицу. В вашем примере вам действительно нужна только одна таблица, поскольку вы можете просто добавить account_number и credit_ranking к таблице suppliers. Но иногда полезно хранить данные в нескольких таблицах. Затем вы должны использовать отношение has_one (один-к-одному).

В вашем примере вы также можете просто добавить атрибут supplier_id к account_histories и заменить has_one :account_history, :through account просто has_one :account_history, но это будет избыточно и также усложнит ваш код, так как вам нужно убедиться, что вы делаете не меняйте один атрибут и не забудьте обновить другой.

UPDATE:

Если вы не добавите атрибут supplier_id к account_histories, тогда Rails не сможет определить, какая строка из этой таблицы принадлежит какому поставщику. Единственный способ выяснить это - посмотреть в соответствующей таблице accounts. Без accounts вы не сможете определить, какой account_history принадлежит поставщику, так как в таблице accounts_histories нет внешних ключей для таблицы suppliers.

Чтобы получить account_history для поставщика без опции :through, вам нужно будет сделать это:

Supplier.find(id).account.account_history

:through позволяет заменить его следующим:

Supplier.find(id).account_history

Как вы написали в своем обновлении, вы можете добавить атрибут credit_ranking к accounts и иметь только две таблицы. Это было бы еще проще, но вы можете просто не сохранять этот атрибут в той же таблице (потому что, возможно, у вас уже есть много других атрибутов и вы не хотите добавлять их еще больше).

1 голос
/ 26 мая 2010

Поскольку с помощью has_one :through вы можете добавить больше атрибутов к Account

...