Какова лучшая практика RoR? совпадать по id или другому столбцу? - PullRequest
0 голосов
/ 11 мая 2010

У меня было ужасное утро. Много писем о том, почему что-то не работает. После расследования я обнаружил, что существует несоответствие данных, которое вызывает ошибки.

Сценарий Customer и Address - две таблицы.

Customer содержит

class Customer < ActiveRecord::Base
    has_one :address, :foreign_key => "id"        
end

Address Содержит

class Address < ActiveRecord::Base
    belongs_to :customer, :foreign_key => "cid"    
end

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

Задача на странице редактирования у нас есть такой код:

params[:line1] = @customer.first.address.line1

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

Вопрос Будучи новичком в Rails, я спрашиваю, всегда ли считается целесообразным создавать дополнительный столбец для объединения записей, а не зависеть от того, какой столбец автоматически увеличивается? Если бы у меня был отдельный столбец в таблице Address, в который я бы вручную вставил недавно добавленный идентификатор клиента, эта проблема не возникла бы.

Ответы [ 2 ]

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

Это соотношение has_one - belongs_to должно привести к тому, что модель "принадлежности" будет иметь ключ модели "иметь". Или, другими словами, предложение :foreign_key должно быть одинаковым в обеих моделях.

Если у меня есть такие:

class Customer < ActiveRecord::Base
  has_one :address, :foreign_key => 'cid' # note foreign_key same as in Address
end
class Address < ActiveRecord::Base
  belongs_to :customer, :foreign_key => 'cid' # note foreign_key same as in Customer
end

тогда я могу сделать это:

>> cust = Customer.create(:name=>'Mr Custard')
+----+------------+
| id | name       |
+----+------------+
| 1  | Mr Custard |
+----+------------+
1 row in set
>> add = cust.create_address(:line_1 => '42 Some Street', :line_2 => 'Some where')
+----+-----+----------------+------------+
| id | cid | line_1         | line_2     |
+----+-----+----------------+------------+
| 1  | 1   | 42 Some Street | Some where |
+----+-----+----------------+------------+
1 row in set

проверка:

>> Customer.first.address
+----+-----+----------------+------------+
| id | cid | line_1         | line_2     |
+----+-----+----------------+------------+
| 1  | 1   | 42 Some Street | Some where |
+----+-----+----------------+------------+
1 row in set
>> Address.first.customer
+----+------------+
| id | name       |
+----+------------+
| 1  | Mr Custard |
+----+------------+

и моя база данных выглядит так:

sqlite> select * from customers;
1|Mr Custard
sqlite> select * from addresses;
1|1|42 Some Street|Some where

(кстати, хороший вывод таблицы для результатов ActiveRecord получается из Hirb )

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

Соглашение Rails заключается в том, чтобы в каждой таблице был столбец первичного ключа с автоинкрементным целым числом с именем id и дополнительно - в вашем примере & mdash; для таблицы addresses должен быть столбец внешнего ключа без автоинкрементного целого числа с именем customer_id. Как следует из названия, он содержит значение первичного ключа из связанной записи в таблице customers.

Если вы следуете этим правилам, нет необходимости указывать параметр :foreign_key для ассоциаций.

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