Change dialing function for combining

I have the following diagram:

schema "countries" do

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

    timestamps
end

My question is: how to write a change set function for the circuit above?

I tried:

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

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

  end

And I have an error message:

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

UPDATE

I rewrite the change set function:

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

and I have:

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

Sorry, here is a diagram from mine LanguageCode:

schema "languages_code" do

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

    timestamps
end

UPDATE

I am testing it again in the 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>

I forgot to mention that the data in the language_code table is already available:

enter image description here

+4
source share
1 answer

The created change set is trying to insert 3 new records: Country, LanguageCode and CountryCode.

There is not enough data in your parameters to insert all of these records:

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

It cannot be inserted into a CountryCode table without fields alpha2and alpha3:

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

LanguageCode code text:

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

, language_id code_id.

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

cast_assoc :

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

put_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

docs cast_assoc cast_assoc put_assoc:

, cast_assoc/3 , , . , put_assoc/3 Ecto, .

0

Source: https://habr.com/ru/post/1661311/


All Articles