2016-09-17 4 views
3

Ein organization hat viele usersEcto Großeltern Schlüssel auf verschachtelte Kinder

schema "organizations" do 
    field :name, :string 
    has_many :users, TestApp.User 
end 

A user hat viele subordinates

schema "users" do 
    field :name, :string 
    belongs_to :organization, TestApp.Organization 
    belongs_to :manager, TestApp.User, 
    foreign_key: :manager_id 
    has_many :subordinates, TestApp.User, 
    foreign_key: :manager_id 
end 

Wie stelle ich sicher, Untergebene haben einen organization_id Wert, wenn sie auf die folgende Weise erzeugt werden ?

test "create Org and User and Subordinate in one step" do 
    subordinate = 
     %User{} 
     |> User.changeset(%{name: "A Subordinate"}) 

    manager = 
     %User{} 
     |> User.changeset(%{name: "A Manager"}) 
     |> Changeset.put_assoc(:subordinates, [subordinate]) 

    organization = 
     %Organization{} 
     |> Organization.changeset(%{name: "An Organization"}) 
     |> Changeset.put_assoc(:users, [manager]) 

    %{users: [ %{subordinates: [subordinate]} = manager]} = organization = Repo.insert!(organization) 

    # Passes 
    assert manager.organization_id == organization.id 
    # Fails 
    assert subordinate.organization_id == organization.id 
    end 

Antwort

0

Option1
Invoke Repo.insert! separat auf jedem changeset

subordinate = 
    %User{} 
    |> User.changeset(%{name: "A Subordinate"}) 
    |> Repo.insert! 

manager = 
    %User{} 
    |> User.changeset(%{name: "A Manager"}) 
    |> Changeset.put_assoc(:subordinates, [subordinate]) 
    |> Repo.insert! 

Helferfunktion erstellen, die Liste der Manager zurück mit ihren Untergebenen zusammen

defp managers_with_subordinates(managers) do 
    Enum.reduce(managers, [], &(&2 ++ [&1] ++ &1.subordinates)) 
end 

dann Ergebnis passieren put_assoc

users = managers_with_subordinates([manager]) 

organization = 
    %Organization{} 
    |> Organization.changeset(%{name: "An Organization"}) 
    |> Changeset.put_assoc(:users, users) 

und Ihr Muster zu

passend ändern
%{users: [user1, user2]} = organization = %Organization{} |> Organization.changeset |> put_assoc(:users, x) |> Repo.insert! 

assert user1.organization_id == organization.id 
assert user2.organization_id == organization.id 
assert user2.manager_id == user1.id 

Option2

subordinate = 
    %User{} 
    |> User.changeset(%{name: "A Subordinate"}) 
    |> prepare_changes(fn(changeset) -> 
    manager = changeset.repo.get(User, changeset.changes.manager_id) 
    changeset |> cast(%{organization_id: manager.organization_id}, [:organization_id]) 
) 
Verwandte Themen