2010-12-28 4 views
3

У меня возникла проблема с тем, как первичный ключ увеличивается, когда я удаляю файл из таблицы и начинаю вставлять его снова. Это проблематично, потому что у меня есть другие модели, которые связаны с очищенной таблицей. Например, если у меня есть Apple, принадлежащий к компьютеру, тогда, когда я очищаю таблицу компьютеров и снова добавляю компьютер, ассоциации становятся беспорядочными, потому что у Apple теперь есть дочерний компьютер в своих рядах. Я хочу иметь возможность сбросить первичный ключ компьютера, чтобы при повторном добавлении компьютера ассоциация оставалась неповрежденной. Как я должен делать это в рельсах?Идентификатор первичного ключа в рельсах

Редактировать Мне очень жаль, что я не знаю об этом, но теперь я скажу, что хочу, я хочу. Я хочу, чтобы пользователь был связан с машиной (компьютером). Компьютер имеет свой собственный идентификатор и может быть создан только администратором. В компьютере есть фиксированный объем компьютера.

User 
belongs_to :computer 

Computer 
has_many :users 

Проблема, с которой я столкнулся в том, что у меня есть компьютерный стол предварительно загружены в seeds.rb/некоторой rakefile. Когда я запускаю свое приложение, я хочу просто запустить файл, который сначала удаляет все, а затем предварительно загружает таблицу. Это позволит пользователю выбрать компьютер только из тех, которые указаны в таблице компьютеров. Я хочу снова запустить этот скрипт (скажем, в консоли heroku, не отбрасывая таблицу User) и по-прежнему получать одинаковый идентификатор, связанный с каждой машиной (и, следовательно, с каждым пользователем). Я смущен тем, как я должен это делать. Пожалуйста, дайте мне знать, если я буду делать это по-другому.

+0

Нельзя загружать данные такого рода семенами или светильниками или что-то еще. Он должен поддерживаться через некоторый интерфейс администратора. Не используйте два первичных ключа - вы попадете в большой беспорядок :) – klew

+0

Может быть, попытайтесь объяснить, что вы делаете и почему вы хотите это сделать. – klew

+0

Я отредактировал свой ответ – klew

ответ

11

Во-первых, вы не должны этого делать! Если вы хотите изменить запись, просто обновите строки в своей таблице. Не удаляйте его и не вставляйте в него! Если вы все еще хотите это сделать, вы должны удалить все связанные строки в других таблицах и вставить как компьютеры, так и яблоки.

Я не знаю Rails пути переустановки автоматического приращения первичного ключа, но если вы используете MySQL, то вы можете запустить пользовательский запрос:

ActiveRecord::Base.connection.execute('ALTER TABLE tablename AUTO_INCREMENT = 1') 

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

EDIT:

Как загрузить данные с id. Я не уверен, что если загрузка семенами может это сделать, но, безусловно, использование светильников может помочь. Что вам нужно подготовить computers.yml файл с данными:

First_computer: 
    id: 1 
    name: computer 

Second_computer: 
    id: 2 
    name: dell 

и т.д.

Затем вы можете использовать эту функцию, чтобы загрузить его в БД:

require 'active_record/fixtures' 

Fixtures.create_fixtures("/path/to/directory/where/your/yml/file/is/", "computers") 

Но сбросит всю таблицу (все строки будут удалены и повторно вставлены, но вы можете сохранить свои идентификаторы).

Снова хочу предупредить вас, что это плохая идея загружать данные таким образом. Светильники/семена должны использоваться только для того, чтобы засеять ваш дБ с помощью начальных (необходимых для запуска вашего приложения) данных.

Почему вы хотите сбросить эту таблицу?

+0

Вы предлагаете мне просто добавить новый компьютер, не удалив всю таблицу? Проблема, которую я испытываю, заключается в том, что когда я уничтожаю все вкладки и начинаю добавлять новые компьютеры, у пользователей будут компьютеры для новорожденных. Как мне предварительно загрузить данные, чтобы идентификатор оставался неизменным при каждом запуске скрипта для загрузки данных. – denniss

+0

Загрузка данных с помощью таблицы сбрасывает весы. Он также сбрасывает идентификаторы. – klew

+1

Вы не должны передавать другие отношения модели на этом. Это плохая идея :). Я все еще не понимаю, почему вы хотите сбросить эту таблицу? Почему бы просто не обновлять каждое поле без его удаления? Или, если это какое-то const-данные в вашем приложении, вы можете попробовать это: https://github.com/jeffp/enumerated_attribute – klew

1

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

+0

Я тоже так думал ... Я пытаюсь использовать дополнительные опции, которые предоставляют рельсы. поэтому, если я хочу, чтобы на компьютере был первичный ключ с именем machine_id (который будет использоваться в качестве внешнего ключа в Apple), могу ли я это сделать? has_many: apples, class => 'apple',: foreign_key => 'machine_id' – denniss

+0

@denniss: это действительно хорошая идея следовать «Rails way», поэтому всегда используйте 'id' в качестве первичного ключа - это много, много проще. И я не уверен, правильно ли ваша ассоциация примеров. Было бы правильно, если бы вы столбец 'machine_id' в модели/таблице Apple. Если вы могли бы добавить обе модели в свою схему вопросов и таблиц, тогда мы могли бы помочь больше. – klew

2

Это странный способ делать вещи, но если вам нужно удалить и заменить ключи в соответствующей таблице, вы можете попробовать указать :dependent => :nullify, который сохраняет связанные строки и задает внешний ключ к NULL при удалении:

class Computer 
    has_many :apples, :dependent => :nullify 
end 

class Apple 
    belongs_to :computer 
end 

c = Computer.find(some_id) 
apples = c.apples 
c.destroy # sets each foreign key in apples to NULL 
new_c = Computer.create 
new_c.apples = apples # sets each foreign key to new_c.id 
Смежные вопросы