2016-11-19 51 views
4

我有以下模式:變更集功能關聯

schema "countries" do 

    belongs_to :code, CountryCode, references: :alpha2 
    belongs_to :language, LanguageCode, references: :code 
    field :text, :string 

    timestamps 
end 

我的問題是,如何編寫上述模式的變更功能?

我想:

def changeset(model, params \\ %{}) do 

     model 
     |> cast(params, [:text]) 
     |> cast_assoc(:code) 
     |> cast_assoc(:language) 
     |> validate_required([:code, :language, :text]) 

    end 

而且我有錯誤消息:

#Ecto.Changeset<action: nil, changes: %{text: "Switzerland"}, 
errors: [language: {"is invalid", [type: :map]}, 
    code: {"is invalid", [type: :map]}], data: #Busiket.Country<>, valid?: false> 

UPDATE

我重寫變更功能:

def changeset(model, params \\ %{}) do 

     model 
     |> cast(params, [:code_id, :language_id, :text]) 
     |> cast_assoc(:code) 
     |> cast_assoc(:language) 
     |> validate_required([:code, :language, :text]) 
end 

和我有:

#Ecto.Changeset<action: nil, changes: %{text: "Switzerland"}, 
errors: [language: {"is invalid", [type: :map]}, 
    code: {"is invalid", [type: :map]}], data: #Busiket.Country<>, valid?: false> 

對不起吧,這裏是從我的LanguageCode模式:

schema "languages_code" do 

    has_one :code, Country, foreign_key: :lang 
    field :text, :string 

    timestamps 
end 

UPDATE

我在shell再次測試:

iex(4)> v = %{code: %{code: "CH"}, language: %{alpha2: "DE"}, text: "Schweiz"} 
%{code: %{code: "CH"}, language: %{alpha2: "DE"}, text: "Schweiz"} 
iex(5)> c = Country.changeset(%Country{}, v)         
#Ecto.Changeset<action: nil, 
changes: %{code: #Ecto.Changeset<action: :insert, changes: %{}, 
    errors: [alpha2: {"can't be blank", []}, alpha3: {"can't be blank", []}], 
    data: #Busiket.CountryCode<>, valid?: false>, 
    language: #Ecto.Changeset<action: :insert, changes: %{}, 
    errors: [code: {"can't be blank", []}, text: {"can't be blank", []}], 
    data: #Busiket.LanguageCode<>, valid?: false>, text: "Schweiz"}, errors: [], 
data: #Busiket.Country<>, valid?: false> 

我忘了提及,這對作爲language_code表中的數據已經可用:

enter image description here

+0

由於您沒有發佈其餘的模式,所以很難說。您的「語言」數據可能無效。它適用於簡單情況:https://gist.github.com/stavro/9d1dcaa3c68a71880aece951005c4d97 –

+0

我在帖子上插入語言代碼模式。 –

+0

我更新了我的帖子。 –

回答

0

所產生的變更是試圖插入3個新的記錄,國家,語言代碼和COUNTRYCODE。

。在你的PARAMS足夠的數據來插入所有這些記錄:

%{code: %{code: "CH"}, language: %{alpha2: "DE"}, text: "Schweiz"} 

它不能插入COUNTRYCODE表沒有alpha2alpha3領域:

code: #Ecto.Changeset<action: :insert, 
         changes: %{}, 
         errors: [alpha2: {"can't be blank", []}, alpha3: {"can't be blank", []}], 
         data: #Busiket.CountryCode<>, 
         valid?: false>` 

它可以」 t插入到沒有codetext字段的LanguageCode表中:

language: #Ecto.Changeset<action: :insert, 
          changes: %{}, 
          errors: [code: {"can't be blank", []}, text: {"can't be blank", []}], 
          data: #Busiket.LanguageCode<>, 
          valid?: false> 

如果您不打算插入所有這些表格,那麼您需要填充language_idcode_id參數。另外

def changeset(model, params \\ %{}) do 
    model 
    |> cast(params, [:code_id, :language_id, :text]) 
    |> validate_required([:code_id, :language_id, :text]) 
end 

,您可以預載的關聯,並使用put_assoc

params = %{language_id: "DE", code_id: "CH", text: "Schweiz"} 

然後從變更功能刪除cast_assoc電話

def changeset(
     model = %Country{}, 
     country_code = %CountryCode{}, 
     language_code = %LanguageCode{}, 
     params \\ %{}) do 

    model 
    |> cast(params, [:text]) 
    |> put_assoc(:code, country_code) 
    |> put_assoc(:language, language_code) 
    |> validate_required([:text, :code, :language]) 
end 

docscast_assoc有一些額外的解釋cast_assocput_assoc之間的差異:

換句話說,當關聯的數據與父結構一起被管理時,cast_assoc/3是很有用的。如果關聯的每一邊都是分開管理的,則最好使用put_assoc/3並直接指示Ecto關聯的外觀。