I’m faced with a problem of needing to store information that I can’t control the values of. I have a “Question” model and I need a field that essentially is a map that can store any value.
In Rails I would typically just make a JSON column and throw anything in that column that I want. This is the behavior I desire for this problem but I’m having trouble implementing it.
I’m using “embeds_one” on my “Question” model for the “information” field. I’ve never used embeds_one before so I may be approaching this completely wrong. Here is my current code:
QUESTION.ex:
schema "questions" do
field(:active, :boolean)
field(:type, :string)
field(:description, :string)
embeds_one :information, MyApp.Information
timestamps()
end
@required_fields ~w(active type description)a
def changeset(struct, params \\ %{}) do
struct
|> cast(params, @required_fields)
|> cast_embed(:information)
|> validate_required(@required_fields)
end
INFORMATION.ex:
embedded_schema do
field :criteria
end
@required_fields ~w(criteria)a
def changeset(struct, params \\ %{}) do
struct
|> cast(params, @required_fields)
|> validate_required(@required_fields)
end
TEST:
valid_attrs %{
active: true,
description: "Player Points",
type: "NBA",
information: %{
criteria: %{
Player_name: "LeBron James"
}
}
}
test "changeset with valid attributes" do
changeset = Question.changeset(%Question{}, @valid_attrs)
assert changeset.valid?
end
ERROR:
information: #Ecto.Changeset<
action: :insert,
changes: %{},
errors: [criteria: {"is invalid", [type: :string, validation: :cast]}],
data: #MyApp.Information<>,
valid?: false
>
So, it seems that the that it is expecting a string not a map. But in this particular case I want criteria to essentially be able to hold anything I pass to it, much like a JSON field would behave.
MAIN QUESTION: How can I implement a JSON column that lets me put essentially anything in map for that attribute?