#elixir #phoenix-framework
#elixir #phoenix-framework
Вопрос:
Вот три модели, которые у меня есть в настоящее время
routine.ex
defmodule DailyRoutine.Routine do
use DailyRoutine.Web, :model
schema "routines" do
field :title, :string
field :timeframe, :integer
field :content, :string
belongs_to :user, DailyRoutine.User
has_many :comments, DailyRoutine.Comment
timestamps
end
@required_fields ~w(title timeframe content)
@optional_fields ~w()
# rest of the code goes here
end
пользователь.бывший
defmodule DailyRoutine.User do
use DailyRoutine.Web, :model
schema "users" do
field :name, :string
field :username, :string
field :password, :string, virtual: true
field :password_hash, :string
has_many :routines, DailyRoutine.Routine
has_many :comments, DailyRoutine.Comment
timestamps
end
@required_fields ~w(name username)
@optional_fields ~w()
# rest of the model code goes here
end
комментарий.пример
defmodule DailyRoutine.Comment do
use DailyRoutine.Web, :model
schema "routines" do
field :content, :string
belongs_to :user, DailyRoutine.User
belongs_to :routine, DailyRoutine.Routine
timestamps
end
@required_fields ~w(user_id routine_id content)
@optional_fields ~w()
#rest of the code goes here
end
Теперь проблема в том, что я не смог найти способ в контроллере сделать несколько build_assoc
и связать их вместе, чтобы создать правильный набор изменений.
Вот мой контроллер:
comment_controller.ex
defmodule DailyRoutine.CommentController do
use DailyRoutine.Web, :controller
alias DailyRoutine.Comment
def create(conn, %{"routine_id" => routine_id, "comment" => comment_params}, user) do
routine = Repo.get!(DailyRoutine.Routine, routine_id) |> Repo.preload(:user)
changeset =
user
|> build_assoc(:comments)
|> Repo.preload(:routine)
|> Comment.changeset(comment_params)
|> Ecto.Changeset.put_assoc(:routine, routine)
case Repo.insert(changeset) do
{:ok, comment} ->
conn
|> put_flash(:info, "Your comment was successfully posted!")
|> redirect(to: routine_path(conn, :show, routine_id))
{:error, changeset} ->
redirect(conn, to: routine_path(conn, :show, routine_id))
end
end
def action(conn, _) do
apply(__MODULE__, action_name(conn), [conn, conn.params, conn.assigns.current_user])
end
end
То, что у меня есть до сих пор, не работает, и я пробовал несколько вещей, включая создание структуры вручную с конкретными отношениями id
и т. Д.
Большое спасибо!
Ответ №1:
Я бы просто ввел идентификаторы вручную в структуру и передал их Comment.changeset/2
для этого вместо того, чтобы пытаться использовать build_assoc
, поскольку у вас уже есть routine
и он user
загружен:
changeset =
%Comment{user_id: user.id, routine_id: routine_id}
|> Comment.changeset(comment_params)
case Repo.insert(changeset) do
...
end
Поскольку у вас есть routine_id
и user_id
в @required_fields
, вы также можете поместить эти идентификаторы в параметры, которые вы передаете Comment.changeset/2
:
comment_params =
comment_params
|> Map.put("user_id", user.id)
|> Map.put("routine_id", routine_id)
changeset = Comment.changeset(%Comment{}, comment_params)
Комментарии:
1. Я пробовал что-то подобное, но по какой-то причине я продолжаю получать эту ошибку:
column "routine_id" of relation "routines" does not exist
даже если у меня есть настройка отношений и столбцы в БД.2. Я на самом деле только что сделал
IEx
, и набор изменений действителен, и там все хорошо, но, похоже, проблема вcolumn_id relation
ошибке, которую я получаю3. Когда вы получаете эту ошибку? После
Repo.insert!
? Что произойдет, если вы попытаетесь вставить набор изменений изiex
?4. Только что понял, что было не так: у вас есть
schema "routines" do
вComment
модели.