2016-11-19 54 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关联的外观。