3

Совсем недавно перешел на Rails 5.0.0.1 и не совсем понимаю кое-каких вещей, связанных с ассоциациями Active Record. Либо я что-то упускаю (давно не брался за рельсы).

В 4-ой версии рельс я мог спокойно проделать следующие действия, не получив при этом ни одной ошибки.

rails g model Parent name:string
rails g model Child name:string parent:references
rake db:migrate

rails c

Parent.create name: "Papa"
p = Parent.last
Child.create name: "Son"
c = Child.last

После этих нехитрых действий можно было спокойно производить следующие действия:

p.children << c # Добавить "Son" к "Papa"
p.children # Вывести список всех дочерних записей
c.parent # Посмотреть родителя c
c.parent = p # Напрямую установить родителя для c

Это все было довольно очевидно и удобно.

Но сейчас я обновился до 5-ой версии рельс и не совсем понимаю, что происходит.

Сначала я произвел стандартные операции:

rails g model Parent name:string
rails g model Child name:string parent:references
rails db:migrate

Ничего нового.

rails c

Parent.create name: "Papa"
p = Parent.last
Child.create name: "Son" # *

И в строке (*) я натыкаюсь на нечто. Что именно - точно сказать не могу. Конкретно происходит следующее:

(0.1ms) begin transaction

(0.1ms) rollback transaction

Судя по всему дело в том, что я не указал, к какому родителю относится потомок, потому как если сделать что-то типа

p.children.create name: "Son"

То тогда я уже никаких роллбэков не получаю и транзакция выполняется.

Собственно, вопрос: я что-то упускаю/делаю неправильно, или действительно больше нельзя создавать модель, которая является наследником другой модели, не указывая при этом родителя? И если это так, то есть ли какой-то способ вернуть прежнее поведение? Ведь может быть такая ситуация, что есть много дочерних моделей и много родителей, но не все дочерние используются. Как тогда их создавать?

smellyshovel
  • 5,224
  • Разумеется, речь в вопросе касается ассоциации has_many - belongs_to, как с остальными - не проверял, но, уверен, ситуация та же. – smellyshovel Sep 29 '16 at 19:10
  • А ларчик просто открывался: Child.create(name: "Son").errors.messages => {:parent=>["must exist"]} –  Sep 29 '16 at 19:50
  • @D-side да я что-то о bang-методах забыл. На фронтенд просто на время переключался. Мечусь меж двух огней, постоянно что-то из головы вылетает :D – smellyshovel Sep 30 '16 at 14:01
  • Во, вы ещё один способ узнать о проблеме нашли. Можете же, когда хотите :) –  Sep 30 '16 at 14:02
  • @D-side все равно обычно проще консультацию у профессионала типа вас получить. Ну а так да, само собой сразу сам ищу решение. – smellyshovel Sep 30 '16 at 14:27
  • @D-side а вот кстати еще вопрос появился. Опциональность связи нужно указывать только в строке с belongs_to или с has_many тоже? В плане has_many :children, optional: true. Или так не нужно делать? – smellyshovel Sep 30 '16 at 14:30
  • А можно стать профессионалом самому, и тогда проще станет всё :) Что касается has_many, то в документации такого атрибута там просто нет. –  Sep 30 '16 at 14:33
  • @D-side Доходчиво, благодарю. А для того, чтобы стать профессионалом нужны годы. Я думаю, у вас не один год ушел на это. – smellyshovel Sep 30 '16 at 14:35
  • Полтора. Заглядывайте в чатик по теме, если интересно поболтать по этому поводу. –  Sep 30 '16 at 14:44

1 Answers1

2

Во-первых, запустите последнюю команду с bang-методом create! вместо create - тогда в консоли увидите причину невыполнения операции:

p.children.create! name: "Son"

Во-вторых, вы верно предположили - в консоли вы увидите объяснение, что у объекта модели Child не указан обязательный параметр parent. Почему обязательный? Потому что в Rails 5 все связи belongs_to стали обязательными по-умолчанию.

В четвертых рельсах:

belongs_to :parent                  # по-умолчанию необязательная связь
belongs_to :parent, required: true  # уточняем обязательность связи

В пятых рельсах:

belongs_to :parent                  # по-умолчанию обязательная связь
belongs_to :parent, optional: true  # уточняем необязательность связи
  • Значит не зря я грешил на нововведения в самих рельсах :) Что ж, спасибо! Кстати, раз уж тут речь о нововведениях зашла, не подскажете, где можно откопать инфу обо всем новом, что добавили (удалили) в пятых рельсах? – smellyshovel Sep 29 '16 at 19:22
  • http://blog.bigbinary.com/categories/Rails-5 – Виталий Емельянцев Sep 29 '16 at 19:23
  • Благодарю, надо будет ознакомиться. Спасибо еще раз за объяснение. – smellyshovel Sep 29 '16 at 19:24