2017-05-23 49 views
1

我有兩個表,usersroles。我想要做的是在它們之間建立簡單的關聯,即users可以有多個roleshas_many關聯,在一列中存儲多個關聯

在數據庫應該看起來像:

角色

id | name 
----------- 
    1 | ADMIN 
    2 | USER 

用戶

id | email   | username | roles 
------------------------------------- 
1 [email protected] test  [1,2] 

到目前爲止,我想出了下面的代碼:

def change do 
    create table(:users) do 
     add :email, :string 
     add :username, :string 
     add :roles, references(:roles) 
    end 
    end 

schema "users" do 
    field :email, :string 
    field :username, :string 
    has_many :roles, TimesheetServer.Role 

    timestamps() 
    end 

    def changeset(struct, params \\ %{}) do 
    struct 
     |> cast(params, [:email, :username]) 
     |> validate_required([:email, :username]) 
    end 

def change do 
    create table(:roles) do 
     add :name, :string 
     timestamps() 
    end 
    end 

schema "roles" do 
    field :name, :string 
    belongs_to :users, TimesheetServer.User 
    timestamps() 
    end 

然後我試圖種子數據庫這樣的:

User.changeset(
    %User{},%{email: "[email protected]", username: "test", roles: [ 
     %Role{name: "ADMIN"}, 
     %Role{name: "USER"} 
    ]}) 

    |> Repo.insert 

不幸的是,這並不在user表中創建角色的列表,並且不保存在roles表的作用。

任何幫助或提示將不勝感激!

+0

所以,用戶應該有很多的角色和作用應該有很多的用戶? – Ninigi

回答

2

正如在評論中提到的那樣,上述關係必須被定義爲many_to_many。爲了達到這個目標,實際上有兩種方法。

第一個是將角色模式定義爲embedded_schema,在這種情況下,它將嵌入到父級(用戶)中。這意味着不會爲角色架構創建數據庫表。

第二種選擇是通過關聯表加入他們。這可以如下所示:

遷移:

def change do 
create table(:users) do 
    add :email, :string 
    add :username, :string 
end 

create table(:roles) do 
    add :name, :string, null: false 
end 

create table(:users_roles, primary_key: false) do 
    add :user_id, references(:users, on_delete: :delete_all) 
    add :role_id, references(:roles, on_delete: :delete_all) 
end 

create unique_index(:users_roles, [:user_id, :role_id]) 
end 

用戶模式:

schema "users" do 
    field :email, :string 
    field :username, :string 
    many_to_many :roles, TimesheetServer.Role, join_through: "users_roles" 
end 

    def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:email, :username]) 
    |> validate_required([:email, :username]) 
    end 
end 

作用模式:

schema "roles" do 
    field :name, :string 
    many_to_many :users, TimesheetServer.User, join_through: "users_roles" 
    end 

    def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:name]) 
    |> validate_required([:name]) 
    end 

現在的關聯可以建立在以下方式:

user = Repo.get!(User, user_id) |> Repo.preload(:roles) 
    role = Repo.get!(Role, role_id) 

    user_changeset = Changeset.change(user) 
         |> Changeset.put_assoc(:roles, [role | user.roles]) 

,這將導致有三個表:

用戶:

id | email   | username | 
------------------------------- 
1 [email protected] test  

角色:

id | name 
----------- 
    1 | ADMIN 
    2 | USER 

users_roles:

user_id | role_id 
------------------ 
     1 | 1 
------------------ 
     1 | 2