2016-01-16 15 views
7

Lassen Sie uns sagen, ich habe diese Schemata:Ecto Verein mehr als eine Schemata

defmodule Sample.Post do 
    use Ecto.Schema 

    schema "post" do 
    field :title 
    has_many :comments, Sample.Comment 
    end 
end 

defmodule Sample.User do 
    use Ecto.Schema 

    schema "user" do 
    field :name 
    has_many :comments, Sample.Comment 
    end 
end 

defmodule Sample.Comment do 
    use Ecto.Schema 

    schema "comment" do 
    field :text 
    belongs_to :post, Sample.Post 
    belongs_to :user, Sample.User 
    end 
end 

Meine Frage ist, wie kann ich Ecto.build_assoc verwenden, um einen Kommentar zu speichern?

iex> post = Repo.get(Post, 13) 
%Post{id: 13, title: "Foo"} 
iex> comment = Ecto.build_assoc(post, :comments) 
%Comment{id: nil, post_id: 13, user_id: nil} 

Bisher ist es in Ordnung, alles, was ich tun muß, ist die gleiche Funktion verwenden, um die user_id in meiner Comment Struktur zu setzen, aber da der Rückgabewert von build_assocComment Struktur ist, kann ich nicht die gleiche Funktion verwendet

iex> user = Repo.get(User, 1) 
%User{id: 1, name: "Bar"} 
iex> Ecto.build_assoc(user, :comment, comment) 
** (UndefinedFunctionError) undefined function: Sample.Comment.delete/2 
... 

ich habe zwei Optionen, aber keiner von ihnen scheint mir gut:

Erste ist user_id manuell einstellen!

iex> comment = %{comment| user_id: user.id} 
%Comment{id: nil, post_id: 13, user_id: 1} 

zweite ist die Struktur zu konvertieren abzubilden und ... Ich will nicht einmal dorthin gehen

Jeder Vorschlag?

Antwort

8

Warum willst du struct nicht in map konvertieren? Es ist wirklich einfach.

build_assoc erwartet Karte der Attribute als letzten Wert. Intern versucht es den Schlüssel :__meta__ zu löschen. Structs haben Zeitgarantien kompilieren, dass sie alle definierten Felder enthalten, so Sie bekommen:

** (UndefinedFunctionError) undefined function: Sample.Comment.delete/2 

Aber man kann nur schreiben:

comment = Ecto.build_assoc(user, :comment, Map.from_struct comment) 

und alles gut funktioniert.

+0

Ich dachte, ich muss "__meta__" entfernen, bevor ich es an 'build_assoc' sende! – slashmili

3

geben Sie es einfach mit build_assoc

iex> comment = Ecto.build_assoc(post, :comments, user_id: 1) 
%Comment{id: nil, post_id: 13, user_id: 1} 

prüfen here für weitere Details entlang.

+3

Ich wollte keinen expliziten Code mit xxx_id haben – slashmili