Skip to content

Instantly share code, notes, and snippets.

@itay-grudev
Last active October 17, 2018 18:24
Show Gist options
  • Save itay-grudev/bdbdbb8d1b9e92daaf50 to your computer and use it in GitHub Desktop.
Save itay-grudev/bdbdbb8d1b9e92daaf50 to your computer and use it in GitHub Desktop.
Rails Current Page Helper
module PathHelper
##
# Checks whether you are on the specified page
#
# @param matchers A comma separated list of matchers.
# @param returnval Return value if the page matches or nil. Defaults to true.
# @return [mixed] returnval (usually truthy) on success or nil on failure.
#
# @example Check if you are on Article#show
# page?( 'article#show' )
# @example Check if on Article#show or News#index
# page?( 'article#show, news#index' )
# @example Check if you are in the article controller under the admin scope
# page?( 'admin/articles#index' )
# @example Check if you are in the article controller and return `'active'`
# page?( 'article', 'active' )
# @example Check aditional parameters and return `'active'` (for use as class)
# page?( "article#show?slug=#{@article.slug}", 'active' )
#
# ==== Matchers
# Matchers are a comma separated list of rules specified with the following
# format. Whitespace between matchers is allowed.
# controller#action?param1=value&param2=value
# Values should be URL encoded if they contain special characters.
#
#
# ==== LICENSE
# Copyright (c) 2015-2017 Itay Grudev <itay[]grudev.com>
# Published under the terms of The MIT License (MIT)
#
def page?( matchers, returnval = true )
matchers.split( ',' ).each do |matcher|
# Split the routing part and the parameters part
routing, params = matcher.strip.split( '?' )
# Split the controller from the action
controller, action = routing.strip.split( '#' ) unless routing.blank?
# Split multiple parameters
params = params.strip.split( '&' ) unless params.blank?
next if ! controller.blank? and request.params[:controller] != controller
next if ! action.blank? and request.params[:action] != action
# Verify parameters
matches = true
params.try( :each ) do |param|
# Split parameter key from value
key, value = param.strip.split( '=' )
if request.params[key] != URI.unescape( value )
matches = false and break
end
end
next unless matches
return returnval
end
nil
end
end
/ Checking if you are on a given page
- if page?( 'article#show' )
/ ...
- if page?( 'article#show, news#index' )
/ ...
/ Marking links as active
ul
li class=[ page?( 'blog', 'active' ) ]
= link_to 'Blog', blog_path
/ Usage with namespaces
ul
li class=[ page?( 'admin/articles#index', 'active' ) ]
= link_to 'Pages', admin_pages_path
/ Checking additional parameters
/ Assuming you have a path like: get '/article/:slug' => 'article#show'
ul
- @pages.each do |page|
li class=[ page?( "article#show?slug=#{@article.slug}", 'active' ) ]
= link_to @page.title, page_path( @page.slug )
require 'rails_helper'
RSpec.describe PathHelper, type: :helper do
describe 'page?' do
before {
@request = double( 'request' )
allow( helper ).to receive( :request ).and_return( @request )
}
# This adds additional test with two matchers where the first is invalid
[ '', 'INVALID#INVALID?invalid=invalid&invalid=invalid,' ].each do |prefix|
context "with#{'out' if prefix.blank?} prefix" do
context 'on matching page' do
before {
allow( @request ).to receive( :params ).and_return(
controller: ( @controller = SecureRandom.hex ),
action: ( @action = SecureRandom.hex )
)
}
it 'matches just a controller' do
expect(
helper.page?( prefix + "#{@controller}" )
).to eq true
end
it 'matches just an action' do
expect(
helper.page?( prefix + "##{@action}" )
).to eq true
end
it 'matches just a controller and an action' do
expect(
helper.page?( prefix + "#{@controller}##{@action}" )
).to eq true
end
end
context 'on controller mismatch' do
before {
allow( @request ).to receive( :params ).and_return(
controller: '!' + ( @controller = SecureRandom.hex ),
action: ( @action = SecureRandom.hex )
)
}
it 'matches just a controller' do
expect(
helper.page?( prefix + "#{@controller}" )
).to be_nil
end
it 'matches just an action' do
expect(
helper.page?( prefix + "##{@action}" )
).to eq true
end
it 'matches just a controller and an action' do
expect(
helper.page?( prefix + "#{@controller}##{@action}" )
).to be_nil
end
end
context 'on action mismatch' do
before {
allow( @request ).to receive( :params ).and_return(
controller: ( @controller = SecureRandom.hex ),
action: '!' + ( @action = SecureRandom.hex )
)
}
it 'matches just a controller' do
expect(
helper.page?( prefix + "#{@controller}" )
).to eq true
end
it 'matches just an action' do
expect(
helper.page?( prefix + "##{@action}" )
).to be_nil
end
it 'matches just a controller and an action' do
expect(
helper.page?( prefix + "#{@controller}##{@action}" )
).to be_nil
end
end
context 'with additional params specified' do
it 'should return true on matching page' do
allow( @request ).to receive( :params ).and_return(
controller: ( @controller = SecureRandom.hex ),
action: ( @action = SecureRandom.hex ),
( param1 = SecureRandom.hex ) => ( value1 = SecureRandom.hex ),
( param2 = SecureRandom.hex ) => ( value2 = SecureRandom.hex )
)
expect(
helper.page?(
"#{@controller}##{@action}?#{param1}=#{value1}&#{param2}=#{value2}"
)
).to eq true
end
it 'should return nil if the page doesn\'t match' do
allow( @request ).to receive( :params ).and_return(
controller: ( @controller = SecureRandom.hex ),
action: ( @action = SecureRandom.hex ),
( param1 = SecureRandom.hex ) => ( value1 = SecureRandom.hex ),
( param2 = SecureRandom.hex ) => ( value2 = SecureRandom.hex )
)
expect(
helper.page?(
"#{@controller}##{@action}?#{param1}=#{value1}&#{param2}=!#{value2}"
)
).to be_nil
end
end
context 'with return value specified' do
it 'should return the specified value on matching page' do
allow( @request ).to receive( :params ).and_return(
controller: ( @controller = SecureRandom.hex ),
action: ( @action = SecureRandom.hex )
)
expect(
helper.page?(
"#{@controller}##{@action}",
( val = SecureRandom.hex )
)
).to eq val
end
it 'should return nil if the page doesn\'t match' do
allow( @request ).to receive( :params ).and_return(
controller: ( '!' + @controller = SecureRandom.hex ),
action: ( '!' + @action = SecureRandom.hex )
)
expect(
helper.page?(
"#{@controller}##{@action}",
( val = SecureRandom.hex )
)
).to be_nil
end
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment