Operation Policies

Last updated 29 November 2016 trailblazer v1.1 v2.0


Trailblazer supports “pundit-style” policy classes. They can be hooked into operations and prevent the operation from running its #process method by raising an exception if the policy rule returned false.

Policy Classes

The format of a policy class is heavily inspired by the excellent Pundit gem. In fact, you can reuse your pundit policies without any code changes in Trailblazer.

A policy file per concept is recommendable.

class Thing::Policy
  def initialize(user, thing)
    @user, @thing = user, thing

  def create?

  def admin?
    @user.admin == true
  # ..

This class would probably be best located at app/concepts/thing/policy.rb.

Operation Policy

Use ::policy to hook the policy class along with a query action into your operation.

class Thing::Create < Trailblazer::Operation
  include Trailblazer::Operation::Policy

  policy Thing::Policy, :create?

The policy is evaluated in #setup!, raises an exception if false and thus suppresses running #process. It is a great way to protect your operations from unauthorized users.

Thing::Create.(current_user: User.find_normal_user, thing: {})

This will raise a Trailblazer::NotAuthorizedError.

Policy Creation

To instantiate the Thing::Policy object internally, per default the params[:current_user] and the operation’s model is passed into the constructor. You can override that via Operation#evaluate_policy.


After #setup!, the policy instance is available at any point in your operation code.

def process(params)
  notify_admin! if policy.admin?

This won’t raise an exception.


Pundit policy classes can be used directly in operations.

class Thing::Create < Trailblazer::Operation
  include Trailblazer::Operation::Policy

  policy ThingPolicy, :create?

As a matter of course, you may call other rule queries on the internal policy object later on.


Instead of using policies, you can also use a simple guard.

A guard is like an inline policy that doesn’t require you to define a policy class. It is run in #setup!, too, like a real policy, but isn’t accessible in the operation after that.

class Thing::Create < Trailblazer::Operation
  include Policy::Guard

  policy do |params|
    params[:current_user].present? # true when present.

If you prefer a separate class as your guard, you can provide a Callable object.

class Thing::Authorization
  include Uber::Callable # marks instance as callable.

  def call(operation, params)

Pass the guard instance to Operation::policy to register it.

class Thing::Create < Trailblazer::Operation
  include Policy::Guard
  policy Authorization.new

The same works with Proc, which will receive params only but is executed in operation context (subject to change).

Note that you can’t mix Policy and guards in one class.


You can use policies in your builders, too. Please refer to the builder docs to learn about that.