Я перехожу на фреймворк Phoenix из Rails. До сих пор это был довольно легкий переход. Однако Phoenix новее, и у меня возникли проблемы с поиском конкретной информации:
Я использую приложение Phoenix в качестве сервисного слоя API.
Я хочу, чтобы моя форма пользовательского интерфейса (и входящие запросы curl) использовала virtual field
для поиска связанной родительской модели и заполнила changeset
дочерней модели соответствующим атрибутом. Все идет нормально:
в моей дочерней модели:
schema "child" do
field :parent_name, :string, virtual: true
belongs_to :parent, MyApp.Parent
end
...
before_insert :find_and_fill_parent
def find_and_fill_parent(changeset) do
parent = MyApp.Repo.get_by(
MyApp.Parent,
parent_name: changeset.changes.parent_name
)
changeset
|> Ecto.Changeset.put_change(:parent_id, parent.id)
end
Вот где я застрял. Я не хочу, чтобы ребенок был создан без родителя. Как и где nil
проверить родительскую модель? Все, что я пробовал, либо блокировало, либо разрешало создание безоговорочно, несмотря на условные операторы.
Похоже, мне нужно предварительно загрузить родительскую модель перед проверкой, поскольку Phoenix разработан, чтобы предотвратить злоупотребление отложенной загрузкой такими людьми, как я. . К сожалению, я не знаю, какова в целом правильная схема нагрузки, поэтому я не уверен, как ее применить здесь. (Я использую MySQL, если это уместно)
Советы и подсказки о том, где искать и на что смотреть, чтобы помочь мне понять это, приветствуются! Спасибо! ????
---EDIT---
По совету @Gazler я убедился, что у миграции моей дочерней модели есть ссылка:
create table(:child) do
add :parent_id, references(:parent)
end
Я все еще немного потерян - я хочу найти parent
по родительскому полю parent_name
("Jane Doe"
), убедиться, что родительская модель существует, и связать дочерний элемент с помощью parent_id
(1
). Я не уверен, как инициировать эти действия с использованием виртуального поля.
Итак, я не уверен, как структурировать поиск родителя, создание ассоциации и проверку проверки внешнего ключа, поскольку внешний ключ никогда не будет существовать в исходных параметрах. Мысли?
Огромное спасибо.
---РЕШЕНО---
Используя обновленный ответ @Gazler, я могу успешно проверить мою родительскую модель в дочернем контроллере без виртуального атрибута или before_insert.
def create(conn, %{"post" => post_params}) do
user = Repo.get_by(User, %{name: post_params["name"]})
if is_nil(user) do
changeset = Post.changeset(%Post{}, post_params)
else
changeset = build(user, :posts) |> Post.changeset(post_params)
end
etc
end
это проверяет входящие параметры именно так, как мне нужно! спасибо @Газлер!