2016-10-04 57 views
4

我是Elixir和Ecto的新手,我需要Ecto的has_many和cast_assoc幫助。無法理解基礎知識,比如我如何用assoc關係創建新模型。如何使用Ecto的has_many和cast_assoc

這裏是我的Has_Model:

​​3210

和這裏的Belong_Model:

defmodule Example.Belong_Model do 
    use Ecto.Schema 
    import Ecto.Changeset 
    alias Example.Repo 
    alias Example.Belong_Model 

    schema "belong_models" do 
    belongs_to :has_model, Example.Has_Model 
    field :name, string 
    timestamps 
    end 

    def changeset(belong_model, params \\ %{}) do 
    belong_model 
    |> cast(params, [:name]) 
    |> cast_assoc(:has_model, required: true) 
    end 
end 

現在,我嘗試做的是首先要創建一個Has_Model

iex()> changeset = Example.Has_Model.changeset(%Has_Model, %{name: "I have"}) 
iex()> Example.Repo.insert(changeset) 

這項工作好。

然後我想創建一個新的Belong_Model和使用以前創建Has_Model它:

iex()> has = Example.Has_Model |> Example.Repo.get_by(name: "I have") 
iex()> changeset = Example.Belong_Model.changeset(%Belong_Model, %{name: "I belong", belongs_to: has}) 

而這正是它失敗:

** (Ecto.CastError) expected params to be a map, got: `%Example.Has_Model{__meta__: #Ecto.Schema.Metadata<:loaded, "has_models">, id: 1, inserted_at: #Ecto.DateTime<2016-10-04 19:39:38>, name: "I have", updated_at: #Ecto.DateTime<2016-10-04 19:39:38>, belong_models: #Ecto.Association.NotLoaded<association :belong_models is not loaded>}` 
    (ecto) lib/ecto/changeset.ex:345: Ecto.Changeset.do_cast/4 
    (example) lib/example/models/has_model.ex:15: Example.Has_Model.changeset/2 
    (ecto) lib/ecto/changeset/relation.ex:99: Ecto.Changeset.Relation.do_cast/5 
    (ecto) lib/ecto/changeset/relation.ex:235: Ecto.Changeset.Relation.single_change/5 
    (ecto) lib/ecto/changeset.ex:571: Ecto.Changeset.cast_relation/4 
    (example) lib/example/models/belong_model.ex:16: Example.Belong_Model.changeset/2 

發生了什麼事和什麼解決方案?我試着把這些參數全天調整,但我不明白。

+1

嘗試更改'%{name:「我屬於」,belongs_to:has}' - >'%{name:「我屬於」,has_model_id:has.id}'。 – Dogbert

+0

這增加了正確的id,但是現在我不能在Belong_Model變更集上使用'cast_assoc(:has_model,required:true)',否則我得到錯誤:[has_model:{「can not be blank」,[] }]' – Gulliver

回答

1

我想你正在尋找的是build_assoc/3

iex()> has = Example.Has_Model |> Example.Repo.get_by(name: "I have") 
iex()> belong_assoc = Ecto.build_assoc(has, :belong_models, has_model_id: has.id, name: "I belong") 
iex()> Repo.insert!(belong_assoc) 

而且cast_assoc/3應該是這樣使用:

iex()> changeset = Example.Belong_Model.changeset(%Belong_Model, %{name: "I belong", has_model: %{name: "I have"}) 
iex()> Repo.insert!(changeset) 

注:

對於給定關聯的參數將從changeset.params中檢索,關聯模塊中的changeset函數將會被檢索被調用

+0

使用build_assoc示例,我確實可以將關聯模型包括到新模型中,但它不使用變更集進行驗證。如果在Repo.insert!(belongs_assoc)之前,我做了'changeset = Example.changeset(%Belong_Model {},belong_assoc)''我再次得到那個'(Ecto.CastError)期望的參數是一張地圖,得到了......錯誤。 – Gulliver

+1

到目前爲止,使用現有Has_Model創建新Belong_Model的唯一工作方式是使用has_model_id而不需要:true對cast_assoc如此:'iex()> changeset = Example.Belong_Model.changeset(%Belong_Model,%{名稱:「我屬於」,has_model_id:has.id})'。如果我在Belong_Model變更集上使用'cast_assoc(:has_model,required:true)',那麼我得到一個錯誤,說它不能爲空,即使我已經使用了has_model_id ... – Gulliver