3
votes

I have schemas Bank and Currency with many to many association. I created a form for Bank with select that contains currencies.

bank.ex

schema "banks" do
  field :name, :string
  many_to_many :currencies, App.Currency, join_through: "banks_currencies"
end

@required_fields ~w(name)
@optional_fields ~w()

def changeset(model, params \\ %{}) do
  model
  |> cast(params, @required_fields, @optional_fields)
  |> cast_assoc(:currencies)
end

form.html.ex

<%= multiple_select(form, :currencies, @currencies) %>

Problem is: when I submit form with some currencies selected, then changeset returns "is invalid" error. I simulated that in iex:

iex(8)> App.Bank.changeset bank, %{"currencies" => ["1"]}  
#Ecto.Changeset<action: nil, changes: %{},
 errors: [currencies: {"is invalid", [type: {:array, :map}]}],
 data: #App.Bank<>, valid?: false>

I have the newest Phoenix installed, recently upgraded from 1.1.4 to 1.2

1

1 Answers

2
votes

I'm not sure is it correct solution, but it works

bank.ex

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

  currencies = Currency
  |> Currency.by_ids(if params["currencies"], do: params["currencies"], else: [])
  |> App.Repo.all
  |> Enum.map(&Ecto.Changeset.change/1)

  model
  |> cast(params, @required_fields, @optional_fields)
  |> put_assoc(:currencies, currencies)
end

currency.ex

def by_ids(query, ids) do
  from c in query, where: c.id in ^ids
end