softshipper
softshipper

Reputation: 34119

A list of maps as argument

I created a schema that looks as follow:

schema "countries" do

    field :code, :string
    field :en, :string
    field :de, :string
    field :it, :string
    field :fr, :string

    timestamps

  end

Now a I want to create changeset function that would accept a list of map. How can I define it? Is this right(I would say it is wrong):

def changeset_all(model, []) do

Then how can I validate if the passed parameter contains maps or not?

The second question is, how can I loop through the list of maps, that after I would get a changeset of all pass values? I would do like this:

def changeset_all(model, [params]) do

  for param <- [params] do
      model
      |> cast(param, [:code, :en, :de, :it, :fr])
      |> validate_required([:code, :en])
      |> validate_length(:code, max: 3)
      |> unique_constraint(:code)
    end
  end

I hope my questions are clear.

Upvotes: 1

Views: 695

Answers (1)

Dogbert
Dogbert

Reputation: 222398

def changeset_all(model, [params]) do will only accept a list of 1 element. To accept any lists, you can do:

def changeset_all(model, params) when is_list(params) do

To create a list of changesets, just do for param <- params. The final code should look like:

def changeset_all(model, params) when is_list(params) do
  for param <- params do
    model
    |> cast(param, [:code, :en, :de, :it, :fr])
    |> validate_required([:code, :en])
    |> validate_length(:code, max: 3)
    |> unique_constraint(:code)
  end
end

Then how can I validate if the passed parameter contains maps or not?

You don't really need to do this as if you pass an invalid parameter, cast will handle throwing an error. If you want to do this, you can loop through the list and use if to check if it's a map:

for param <- params
  if !is_map(param) do
    raise "#{param} is not a map"
  end
end

for param <- params do
  # changeset stuff
end

I would recommend creating a changeset/2 function separately and then calling it using Enum.map in changeset_all/2:

def changeset(model, params) do
  model
  |> cast(params, [:code, :en, :de, :it, :fr])
  |> validate_required([:code, :en])
  |> validate_length(:code, max: 3)
  |> unique_constraint(:code)
end

def changeset_all(model, list) do
  list |> Enum.map(fn params -> changeset(model, params) end)
end

Upvotes: 2

Related Questions