是否可以在ecto中的many_to_many关联中添加其他字段?

时间:2018-05-24 09:42:23

标签: postgresql phoenix-framework ecto

我是Ecto的新手。我在Ecto架构中定义了三个名为User,Role和UserRole的表。在UserRole中,我需要在关联User和Role表时更新其他字段(例如“status”),这将在UserRole表中生成一个条目。

// User Schema
schema "users" do
    field :first_name, :string
    field :last_name, :string
    field :email, :string

    many_to_many :roles, Role, join_through: "userroles"
end

// Role Schema
schema "roles" do
    field :code, :string
    field :description, :string

    many_to_many :users, User, join_through: "userroles"
end

// UserRole Schema
schema "userroles" do
    field :is_default, :boolean, default: false
    field :status, :string
    field :user_id, :id
    field :role_id, :id

    belongs_to :users, User, define_field: false
    belongs_to :roles, Role, define_field: false
end

//以下是我已经完成的步骤

  1. 使用 iex -S mix
  2. 打开iex
  3. 在用户表格中插入记录。

    一个。 userChangeset = User.changeset(%User {},%{email:“xyz @ gmail.com”,first_name:“xyz”,last_name:“z”})    湾 user1 = Repo.insert!(userChangeset)

  4. 在角色表中插入记录。

    一个。 roleChangeset = Role.changeset(%Role {},%{code:“CON”,description:“Consumer”})    湾 role1 = Repo.insert!(roleChangeset)

  5. 现在一切都很好,我在变量user1上有用户记录,在变量role1上分别有角色记录。
  6. 现在我需要关联两个记录以在UserRole表中插入记录。这将在关联user1和role1记录时自动创建
  7. 使用iex

    中的以下命令关联user1和role1记录

    一个。 userRoleAssoc = user1 |> Repo.preload(:roles)|> Ecto.Changeset.change()|> Ecto.Changeset.put_assoc(:roles,[role1])|> Repo.update!

  8. 是的,它会在UserRole上插入一条记录,如下所示enter image description here

  9. 但问题是,我需要在关联时插入状态字段。我该怎么做。
  10. 我尝试更新UserRole记录

    一个。 fetchUserRole = Repo.get_by(UserRole,id:1)

    fetchUserRole =%{fetchUserRole |状态:“有效”}

    ℃。 fetchUserRole |> Ecto.Changeset.change()|> Repo.update

  11. 它给出了以下结果。在结果中它得到更新但没有反映在我的数据库中。结果与上图一样。

    {:确定,  %UserRole的{     meta :#Ecto.Schema.Metadata<:loaded,“userroles”>,    公司:#Ecto.Association.NotLoaded,    id:1,    is_default:false,    role_id:1,    角色:#Ecto.Association.NotLoaded,    状态:“有效”,    user_id:1,    用户:#Ecto.Association.NotLoaded  }}

  12. 我的问题是,是否有任何方法可以在关联时插入字段值,如果它是一个many_to_many关联。如果是,则表示如何做到。

1 个答案:

答案 0 :(得分:1)

要真正回答#11,有一个关于您需要回答的业务逻辑的问题:

当您的用户将用户分配给某个角色时,他们是否创建新角色?或者只选择预定义的角色?

我会想象它是后者。如果是这样,我会想你可以做以下事情......

defmodule YourApp.User do
  use Ecto.Schema
  import Ecto.Changeset

  schema "users" do
    ...
    has_many :user_roles, YourApp.UserRole
  end

  def changeset(user, params) do
    user
    |> cast_things...
    |> cast_assoc(:user_roles)
  end
end

...因为您的用户永远不会更改可用的角色。只是UserRoles。哪个会让你做点像......

user = YourApp.Repo.get(YourApp.User,1)

user
|> YourApp.User.changeset(%{user_roles: [%{role_id: 1, status: "Active"}]})
|> YourApp.Repo.update

这是一种可能性。但是,我个人觉得与cast_assoc一起工作有时难以理解,特别是考虑到the preloading required and nuanced rules to process,所以我倾向于直接处理连接表。这就是为什么我在上面的评论中提到,我很困惑为什么#9和#10不能在上面工作。