Сложные объединения с устаревшими таблицами в Rails - PullRequest
3 голосов
/ 15 декабря 2009

Я пишу довольно простой веб-интерфейс для базы данных счетов / клиентов / контрактов. Я хотел бы иметь следующую структуру для моих моделей:

class Invoice < ActiveRecord::Base
   set_table_name 't10_invoices'
   set_primary_key 'id_invoice'
   has_one :client
end

class Client < ActiveRecord::Base
   set_table_name 't20_clients'
   set_primary_key 'id_client'
   has_many :invoices
end

Проблема в том, что у меня следующая структура базы данных:

Tables:
t10_invoices:
   id_invoice - primary_key
   id_contract - foreign_key


t12_contracts:
   id_contract - primary_key      

t15_contracts_clients
   id_client - foreign_key
   id_contract - foreign_key

t20_clients
   id_client - primary_key

Существует соотношение 1-1 между t20_clients и t12_contracts до t15_contracts_clients и существует отношение 1-n между t20_clients и t10_invoices.

В чем разница между :foreign_key и :association_foreign_key?

Проблема в том, что я не могу изменить структуру базы данных, и я совершенно заблудился в переопределении имен таблиц, внешних ключей, join_foreign_keys и т. Д. Я хотел бы простой способ найти клиентов счета-фактуры обычным способом Rails Invoice.find(:first).client

Буду признателен за любые предложения и помощь.

Ответы [ 3 ]

2 голосов
/ 15 декабря 2009

Создайте ContractClient модель соединения, соответствующую таблице t15_contracts_clients. Это определяет имя таблицы и использует belongs_to ассоциации для 2 внешних ключей:

class ContractClient < ActiveRecord::Base
  set_table_name 't15_contracts_clients'
  belongs_to :client, :foreign_key => :id_client
  belongs_to :contract, :foreign_key => :id_contract
end

Укажите таблицу и первичный ключ для Client:

class Client < ActiveRecord::Base
  set_table_name 't20_clients'
  set_primary_key 'id_client'
end

Используйте belongs_to :contract_client в счете, а затем has_one :through, чтобы связать клиента через ContractClient:

class Invoice < ActiveRecord::Base
  set_table_name 't10_invoices'
  set_primary_key 'id_invoice'
  belongs_to :contract_client, :foreign_key => :id_contract
  has_one :client, :through => :contract_client
end

Invoice.find(:first).client должен тогда вести себя как ожидалось.

2 голосов
/ 15 декабря 2009

У вас есть пара странностей в модели. Он не настроен таким образом, чтобы клиент has_one заключал контракт. Посередине находится таблица соединений, которая позволяет заключать несколько контрактов на одного клиента. Так как вы не можете изменить таблицы, лучше просто применять любые отношения в коде. Поскольку эта таблица, по-видимому, не имеет первичного ключа, вам, вероятно, нужно использовать has_and_belongs_to_many. В этом типе отношений :association_foreign_key для «другого» класса, а :foreign_key для класса, в котором вы находитесь.

class Invoice < ActiveRecord::Base
   set_table_name 't10_invoices'
   set_primary_key 'id_invoice'
   belongs_to :contract, :foreign_key => 'id_contract'
   has_one :client, :through => :contract
end

class Contract
  set_table_name 't12_contracts'
  set_primary_key 'id_contract'
  has_and_belongs_to_many :clients, 
                           :join_table => 't15_contracts_clients' 
                           :foreign_key => 'id_contract',
                           :association_foreign_key => 'id_client'
  has_many :invoices, :foreign_key => 'id_contract'
end

class Client < ActiveRecord::Base
   set_table_name 't20_clients'
   set_primary_key 'id_client'
   has_and_belongs_to_many :clients, 
                           :join_table => 't15_contracts_clients' 
                           :foreign_key => 'id_client',
                           :association_foreign_key => 'id_contract'
   has_many :invoices, :through => :contracts
end

Затем вам нужно вызвать

Invoice.find(:first).client
1 голос
/ 15 декабря 2009

Рассматривали ли вы создание базы данных view ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...