How to derive a value inside an action, so the changeset is enriched?

Hello,

Say I have a cut down version of my create action.
I would like to populate an attribute (:geom) by using accepted values (:latitude, :longitude)


attributes do
    attribute :latitude, :float, allow_nil?: false
    attribute :longitude, :float, allow_nil?: false
    attribute :geom, :geometry, allow_nil?: false
end

actions do
    defaults [:read]

    create :create do
      accept [:latitude, :longitude]

      # I should be able to build a geometry 'point' field like so:
      # "POINT(#{:longitude} #{:latitude})"

      # but how to apply :geom to the changeset?

    end
end

Can someone please describe the “Ash” way of doing this?

I have a few use case like this, even triggering an oban job to go off and get data from an external to enrich related fields

Thanks.

In this case a change would do the trick

   create :create do
      accept [:latitude, :longitude]

      change fn changeset, _ ->
        Ash.Changeset.change_attribute(
          :geom, 
          POINT(
            #{Ash.Changeset.get_attribute(changeset, :longitude),
            #{Ash.Changeset.get_attribute(changeset, :latitude)
          )
        )
      end
    end

Thanks @barnabasJ !

You have put me on the right track. Turns out the creation of the geometry types was easier like so:

create :create do
      accept [:latitude, :longitude]

      change fn changeset, _ ->
        Ash.Changeset.change_attribute(
          changeset,
          :geom,
          %Geo.Point{
            coordinates:
              {Ash.Changeset.get_attribute(changeset, :latitude),
               Ash.Changeset.get_attribute(changeset, :longitude)},
            srid: 4326
          }
        )
      end
    end

Although I believe AshGeo has it’s own DSL for coercing the postgis type, I found it easier to use the underlying library in this case.

But now I know how to intercept a changeset!

Thanks again

2 Likes