Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically get a Rails Routes constraint?

I'm trying to collect all the Rails routes, and dump their named_route, path and constraint (if there is one).

I'm able to get the named_route, path, but I'm trying to find a way to get the routes constraint.

routes = Rails.application.routes.routes.map do |route|
 path = route.path.spec.to_s.gsub!("(.:format)", '')

 # route.constraints always output {} ??
 puts route.constraints

 name = route.name
 [name, path]
end.to_h

Here is an example of a route..

USER_NAME_PATTERN ||= /@[a-z0-9][-a-z0-9]+/
get ":username/:slug", to: 'calcs#show', as: :user_calc , constraints: {username: USER_NAME_PATTERN }

How to programmatically get a Rails Routes constraint?

like image 784
GN. Avatar asked Oct 15 '25 15:10

GN.


1 Answers

Constraints are a bit complicated, because there are multiple kinds of route constraint, which are specified the same way in routes.rb, but get handled internally somewhat differently.

The kind of constraint in your question is a segment constraint, which imposes a format on one or more segments of the path. Segment constraints are stored in the requirements hash at the path level, using keys that correspond to the segment names (segment names are stored in the parts attribute on the Route).

> route = Rails.application.routes.named_routes.get(:user_calc)
=> #<ActionDispatch::Journey::Route:0x00007f6aa05b2cc0>
> route.parts
=> [:username, :slug, :format]
> route.path.requirements
=> {:username=>/@[a-z0-9][-a-z0-9]+/}

There are also request constraints, which constrains a route based on any method on the Request object that returns a string. These get specified similarly to segment constraints:

get ":username/:slug", to: 'calcs#show', as: :user_calc , constraints: {subdomain: 'admin'}

Request constraints are stored in the constraints attribute on the Route object.

> route = Rails.application.routes.named_routes.get(:user_calc)
=> #<ActionDispatch::Journey::Route:0x00007f6aa05b2cc0>
> route.constraints
=> {:subdomain=>"admin"}

You can also specify constraints using a lambda or class that responds to .matches?. These advanced constraints seem to be handled by a different mechanism, but I haven't dug around enough in the code to understand exactly how.

like image 59
rmlockerd Avatar answered Oct 17 '25 03:10

rmlockerd



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!