venomnert

venomnert

Ecto.update is not updating jsonb

The problem

I have a :map field that I am able to update on create. On update, the changeset returns a successful update;however, the database jsonb is not reflecting the changes. I’m unable to determine what the issue is.

Schema:

 schema "promo_jobs" do
    field(:content, :map, default: %{})
    field(:draft, :boolean, default: true)
    field(:end_date, :utc_datetime)
    field(:name, :string)
    field(:rolled_out, :boolean, default: false)
    field(:start_date, :utc_datetime)
    field(:take_down, :boolean, default: false)

    has_one(:landing_page_url, LandingPageUrl, on_replace: :nilify, on_delete: :nilify_all)
    belongs_to(:region, Region)
  end

  def changeset(promo_job, attrs) do
    promo_job
    |> add_content(attrs)
    |> cast(attrs, [:name, :rolled_out, :take_down, :start_date, :end_date, :content, :draft])
    |> validate_required([
      :name,
      :rolled_out,
      :take_down,
      :start_date,
      :end_date,
      :content,
      :draft
    ])
  end

  defp add_content(promo_job, attrs) do
    promo_job
    |> Map.put(:content,
      Morphix.atomorphiform!(promo_job.content)
      |> Content.new()
      |> Content.update_input_value(attrs))
  end

Controller:

  def show(conn, %{"id" => id}) do
    promo_job = Promos.get_promo_job!(id) |> IO.inspect(label: "SHOW")
    render(conn, "show.html", promo_job: promo_job)
  end

def update(conn, %{"id" => id, "promo_job" => promo_job_params}) do
    promo_job = Promos.get_promo_job!(id)

    case Promos.update_promo_job(promo_job, promo_job_params) do
      {:ok, promo_job} ->

        IO.inspect(promo_job, label: "UODATED")

        conn
        |> put_flash(:info, "Promo job updated successfully.")
        |> redirect(to: Routes.promo_job_path(conn, :show, promo_job))

      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, "edit.html", promo_job: promo_job, changeset: changeset)
    end
  end

Context:

  def create_promo_job(attrs \\ %{}) do
    promo_job = %PromoJob{} |> PromoJob.changeset(attrs)

      promo_job
      |> Repo.insert()
  end

  def update_promo_job(%PromoJob{} = promo_job, attrs) do
    promo_job
    |> PromoJob.changeset(attrs)
    |> Repo.update()
  end

Inspect Logs:

 UODATED: %PromoRollout.Promos.PromoJob{
  __meta__: #Ecto.Schema.Metadata<:loaded, "promo_jobs">,
  content: %{
    body_promo: %{
      fields: [
        %{
          content: "abab",
          field_type: "text_input",
          name: "bg_mobile",
          placeholder: "Image url"
        },
        %{
          content: "2312312",
          field_type: "text_input",
          name: "bg_desktop",
          placeholder: "Image url"
        }
      ],
      full_html: "",
      status: false
    },
    promo_bar: %{
      fields: [
        %{
          content: "zcxzc",
          field_type: "text_input",
          name: "image_url",
          placeholder: "Image url"
        }
      ],
      full_html: "",
      status: false
    }
  },
  draft: false,
  end_date: ~U[2020-01-01 00:00:00Z],
  id: 25,
  inserted_at: ~N[2020-01-30 23:06:54],
  landing_page_url: %PromoRollout.Promos.LandingPageUrl{
    __meta__: #Ecto.Schema.Metadata<:loaded, "landing_page_urls">,
    draft: true,
    end_date: ~U[2020-01-01 00:00:00Z],
    id: 1,
    inserted_at: ~N[2020-01-25 12:20:57],
    promo_job: #Ecto.Association.NotLoaded<association :promo_job is not loaded>,
    promo_job_id: 25,
    redirected: false,
    updated_at: ~N[2020-01-30 23:30:03],
    url: "/lp/easter"
  },
  name: "testing 123",
  region: nil,
  region_id: nil,
  rolled_out: false,
  start_date: ~U[2020-01-01 00:00:00Z],
  take_down: false,
  updated_at: ~N[2020-01-30 23:30:03]
}
SHOW: %PromoRollout.Promos.PromoJob{
  __meta__: #Ecto.Schema.Metadata<:loaded, "promo_jobs">,
  content: %{
    "body_promo" => %{
      "fields" => [
        %{
          "content" => "21312321321",
          "field_type" => "text_input",
          "name" => "bg_mobile",
          "placeholder" => "Image url"
        },
        %{
          "content" => "dsfasfasfsfss",
          "field_type" => "text_input",
          "name" => "bg_desktop",
          "placeholder" => "Image url"
        }
      ],
      "full_html" => "",
      "status" => false
    },
    "promo_bar" => %{
      "fields" => [
        %{
          "content" => "xzzzxZxxzx",
          "field_type" => "text_input",
          "name" => "image_url",
          "placeholder" => "Image url"
        }
      ],
      "full_html" => "",
      "status" => false
    }
  },
  draft: false,
  end_date: ~U[2020-01-01 00:00:00Z],
  id: 25,
  inserted_at: ~N[2020-01-30 23:06:54],
  landing_page_url: %PromoRollout.Promos.LandingPageUrl{
    __meta__: #Ecto.Schema.Metadata<:loaded, "landing_page_urls">,
    draft: true,
    end_date: ~U[2020-01-01 00:00:00Z],
    id: 1,
    inserted_at: ~N[2020-01-25 12:20:57],
    promo_job: #Ecto.Association.NotLoaded<association :promo_job is not loaded>,
    promo_job_id: 25,
    redirected: false,
    updated_at: ~N[2020-01-30 23:30:03],
    url: "/lp/easter"
  },
  name: "testing 123",
  region: #Ecto.Association.NotLoaded<association :region is not loaded>,
  region_id: nil,
  rolled_out: false,
  start_date: ~U[2020-01-01 00:00:00Z],
  take_down: false,
  updated_at: ~N[2020-01-30 23:30:03]
}

You will notices that the update log is correct, it reflects all the changes I’ve made. Once we are directed to the show route, the data that’s retrieved from the db has some inconsistency. The name gets updated correctly, but the content the :map field doesn’t get updated, it shows the old value. Which is the main problem I am having.

Marked As Solved

venomnert

venomnert

I was able to resolve the issue, thanks to Ecto’s documentation

A changeset is required as it is the only mechanism for tracking dirty changes. Only the fields present in the changes part of the changeset are sent to the database. Any other, in-memory changes done to the schema are ignored.

Link

Looks like I wasn’t setting the change field for the changeset. So here is the update PromoJob.changeset

 defp add_content(promo_job, attrs) do
    promo_job
    |>put_change(:content,
      Morphix.atomorphiform!(promo_job.data.content)
      |> Content.new()
      |> Content.update_input_value(attrs))

  end

Where Next?

Popular in Questions Top

New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
JulienCorb
I am trying to implement my new.html.eex file to create new posts on my website. new.html.eex: &lt;h1&gt;Create Post&lt;/h1&gt; &lt;%= ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
marick
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I’m a nov...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31142 143
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New

We're in Beta

About us Mission Statement