The docs for _normalize_callback_options make it clear that these controller hooks will behave unexpectedly when combining if / unless with only / except:
only: :index, if: -> { true } # the :if option will be ignored.
except: :index, if: -> { true } # the :except option will be ignored.
In practice, I don’t think many people will make it so far into the docs to understand this, until they encounter a bug with their code or inexplicable failing test. It’s also inconsistent:
# seems to work fine
# Will only run the action if certain_endpoint is hit and some_condition? is true
before_action :do_thing, only: [:certain_endpoint], if: :some_condition?
# does not work!
# Will NOT apply the only: [:certain_endpoint] filter
skip_before_action :standard_auth, only: [:certain_endpoint], if: :passes_special_auth?
If this is intended behavior, I think it’s bad design. The fact that only compiles into if is an implementation detail leaking into the interface. I imagine that the implementation could convert only into an if without replacing the if that the user specifies (e.g. it could combine both conditions).