Разница между has_one и own_to в Rails?
Я пытаюсь понять has_one
отношения в RoR.
Допустим, у меня есть две модели - Person
а также Cell
:
class Person < ActiveRecord::Base
has_one :cell
end
class Cell < ActiveRecord::Base
belongs_to :person
end
Могу ли я просто использовать has_one :person
вместо belongs_to :person
в Cell
модель?
Разве это не то же самое?
3 ответа
Нет, они не взаимозаменяемы, и есть некоторые реальные различия.
belongs_to
означает, что внешний ключ находится в таблице для этого класса. Так belongs_to
ТОЛЬКО может пойти в класс, который содержит внешний ключ.
has_one
означает, что в другой таблице есть внешний ключ, который ссылается на этот класс. Так has_one
можно ТОЛЬКО перейти в класс, на который ссылается столбец в другой таблице.
Так что это неправильно
class Person < ActiveRecord::Base
has_one :cell # the cell table has a person_id
end
class Cell < ActiveRecord::Base
has_one :person # the person table has a cell_id
end
И это тоже неправильно
class Person < ActiveRecord::Base
belongs_to :cell # the person table has a cell_id
end
class Cell < ActiveRecord::Base
belongs_to :person # the cell table has a person_id
end
Правильный путь есть (если Cell
содержит person_id
поле):
class Person < ActiveRecord::Base
has_one :cell # the person table does not have 'joining' info
end
class Cell < ActiveRecord::Base
belongs_to :person # the cell table has a person_id
end
Для двусторонней ассоциации вам нужен один из них, и они должны идти в правильный класс. Даже для односторонней ассоциации важно, какой из них вы используете.
Если вы добавите "own_to", вы получите двунаправленную ассоциацию. Это означает, что вы можете получить человека из клетки, а клетку от человека.
В этом нет никакой разницы, оба подхода (с "без_ответа" и без него) используют одну и ту же схему базы данных (поле person_id в таблице базы данных ячеек).
Подводя итог: не добавляйте "assign_to", если вам не нужны двунаправленные связи между моделями.
Использование обоих позволяет получать информацию как от модели Person, так и от Cell.
@cell.person.whatever_info and @person.cell.whatever_info.