module Rewrite
This module can match and rewrite requests before they processed. This allows you to handle URLs like /post/15/view
or /blog/123-pictures-of-my-cat
easily. The basic rewrite operation is to extract some part of the path and optionally executes a block. That means that the path is modified before being passed on to the next layer in the controller, and controller instance variables may be set.
Regular Expressions
In your controller.rb
:
prepend Rewrite, Actions
rewrite.extract_prefix permalink: /(?<id>\d+)-(?<title>.*)/ do |request, path, match|
# The rewrite matched, but there was no valid post, so we fail:
fail! unless @post = Post.find(@permalink[:id])
# If the path matched, but there was no suffix, we make it default to the post action:
if match.post_match.empty?
match.post_match.components << "post"
end
end
on 'post' do
# You can do further processing here.
fail! unless @post.published?
@comments = @post.comments.first(5)
end
on 'edit' do
# You can do further processing here.
fail! unless @current_user&.editor?
end
In your post.xnode
, as an example:
<content:page>
<content:heading>Post #{attributes[:permalink][:id]} about #{attributes[:permalink][:title]}</content:heading>
<p>#{attributes[:post].content}</p>
</content:page>
Keep in mind, that URLs like /123-pictures-of-my-cat/edit
will work as expected, and hit the edit
action of the controller.
Restful Resources
Similar to the above, if we were solely interested in IDs, we could do the following:
prepend Rewrite, Actions
rewrite.extract_prefix post_id: Integer do |request, path, match|
# The rewrite matched, but there was no valid post, so we fail:
fail! unless @post = Post.find(@post_id)
# If the path matched, but there was no suffix, we make it default to the post action:
if match.post_match.empty?
match.post_match.components << "post"
end
end
This will only match complete integers. Assuming this code is in /blog/controller.rb
, it would match something like /blog/123/view
and assign Integer("123")
to @post_id
.
Matching.. other things
It's possible to match using Integer
, Float
, String
, and you can provide your own class which will be instantiated. If it doesn't match, raise an exception and the rewrite rule will fail.
Nested
Definitions
def process!(request, path)
Rewrite the path before processing the request if possible.
Implementation
def process!(request, path)
catch_response do
self.class.rewrite_request(self, request, path)
end || super
end