loaf 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -3
- data/.rspec +1 -0
- data/.travis.yml +30 -12
- data/Appraisals +27 -9
- data/CHANGELOG.md +59 -11
- data/Gemfile +11 -11
- data/Gemfile.lock +182 -0
- data/README.md +120 -56
- data/assets/loaf_logo.png +0 -0
- data/bin/appraisal +16 -0
- data/bin/rake +16 -0
- data/gemfiles/rails3.2.gemfile +15 -13
- data/gemfiles/rails4.0.gemfile +13 -12
- data/gemfiles/rails4.1.gemfile +14 -13
- data/gemfiles/rails4.2.gemfile +14 -13
- data/gemfiles/rails5.0.gemfile +22 -0
- data/gemfiles/rails5.1.gemfile +22 -0
- data/lib/loaf.rb +2 -22
- data/lib/loaf/breadcrumb.rb +30 -0
- data/lib/loaf/configuration.rb +7 -8
- data/lib/loaf/controller_extensions.rb +13 -28
- data/lib/loaf/crumb.rb +5 -4
- data/lib/loaf/crumb_formatter.rb +3 -1
- data/lib/loaf/errors.rb +1 -3
- data/lib/loaf/options_validator.rb +2 -2
- data/lib/loaf/railtie.rb +19 -13
- data/lib/loaf/translation.rb +1 -1
- data/lib/loaf/version.rb +1 -3
- data/lib/loaf/view_extensions.rb +69 -18
- data/loaf.gemspec +20 -13
- data/spec/integration/{crumbs_routing_spec.rb → breadcrumb_trail_spec.rb} +19 -12
- data/spec/rails_app/app/controllers/application_controller.rb +2 -0
- data/spec/rails_app/app/controllers/posts_controller.rb +1 -4
- data/spec/rails_app/app/views/layouts/_breadcrumbs.html.erb +7 -5
- data/spec/rails_app/app/views/layouts/application.html.erb +0 -2
- data/spec/rails_app/config/environments/test.rb +1 -1
- data/spec/rails_app/config/secrets.yml +22 -0
- data/spec/spec_helper.rb +3 -3
- data/spec/support/dummy_controller.rb +9 -0
- data/spec/support/dummy_view.rb +42 -2
- data/spec/unit/configuration_spec.rb +35 -0
- data/spec/unit/controller_extensions_spec.rb +5 -14
- data/spec/unit/generators/install_generator_spec.rb +2 -1
- data/spec/unit/view_extensions/breadcrumb_trail_spec.rb +232 -0
- metadata +65 -31
- data/.ruby-version +0 -1
- data/init.rb +0 -3
- data/lib/loaf/builder.rb +0 -38
- data/spec/rails_app/.gitignore +0 -5
- data/spec/rails_app/lib/assets/.gitkeep +0 -0
- data/spec/rails_app/lib/tasks/.gitkeep +0 -0
- data/spec/rails_app/script/rails +0 -6
- data/spec/unit/view_extensions/breadcrumbs_spec.rb +0 -128
@@ -0,0 +1,22 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "ammeter", "~> 1.1.4"
|
6
|
+
gem "appraisal", "~> 2.2.0"
|
7
|
+
gem "yard", "~> 0.9.9"
|
8
|
+
gem "capybara", "~> 2.15.4"
|
9
|
+
gem "rspec-rails", "~> 3.6.1"
|
10
|
+
gem "nokogiri", "~> 1.6.8"
|
11
|
+
gem "public_suffix", "~> 2.0.5"
|
12
|
+
gem "sqlite3", "~> 1.3.13", platforms: :ruby
|
13
|
+
gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.23", platforms: :jruby
|
14
|
+
gem "rails", "~> 5.0.6"
|
15
|
+
|
16
|
+
group :metrics do
|
17
|
+
gem "coveralls", "0.8.17"
|
18
|
+
gem "simplecov", "~> 0.12.0"
|
19
|
+
gem "yardstick", "~> 0.9.9"
|
20
|
+
end
|
21
|
+
|
22
|
+
gemspec path: "../"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "ammeter", "~> 1.1.4"
|
6
|
+
gem "appraisal", "~> 2.2.0"
|
7
|
+
gem "yard", "~> 0.9.9"
|
8
|
+
gem "capybara", "~> 2.15.4"
|
9
|
+
gem "rspec-rails", "~> 3.6.1"
|
10
|
+
gem "nokogiri", "~> 1.6.8"
|
11
|
+
gem "public_suffix", "~> 2.0.5"
|
12
|
+
gem "sqlite3", "~> 1.3.13", platforms: :ruby
|
13
|
+
gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.23", platforms: :jruby
|
14
|
+
gem "rails", "~> 5.1.4"
|
15
|
+
|
16
|
+
group :metrics do
|
17
|
+
gem "coveralls", "0.8.17"
|
18
|
+
gem "simplecov", "~> 0.12.0"
|
19
|
+
gem "yardstick", "~> 0.9.9"
|
20
|
+
end
|
21
|
+
|
22
|
+
gemspec path: "../"
|
data/lib/loaf.rb
CHANGED
@@ -1,15 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'loaf/configuration'
|
4
|
-
require 'loaf/errors'
|
5
|
-
require 'loaf/railtie'
|
6
|
-
require 'loaf/crumb'
|
7
|
-
require 'loaf/builder'
|
8
|
-
require 'loaf/translation'
|
9
|
-
require 'loaf/controller_extensions'
|
10
|
-
require 'loaf/view_extensions'
|
11
|
-
require 'loaf/crumb_formatter'
|
12
|
-
require 'loaf/options_validator'
|
1
|
+
require_relative 'loaf/configuration'
|
2
|
+
require_relative 'loaf/railtie'
|
13
3
|
|
14
4
|
module Loaf
|
15
5
|
# Set global configuration
|
@@ -34,14 +24,4 @@ module Loaf
|
|
34
24
|
def self.configure
|
35
25
|
yield configuration
|
36
26
|
end
|
37
|
-
|
38
|
-
if defined? Rails::Railtie
|
39
|
-
require 'loaf/railtie'
|
40
|
-
else
|
41
|
-
autoload :ControllerExtensions, 'loaf/controller_extensions'
|
42
|
-
autoload :Helpers, 'loaf/view_extensions'
|
43
|
-
|
44
|
-
::ActionController::Base.send :include, Loaf::ControllerExtensions
|
45
|
-
::ActionController::Base.helper Loaf::ViewExtensions
|
46
|
-
end
|
47
27
|
end # Loaf
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Loaf
|
2
|
+
# A container for breadcrumb values
|
3
|
+
# @api public
|
4
|
+
class Breadcrumb
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
attr_reader :path
|
8
|
+
alias url path
|
9
|
+
|
10
|
+
def self.[](*args)
|
11
|
+
new(*args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(name, path, current)
|
15
|
+
@name = name
|
16
|
+
@path = path
|
17
|
+
@current = current
|
18
|
+
freeze
|
19
|
+
end
|
20
|
+
|
21
|
+
def current?
|
22
|
+
@current
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_ary
|
26
|
+
[@name, @path, @current]
|
27
|
+
end
|
28
|
+
alias to_a to_ary
|
29
|
+
end # Breadcrumb
|
30
|
+
end # Loaf
|
data/lib/loaf/configuration.rb
CHANGED
@@ -1,15 +1,12 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Loaf
|
4
4
|
class Configuration
|
5
5
|
VALID_ATTRIBUTES = [
|
6
6
|
:locales_path,
|
7
|
-
:style_classes,
|
8
7
|
:crumb_length,
|
9
|
-
:
|
10
|
-
|
11
|
-
:root
|
12
|
-
]
|
8
|
+
:capitalize
|
9
|
+
].freeze
|
13
10
|
|
14
11
|
attr_accessor(*VALID_ATTRIBUTES)
|
15
12
|
|
@@ -28,9 +25,11 @@ module Loaf
|
|
28
25
|
# Setup this configuration
|
29
26
|
#
|
30
27
|
# @api public
|
31
|
-
def initialize
|
28
|
+
def initialize(attributes = {})
|
32
29
|
VALID_ATTRIBUTES.each do |attr|
|
33
|
-
|
30
|
+
default = self.class.const_get("DEFAULT_#{attr.to_s.upcase}")
|
31
|
+
attr_value = attributes.fetch(attr) { default }
|
32
|
+
send("#{attr}=", attr_value)
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
@@ -1,4 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'crumb'
|
2
4
|
|
3
5
|
module Loaf
|
4
6
|
module ControllerExtensions
|
@@ -19,16 +21,23 @@ module Loaf
|
|
19
21
|
# @api public
|
20
22
|
def breadcrumb(name, url, options = {})
|
21
23
|
normalizer = method(:_normalize_name)
|
22
|
-
|
24
|
+
send(_filter_name, options) do |instance|
|
23
25
|
normalized_name = normalizer.call(name, instance)
|
24
26
|
normalized_url = normalizer.call(url, instance)
|
25
27
|
instance.send(:breadcrumb, normalized_name, normalized_url, options)
|
26
28
|
end
|
27
29
|
end
|
28
|
-
|
30
|
+
alias add_breadcrumb breadcrumb
|
29
31
|
|
30
32
|
private
|
31
33
|
|
34
|
+
# Choose available filter name
|
35
|
+
#
|
36
|
+
# @api private
|
37
|
+
def _filter_name
|
38
|
+
respond_to?(:before_action) ? :before_action : :before_filter
|
39
|
+
end
|
40
|
+
|
32
41
|
# @api private
|
33
42
|
def _normalize_name(name, instance)
|
34
43
|
case name
|
@@ -42,24 +51,6 @@ module Loaf
|
|
42
51
|
end # ClassMethods
|
43
52
|
|
44
53
|
module InstanceMethods
|
45
|
-
# Add collection of nested breadcrumbs.
|
46
|
-
# * <tt>collection</tt> - required collection of object for iteration
|
47
|
-
# * <tt>field</tt> - required object attribute name
|
48
|
-
#
|
49
|
-
def add_breadcrumbs(collection, field, options = {})
|
50
|
-
namespace = nil
|
51
|
-
item_set = if _check_if_nested collection
|
52
|
-
items = collection.pop
|
53
|
-
namespace = collection
|
54
|
-
items
|
55
|
-
else
|
56
|
-
collection
|
57
|
-
end
|
58
|
-
item_set.each do |item|
|
59
|
-
add_breadcrumb item.send(field.to_sym), [ namespace, item ].flatten.compact
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
54
|
# Add breadcrumb in controller as instance method
|
64
55
|
#
|
65
56
|
# @param [String] name
|
@@ -70,7 +61,7 @@ module Loaf
|
|
70
61
|
def breadcrumb(name, url, options = {})
|
71
62
|
_breadcrumbs << Loaf::Crumb.new(name, url, options)
|
72
63
|
end
|
73
|
-
|
64
|
+
alias add_breadcrumb breadcrumb
|
74
65
|
|
75
66
|
# Collection of breadcrumbs
|
76
67
|
#
|
@@ -85,12 +76,6 @@ module Loaf
|
|
85
76
|
def clear_breadcrumbs
|
86
77
|
_breadcrumbs.clear
|
87
78
|
end
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
def _check_if_nested(collection)
|
92
|
-
collection.last.is_a? Array
|
93
|
-
end
|
94
79
|
end # InstanceMethods
|
95
80
|
end # ControllerExtensions
|
96
81
|
end # Loaf
|
data/lib/loaf/crumb.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Loaf
|
4
4
|
# Basic crumb container
|
@@ -7,12 +7,13 @@ module Loaf
|
|
7
7
|
|
8
8
|
attr_reader :url
|
9
9
|
|
10
|
-
attr_reader :
|
10
|
+
attr_reader :match
|
11
11
|
|
12
12
|
def initialize(name, url, options = {})
|
13
13
|
@name = name
|
14
14
|
@url = url
|
15
|
-
@
|
15
|
+
@match = options.delete(:match) { :inclusive }
|
16
|
+
freeze
|
16
17
|
end
|
17
|
-
end
|
18
|
+
end # Crumb
|
18
19
|
end # Loaf
|
data/lib/loaf/crumb_formatter.rb
CHANGED
data/lib/loaf/errors.rb
CHANGED
data/lib/loaf/railtie.rb
CHANGED
@@ -3,27 +3,33 @@
|
|
3
3
|
require 'action_controller'
|
4
4
|
require 'action_view'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
class Railtie < Rails::Railtie
|
9
|
-
initializer "loaf.extend_action_controller_base" do |app|
|
10
|
-
ActiveSupport.on_load :action_controller do
|
11
|
-
Loaf::Railtie.insert_controller
|
12
|
-
Loaf::Railtie.insert_view
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
6
|
+
require_relative 'controller_extensions'
|
7
|
+
require_relative 'view_extensions'
|
17
8
|
|
18
|
-
|
9
|
+
module Loaf
|
10
|
+
class RailtieHelpers
|
19
11
|
class << self
|
20
12
|
def insert_view
|
21
13
|
ActionController::Base.helper Loaf::ViewExtensions
|
22
14
|
end
|
15
|
+
|
23
16
|
def insert_controller
|
24
17
|
ActionController::Base.send :include, Loaf::ControllerExtensions
|
25
18
|
end
|
26
19
|
end
|
27
|
-
end #
|
20
|
+
end # RailtieHelpers
|
28
21
|
|
22
|
+
if defined?(Rails::Railtie)
|
23
|
+
class Railtie < Rails::Railtie
|
24
|
+
initializer "loaf.extend_action_controller_base" do |app|
|
25
|
+
ActiveSupport.on_load :action_controller do
|
26
|
+
Loaf::RailtieHelpers.insert_controller
|
27
|
+
Loaf::RailtieHelpers.insert_view
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
else
|
32
|
+
Loaf::RailtieHelpers.insert_controller
|
33
|
+
Loaf::RailtieHelpers.insert_view
|
34
|
+
end
|
29
35
|
end # Loaf
|
data/lib/loaf/translation.rb
CHANGED
data/lib/loaf/version.rb
CHANGED
data/lib/loaf/view_extensions.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require_relative 'breadcrumb'
|
4
|
+
require_relative 'crumb'
|
5
|
+
require_relative 'crumb_formatter'
|
6
|
+
require_relative 'options_validator'
|
5
7
|
|
6
8
|
module Loaf
|
7
9
|
# A mixin to define view extensions
|
@@ -36,37 +38,86 @@ module Loaf
|
|
36
38
|
def breadcrumb(name, url, options = {})
|
37
39
|
_breadcrumbs << Loaf::Crumb.new(name, url, options)
|
38
40
|
end
|
39
|
-
|
41
|
+
alias add_breadcrumb breadcrumb
|
40
42
|
|
41
43
|
# Renders breadcrumbs inside view.
|
42
44
|
#
|
43
45
|
# @param [Hash] options
|
44
46
|
#
|
45
47
|
# @api public
|
46
|
-
def
|
47
|
-
|
48
|
-
|
48
|
+
def breadcrumb_trail(options = {})
|
49
|
+
return enum_for(:breadcrumb_trail) unless block_given?
|
50
|
+
|
49
51
|
valid?(options)
|
50
52
|
options = Loaf.configuration.to_hash.merge(options)
|
51
53
|
_breadcrumbs.each do |crumb|
|
52
|
-
name
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
name = format_name(crumb.name, options)
|
55
|
+
path = url_for(_expand_url(crumb.url))
|
56
|
+
current = current_crumb?(path, crumb.match)
|
57
|
+
|
58
|
+
yield(Loaf::Breadcrumb[name, path, current])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Check if breadcrumb is current based on the pattern
|
63
|
+
#
|
64
|
+
# @param [String] path
|
65
|
+
# @param [Object] pattern
|
66
|
+
# the pattern to match on
|
67
|
+
#
|
68
|
+
# @api public
|
69
|
+
def current_crumb?(path, pattern = :inclusive)
|
70
|
+
return false unless request.get? || request.head?
|
71
|
+
|
72
|
+
origin_path = URI.parser.unescape(path).force_encoding(Encoding::BINARY)
|
73
|
+
|
74
|
+
request_uri = request.fullpath
|
75
|
+
request_uri = URI.parser.unescape(request_uri)
|
76
|
+
request_uri.force_encoding(Encoding::BINARY)
|
77
|
+
|
78
|
+
# strip away trailing slash
|
79
|
+
if origin_path.start_with?('/') && origin_path != '/'
|
80
|
+
origin_path.chomp!('/')
|
81
|
+
request_uri.chomp!('/')
|
82
|
+
end
|
83
|
+
|
84
|
+
if %r{^\w+://} =~ origin_path
|
85
|
+
origin_path.chomp!('/')
|
86
|
+
request_uri.insert(0, "#{request.protocol}#{request.host_with_port}")
|
87
|
+
end
|
88
|
+
|
89
|
+
case pattern
|
90
|
+
when :inclusive
|
91
|
+
!request_uri.match(/^#{Regexp.escape(origin_path)}(\/.*|\?.*)?$/).nil?
|
92
|
+
when :exclusive
|
93
|
+
!request_uri.match(/^#{Regexp.escape(origin_path)}\/?(\?.*)?$/).nil?
|
94
|
+
when :exact
|
95
|
+
request_uri == origin_path
|
96
|
+
when :force
|
97
|
+
true
|
98
|
+
when Regexp
|
99
|
+
!request_uri.match(pattern).nil?
|
100
|
+
when Hash
|
101
|
+
query_params = URI.encode_www_form(pattern)
|
102
|
+
!request_uri.match(/^#{Regexp.escape(origin_path)}\/?(\?.*)?.*?#{query_params}.*$/).nil?
|
103
|
+
else
|
104
|
+
raise ArgumentError, "Unknown `:#{pattern}` match option!"
|
59
105
|
end
|
60
106
|
end
|
61
107
|
|
62
108
|
private
|
63
109
|
|
110
|
+
# Expand url in the current context of the view
|
111
|
+
#
|
64
112
|
# @api private
|
65
|
-
def
|
66
|
-
|
67
|
-
|
113
|
+
def _expand_url(url)
|
114
|
+
case url
|
115
|
+
when String, Symbol
|
116
|
+
respond_to?(url) ? send(url) : url
|
117
|
+
when Proc
|
118
|
+
url.call(self)
|
68
119
|
else
|
69
|
-
|
120
|
+
url
|
70
121
|
end
|
71
122
|
end
|
72
123
|
end # ViewExtensions
|