DEV Community

Nick Sutterer for Trailblazer

Posted on

Fetching models using the new Model::Find() macro

Trailblazer comes with predefined steps we call "macros" that help you with common tasks such as validating a form object or finding an existing model using ActiveRecord (actually, any other ORM you approve of).

The newly released Model::Find() macro is a replacement for Model() that, over the years, turned out to be helpful but a bit hard to customize, as it wouldn't really allow you to change how things are performed in the background.

class Update < Trailblazer::Activity::Railway
  step Model::Find(Song, find_by: :id, params_key: :slug)
Enter fullscreen mode Exit fullscreen mode

You are going to need trailblazer-macro 2.1.16 for this goodie.

Extracting the ID

The new macro provides options such as :params_key and :column_key to configure how the ID is extracted. If you want to do it yourself, simply use a block.

step Model::Find(Song, find_by: :id) { |ctx, params:, **|
  params[:song] && params[:song][:id]
}
Enter fullscreen mode Exit fullscreen mode

A bunch of discussions with long-term users lead us to the decision that overriding ID extraction should be straight-forward since this is more than just an edge case.

Customizing the query

Once the ID is extracted, it's now very simple to customize how the query is performed (e.g. find_by: id vs find(id)). Nevertheless, the new key feature is the :query option that allows you to write that code manually.

step Model::Find(
  Song,
  query: ->(ctx, id:, current_user:, **) { where(id: id, user: current_user) }
)
Enter fullscreen mode Exit fullscreen mode

Note how the query logic can access ctx and keyword arguments, just like a real step. The extracted ID is available in the variable :id.

Not_found terminus

If one of the two steps weren't successful, you can instantly go to a new terminus not_found in your business operation, indicating to the outer world that this particular step failed. With the release of trailblazer-endpoint this will become interesting as the endpoint code could, for instance, automatically render a 404 page for you.

Discussion

The code of this macro is nothing special. In fact, it simply creates a tiny nested activity behind the scenes with two steps, one to extract the ID, and one to actually fetch the model.

Anyhow, we strongly recommend sticking with this macro instead of writing your own, for three reasons.

  1. Well, code we write and maintain is less work for you. Keep in mind that we also provide documentation.
  2. Features like the not_found terminus we added with forward-compatibility in mind: they will save you code once endpoints are becoming a thing.
  3. Debugging Model::Find() is a matter of using our internal tracing. In the trace, you can see which part failed.

Image description

Please give us some feedback about what's missing or what you like about this simple addition to our stack. Have fun!

Top comments (0)