Ash action needs calculation to be loaded, how?

Hi,

I have an action called ‘start’:

    update :start do
      change transition_state(:active)
      require_atomic? false

      validate attribute_equals(:enough_parties_defined?, true)

      validate attribute_equals(:has_parties_with_no_members?, false)

      validate Validations.HasDocuments,
        before_action?: true

      change Changes.SendInvitesToAllParticipants
    end

It has some validations that are based on calculations :enough_parties_defined? and :has_parties_with_no_members?.

Currently I do:

project = Ash.load!(project, [:has_parties_with_no_members?, :enough_parties_defined?])
Project.start(project)

I would like to avoid the load! step, as it is leaking implementation details to the call-site.
Can I make my action ensure these are loaded and lazy load them if needed?

You can add a change before your validations that loads the data.

I think something like this should work

    update :start do
      require_atomic? false
      change fn %{data: data} = changeset, _ ->
       data = Ash.load!(
         data, 
         [:has_parties_with_no_members?, :enough_parties_defined?],
         # you probably want to add this because the change can be run
         # multiple time, but you need to make sure you don't pass a resource
         # with stale values, otherwise it might be better to do all the validations
         # and the loading as before_actions
         lazy?: true
        )
       
        %{changeset | data: data}
      end

      change transition_state(:active)

      validate attribute_equals(:enough_parties_defined?, true)

      validate attribute_equals(:has_parties_with_no_members?, false)

      validate Validations.HasDocuments,
        before_action?: true

      change Changes.SendInvitesToAllParticipants
    end

changes and validations are run in the order they are specified in the dsl

1 Like