Пользовательская запись в БД для 3 way habtm в ROR - PullRequest
3 голосов
/ 04 декабря 2011

Я конвертирую существующее приложение perl gtk в приложение ROR

У меня есть модель трехсторонней ассоциации habtm.

class CustomerMaster < ActiveRecord::Base
  has_and_belongs_to_many :address_master, :join_table => "customer_phone_addres"
  has_and_belongs_to_many :phone_master, :join_table => "customer_phone_address"

class AddressMaster < ActiveRecord::Base
    has_and_belongs_to_many :customer_master, :join_table => "customer_phone_addres"
    has_and_belongs_to_many :phone_master, :join_table => "customer_phone_addres"

class PhoneMaster < ActiveRecord::Base
  has_and_belongs_to_many :customer_master, :join_table => "customer_phone_addres"
  has_and_belongs_to_many :address_master, :join_table => "customer_phone_addres"

Таблица соединений имеет следующую схему

CREATE TABLE customer_phone_address
(
  id bigserial NOT NULL,
  customer_master_id bigint,
  phone_master_id bigint,
  address_master_id bigint,
  CONSTRAINT customer_phone_address_pkey PRIMARY KEY (id),
  CONSTRAINT address FOREIGN KEY (address_master_id)
      REFERENCES address_master (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT customer FOREIGN KEY (customer_master_id)
      REFERENCES customer_master (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT phone FOREIGN KEY (phone_master_id)
      REFERENCES phone_master (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT uniq_cust_phone_address UNIQUE (customer_master_id, phone_master_id, address_master_id)
)

И я создал вложенную форму для customer_master # new, которая принимает данные как для address_master, так и phone_master

Изначально для приложения perl gtk в join_table создается только одна запись для каждой записи клиента, адрес и телефон

id|customer_master_id|phone_master_id|address_master_id
186767|182774|500773|210683

Однако, используя вышеуказанную модель отношений, я получаю две записи в случае ROR

id|customer_master_id|phone_master_id|address_master_id
186769|182810|500775|nil|
186770|182810|nil|211935|

Мне необходимо поддерживать обратную совместимость с приложением perl gtk. Как получить эту единственную запись в объединяющей таблице вместо двух?

Мне кажется, этот вопрос похож на https://stackoverflow.com/questions/5507150/custom-join-3-tables-usage-in-rails-2-3-8

1 Ответ

4 голосов
/ 07 декабря 2011

Предположим, вы используете Rails 3.

Вы должны использовать habtm, когда в вашей таблице соединений есть только 2 внешних ключа. В большинстве случаев has_many :through будет более гибким.

В вашем случае вы должны создать модель для таблицы соединений. Во-первых, вы должны отключить множественное число для старой схемы БД. (Я думал, ты уже сделал это).

# In config/application.rb
config.active_record.pluralize_table_names = false

Создайте таблицу соединений, а именно CustomerPhoneAddress по соглашению (я дам ей более осмысленное имя):

# customer_phone_address.rb
class CustomerPhoneAddress < ActiveRecord::Base
  belongs_to :address_master
  belongs_to :customer_master
  belongs_to :phone_master
end

Наконец, свяжите ваши модели с has_many и has_many :through:

# address_master.rb
class AddressMaster < ActiveRecord::Base
  has_many :customer_phone_addresses
  has_many :customer_masters, :through => :customer_phone_addresses
  has_many :phone_masters, :through => :customer_phone_addresses
end

# customer_master.rb
class CustomerMaster < ActiveRecord::Base
  has_many :customer_phone_addresses
  has_many :address_masters, :through => :customer_phone_addresses
  has_many :phone_masters, :through => :customer_phone_addresses
end

# phone_master.rb
class PhoneMaster < ActiveRecord::Base
  has_many :customer_phone_addresses
  has_many :customer_masters, :through => :customer_phone_addresses
  has_many :phone_masters, :through => :customer_phone_addresses
end

Я протестировал код, и он работает очень хорошо. Чтобы создать ассоциацию:

CustomerPhoneAddress.create(
  :phone_master => PhoneMaster.first,
  :address_master => AddressMaster.first,
  :customer_master => CustomerMaster.first)

Для запроса ассоциации:

IRB> a = AddressMaster.first
=> #<AddressMaster id: 1, created_at: "2011-12-07 15:23:07", updated_at: "2011-12-07 15:23:07">
IRB> a.customer_masters
=> [#<CustomerMaster id: 1, created_at: "2011-12-07 15:23:15", updated_at: "2011-12-07 15:23:15">]
IRB> a.phone_masters
=> [#<PhoneMaster id: 1, created_at: "2011-12-07 15:23:19", updated_at: "2011-12-07 15:23:19">]
IRB> a.customer_phone_addresses
=> [#<CustomerPhoneAddress id: 1, address_master_id: 1, customer_master_id: 1, phone_master_id: 1, created_at: "2011-12-07 15:24:01", updated_at: "2011-12-07 15:24:01">]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...