2017-05-23 10 views
1

私は2つのテーブルusersrolesを持っています。私がしようとしているのは、usersが複数のrolesを持つことができる、それらの間の単純な関連付けを作成することです。has_many関連、複数の関連付けを1つの列に格納

データベースでは、それはそれのようになります。

役割

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として定義されなければならない。そのためには、実際には2つの方法があります。

最初に、ロールスキーマをembedded_schemaと定義すると、親(ユーザー)の内部に埋め込まれます。これは、ロールスキーマ用にdbテーブルが作成されないことを意味します。

2番目のオプションは、関連付けテーブルを使用してそれらを結合することです。次のようにそれは見ることができます:

移行:

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]) 

3つのテーブルを持つことになること:

ユーザー:

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

役割:

id | name 
----------- 
    1 | ADMIN 
    2 | USER 
今協会は、以下の方法でに構築することができます

users_roles:

user_id | role_id 
------------------ 
     1 | 1 
------------------ 
     1 | 2 
関連する問題