Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add :http_verbs option #50

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ tmp
*.o
*.a
mkmf.log
.byebug_history
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ gem 'yard', '~> 0.9.24'
gem 'capybara', '~> 3.30.0'
gem 'rspec-rails', '~> 3.9.0'
gem 'public_suffix', '~> 2.0.5'
gem 'byebug'
hoppergee marked this conversation as resolved.
Show resolved Hide resolved

group :metrics do
gem 'coveralls', '0.8.23'
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ rails generate loaf:install
* [2.1.1 controller](#211-controller)
* [2.1.2 view](#212-view)
* [2.1.3 :match](#213-match)
* [2.1.4 :http_verbs](#214-http_verbs)
* [2.2 breadcrumb_trail](#22-breadcrumb_trail)
* [3. Configuration](#3-configuration)
* [4. Translation](#4-translation)
Expand Down Expand Up @@ -207,6 +208,29 @@ To make a breadcrumb current based on the query parameters do:
breadcrumb "Posts", posts_path(order: :desc), match: {order: :desc}
```

#### 2.1.4 :http_verbs

**Loaf** allows you to match on multiple HTTP verbs in order to make a breadcrumb current with the `:http_verbs` option.

The `:http_verbs` key accepts `:all` or an array with following values:

* `:get`
* `:post`
* `:put`
* `:patch`
* `:delete`
* `:head`
piotrmurach marked this conversation as resolved.
Show resolved Hide resolved

Its default value is `[:get]`
hoppergee marked this conversation as resolved.
Show resolved Hide resolved

For example:
hoppergee marked this conversation as resolved.
Show resolved Hide resolved

```ruby
http_verbs: %w[get head]
http_verbs: %w[post get head]
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
http_verbs: :all
```

### 2.2 breadcrumb_trail

In order to display breadcrumbs use the `breadcrumb_trail` view helper. It accepts optional argument of configuration options and can be used in two ways.
Expand Down
5 changes: 4 additions & 1 deletion lib/loaf/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ module Loaf
class Configuration
VALID_ATTRIBUTES = [
:locales_path,
:match
:match,
:http_verbs
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
].freeze

attr_accessor(*VALID_ATTRIBUTES)
Expand All @@ -13,6 +14,8 @@ class Configuration

DEFAULT_MATCH = :inclusive

DEFAULT_HTTP_VERBS = [:get]
hoppergee marked this conversation as resolved.
Show resolved Hide resolved

# Setup this configuration
#
# @api public
Expand Down
3 changes: 3 additions & 0 deletions lib/loaf/crumb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ class Crumb

attr_reader :match

attr_reader :http_verbs

def initialize(name, url, options = {})
@name = name || raise_name_error
@url = url || raise_url_error
@match = options.fetch(:match, Loaf.configuration.match)
@http_verbs = options.fetch(:http_verbs, Loaf.configuration.http_verbs)
freeze
end

Expand Down
10 changes: 7 additions & 3 deletions lib/loaf/view_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ def breadcrumb_trail(options = {})
_breadcrumbs.each do |crumb|
name = title_for(crumb.name)
path = url_for(_expand_url(crumb.url))
current = current_crumb?(path, options.fetch(:match) { crumb.match })
current = current_crumb?(
path,
options.fetch(:match) { crumb.match },
options.fetch(:http_verbs) { crumb.http_verbs }
)

yield(Loaf::Breadcrumb[name, path, current])
end
Expand All @@ -65,8 +69,8 @@ def breadcrumb_trail(options = {})
# the pattern to match on
#
# @api public
def current_crumb?(path, pattern = :inclusive)
return false unless request.get? || request.head?
def current_crumb?(path, pattern = :inclusive, http_verbs = [:get])
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
return false unless http_verbs == :all || http_verbs.any? {|verb| request.send("#{verb}?")}
hoppergee marked this conversation as resolved.
Show resolved Hide resolved

origin_path = URI::DEFAULT_PARSER.unescape(path).force_encoding(Encoding::BINARY)

Expand Down
48 changes: 48 additions & 0 deletions spec/integration/breadcrumb_trail_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,52 @@
)
end
end

it 'match to Non-GET methods' do
visit onboard_path

expect(page).to have_selector('h1', text: 'Onboard')
page.within '#breadcrumbs' do
expect(page).to have_content('Onboard')
end

click_link 'Step 1' # GET
expect(page).to have_selector('h1', text: 'Step 1')
page.within '#breadcrumbs' do
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
expect(page.html).to include('<a href="/onboard">Onboard</a>')
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
end
page.within '#breadcrumbs .selected' do
expect(page.html).to include('<a href="/onboard/step/1">Step 1</a>')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to previous comment please consider using capybara helper:

expect(page).to have_link("Step 1", href: "/onboard/step/1")

end

click_on 'Save & Next' # POST
expect(page).to have_selector('h1', text: 'Step 2')
page.within '#breadcrumbs .selected' do
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
expect(page.html).to include('<a href="/onboard/step/2">Step 2</a>')
end

click_on 'Save & Next' # PUT
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
expect(page).to have_selector('h1', text: 'Step 3')
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
page.within '#breadcrumbs .selected' do
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
expect(page.html).to include('<a href="/onboard/step/3">Step 3</a>')
end

click_on 'Save & Next' # PATCH
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
expect(page).to have_selector('h1', text: 'Step 4')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.

page.within '#breadcrumbs .selected' do

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.

expect(page.html).to include('<a href="/onboard/step/4">Step 4</a>')
end

click_on 'Save & Next' # DELETE

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.

expect(page).to have_selector('h1', text: 'Step 5')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.

page.within '#breadcrumbs .selected' do

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.

expect(page.html).to include('<a href="/onboard/step/5">Step 5</a>')
end

click_on 'Save & Next' # GET

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.

expect(page).to have_selector('h1', text: 'Step 6')
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
page.within '#breadcrumbs .selected' do
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
expect(page.html).to include('<a href="/onboard/step/6">Step 6</a>')
end
end
end
29 changes: 29 additions & 0 deletions spec/rails_app/app/controllers/onboard_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class OnboardController < ApplicationController
hoppergee marked this conversation as resolved.
Show resolved Hide resolved

hoppergee marked this conversation as resolved.
Show resolved Hide resolved
breadcrumb 'Onboard', :onboard_path, match: :exact

def setup
case params[:step]
when '1'
breadcrumb 'Step 1', onboard_step_path(step: 1), match: :exact, http_verbs: [:get]
render 'step1'
when '2'
breadcrumb 'Step 2', onboard_step_path(step: 2), match: :exact, http_verbs: [:get, :post]
render 'step2'
when '3'
breadcrumb 'Step 3', onboard_step_path(step: 3), match: :exact, http_verbs: [:get, :put]
render 'step3'
when '4'
breadcrumb 'Step 4', onboard_step_path(step: 4), match: :exact, http_verbs: [:get, :patch]
render 'step4'
when '5'
breadcrumb 'Step 5', onboard_step_path(step: 5), match: :exact, http_verbs: [:get, :delete]
render 'step5'
when '6'
breadcrumb 'Step 6', onboard_step_path(step: 6), match: :exact, http_verbs: :all
render 'step6'
else
render 'setup'
end
end
end
piotrmurach marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 3 additions & 0 deletions spec/rails_app/app/views/onboard/setup.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h1>Onboard</h1>

<%= link_to 'Step 1', onboard_step_path(step: 1) %>
2 changes: 2 additions & 0 deletions spec/rails_app/app/views/onboard/step1.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h1>Step 1</h1>
<%= button_to 'Save & Next', onboard_step_path(step: 2), method: :post %>
2 changes: 2 additions & 0 deletions spec/rails_app/app/views/onboard/step2.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h1>Step 2</h1>
<%= button_to 'Save & Next', onboard_step_path(step: 3), method: :put %>
2 changes: 2 additions & 0 deletions spec/rails_app/app/views/onboard/step3.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h1>Step 3</h1>
<%= button_to 'Save & Next', onboard_step_path(step: 4), method: :patch %>
2 changes: 2 additions & 0 deletions spec/rails_app/app/views/onboard/step4.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h1>Step 4</h1>
<%= button_to 'Save & Next', onboard_step_path(step: 5), method: :delete %>
2 changes: 2 additions & 0 deletions spec/rails_app/app/views/onboard/step5.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h1>Step 5</h1>
<%= button_to 'Save & Next', onboard_step_path(step: 6), method: :get %>
1 change: 1 addition & 0 deletions spec/rails_app/app/views/onboard/step6.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1>Step 6</h1>
7 changes: 7 additions & 0 deletions spec/rails_app/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,11 @@
resources :posts do
resources :comments
end

get '/onboard', to: 'onboard#setup', as: :onboard
get '/onboard/step/:step', to: 'onboard#setup', as: :onboard_step
post '/onboard/step/:step', to: 'onboard#setup'
patch '/onboard/step/:step', to: 'onboard#setup'
put '/onboard/step/:step', to: 'onboard#setup'
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
delete '/onboard/step/:step', to: 'onboard#setup'
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
end
1 change: 1 addition & 0 deletions spec/support/capybara.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

RSpec.configure do |c|
c.include Capybara::DSL, :file_path => /\bspec\/integration\//
c.filter_run_when_matching :focus => true
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
end
Capybara.default_driver = :rack_test
Capybara.default_selector = :css
28 changes: 26 additions & 2 deletions spec/support/dummy_view.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,29 @@
class DummyView < ActionView::Base
module FakeRequest
class Request
attr_accessor :path, :fullpath, :protocol, :host_with_port
attr_accessor :path, :fullpath, :protocol, :host_with_port, :_request_method
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
def get?
true
_request_method == nil ? true : _request_method == 'GET'
end

def post?
_request_method == nil ? false : _request_method == 'POST'
end

def put?
_request_method == nil ? false : _request_method == 'PUT'
end

def patch?
_request_method == nil ? false : _request_method == 'PATCH'
end

def delete?
_request_method == nil ? false : _request_method == 'DELETE'
end

def head?
_request_method == nil ? false : _request_method == 'HEAD'
end
end
def request
Expand Down Expand Up @@ -51,4 +71,8 @@ def set_path(path)
request.protocol = "http://"
request.host_with_port = "www.example.com"
end

def set_request_method(method)
request._request_method = method.upcase.to_s
end
end
3 changes: 2 additions & 1 deletion spec/unit/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
config = Loaf::Configuration.new
expect(config.to_hash).to eq({
locales_path: "/",
match: :inclusive
match: :inclusive,
http_verbs: [:get]
})
end

Expand Down
27 changes: 27 additions & 0 deletions spec/unit/view_extensions/breadcrumb_trail_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -280,4 +280,31 @@
expect(view.breadcrumb_trail.map(&:url)).to eq(%w[/ /posts /posts/1])
expect(view.breadcrumb_trail(match: :exact).map(&:current?)).to eq([false, false, true])
end

it "match current path with :http_verbs" do
view = DummyView.new
view.breadcrumb("posts", "/posts", http_verbs: [:get, :post])
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
view.set_path("/posts")
view.set_request_method(:post)

expect(view.breadcrumb_trail.map(&:to_a)).to eq([["posts", "/posts", true]])
end

it "fail to match current path with :http_verbs" do
view = DummyView.new
view.breadcrumb("posts", "/posts")
view.set_path("/posts")
view.set_request_method(:post)

expect(view.breadcrumb_trail.map(&:to_a)).to eq([["posts", "/posts", false]])
hoppergee marked this conversation as resolved.
Show resolved Hide resolved
end

it "match current path with :http_verbs => :all" do
view = DummyView.new
view.breadcrumb("posts", "/posts", http_verbs: :all)
view.set_path("/posts")
view.set_request_method(:delete)

expect(view.breadcrumb_trail.map(&:to_a)).to eq([["posts", "/posts", true]])
end
end