easy_breadcrumbs 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fcf9be5056635f695ed430f771d5ca29e4246a22
4
- data.tar.gz: 32c198b059cad879a487b54ff286c29b53451bf1
3
+ metadata.gz: da48440d6066a1f709e0f1a08d3e2e845c0351eb
4
+ data.tar.gz: f9bf00269eb7de2c967d2874c4eecb25c005654c
5
5
  SHA512:
6
- metadata.gz: e55a3be879f425b60a06f768171ce920dd644f11043b34cec8c99e31a2a9c07761bc77f45e9e39ab97c1ef30674834359f80d7d7fac2e1d3fae1c95a476dff1a
7
- data.tar.gz: c584c9494c1eca7fd9b53ce63cdce7b723106cbb80397ee0f34891a34214b99a4f2effd6a710fe3990a240f1ac52510249eb523657c425658fdfdb0dcfc5d883
6
+ metadata.gz: 1f9b9fb5ee030f4912922587912733d3c6a37c8610210d160ac8c020d41e5a617ee24e1e842ae25c11a55fcfb55f2fe8e66299c0b30d2c3b16df47cc47ac09c7
7
+ data.tar.gz: 2941b856493d0e4c3f1ca38c6eb77cee6c3d6f33e9d9bce665f30e352b7d745980211b03eebd6d9de8a6f099ae319018c25b041827c1a14a7bd777d978faa6dd
data/README.md CHANGED
@@ -4,6 +4,7 @@ Provides an `easy_breadcrumbs` view helper for automatically generating bootstra
4
4
 
5
5
  * It's able to properly generate the html for many different types of complex routes (See Below).
6
6
  * It only generates breadcrumbs for the routes you've defined, so if you have a route `/categories/10/contacts/5`, but haven't defined an index view route for `/categories`, that item will be left out.
7
+ * It can automatically detect certain name attributes for specific resources.
7
8
 
8
9
  ## Installation
9
10
 
@@ -53,7 +54,27 @@ And last but not least, make sure you have bootstrap installed. You can install
53
54
 
54
55
  ## Details
55
56
 
56
- Easy Breadcrumbs is able to handle a variety of complex routes. Here are some examples:
57
+ **NEW: Auto Name Detection**
58
+
59
+ Easy Breadcrumbs can now detect names for specific resources.
60
+ ```
61
+ Path: /contacts/10
62
+ Old Breadcrumb Format: Home > Contacts > Contact
63
+ New Breadcrumb Format: Home > Contacts > Ada Lovelace
64
+ ```
65
+
66
+ It's able to detect the name with the following limitations:
67
+ * The resource is either a Hash or a Custom object
68
+ * The resource has a key (Hash) or accessor method (custom object) of one of the following 3 commonly used name attributes:
69
+ * :name
70
+ * :title
71
+ * :subject
72
+
73
+ If this condition fails, it will default to the old format.
74
+
75
+ **Easy Breadcrumbs is able to handle a variety of complex routes.**
76
+
77
+ Here are some examples:
57
78
 
58
79
  ### Simple path to page
59
80
  ```
@@ -111,11 +132,13 @@ Breadcrumb: Home > Categories > Category > Contacts > Contact > Edit Contact
111
132
 
112
133
  ## Road Map
113
134
 
114
- * Add configuration for showing individual resource name/title as breadcrumb (e.g. "Ada Lovelace") anchor text rather than resource type name (e.g. "Contact")
115
- * Integration for Rails
116
- * A simple means of configuration for things like:
117
- * Turning on and off specific routes
118
- * Setting breadcrumb styles (maybe provide an option for a different framework like Foundation, or just provide a few different styling presets)
135
+ * Allow for custom configuration of name attributes for resources
136
+ * Should be able to do something like `set :easy_breadcrumbs, user: :name, post: :title`
137
+ * More robust spec suite
138
+ * Explore more edge cases for both unit and integration tests
139
+ * Eliminate repetition in specs
140
+ * Other development gems that would help with this?
141
+ * Update gemspec with depencency version restrictions and bump gem version to 1.0
119
142
 
120
143
  ## Contributing
121
144
 
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
 
12
12
  spec.summary = %q{Automatically add bootstrap breadcrumbs to your Sinatra app.}
13
13
  spec.description = %q{Provides an `easy_breadcrumbs` view helper for automatically generating bootstrap breadcrumbs for your Sinatra Application.}
14
- spec.homepage = ""
14
+ spec.homepage = "https://github.com/nerboda/easy_breadcrumbs"
15
15
  spec.license = "MIT"
16
16
 
17
17
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -1,14 +1,14 @@
1
1
  <ol class="breadcrumb">
2
- <% if @links.empty? %>
2
+ <% if @breadcrumbs.empty? %>
3
3
  <li class="breadcrumb-item active">Home</li>
4
4
  <% else %>
5
5
  <li class="breadcrumb-item"><a href="/">Home</a></li>
6
6
  <% end %>
7
- <% @links.each do |link| %>
8
- <% if link.path == @links.last.path %>
9
- <li class="breadcrumb-item active"><%= link.text %></li>
7
+ <% @breadcrumbs.each do |breadcrumb| %>
8
+ <% if breadcrumb.path == @breadcrumbs.last.path %>
9
+ <li class="breadcrumb-item active"><%= breadcrumb.text %></li>
10
10
  <% else %>
11
- <li class="breadcrumb-item"><a href="<%= link.path %>"><%= link.text %></a></li>
11
+ <li class="breadcrumb-item"><a href="<%= breadcrumb.path %>"><%= breadcrumb.text %></a></li>
12
12
  <% end %>
13
13
  <% end %>
14
14
  </ol>
@@ -1,23 +1,57 @@
1
1
  require 'sinatra/base'
2
2
  require 'easy_breadcrumbs/version'
3
- require 'easy_breadcrumbs/breadcrumb'
3
+ require 'easy_breadcrumbs/breadcrumbs'
4
4
 
5
5
  module Sinatra
6
6
  include ::EasyBreadcrumbs
7
7
 
8
8
  module EasyBreadcrumbs
9
- Breadcrumb = ::EasyBreadcrumbs::Breadcrumb
9
+ Breadcrumbs = ::EasyBreadcrumbs::Breadcrumbs
10
10
 
11
11
  def easy_breadcrumbs
12
- # Path from current Rack::Request object
12
+ breadcrumb = Breadcrumbs.new(config)
13
+ breadcrumb.to_html
14
+ end
15
+
16
+ private
17
+
18
+ EXCLUDED_VARS = [:@default_layout, :@preferred_extension,
19
+ :@app, :@template_cache, :@template_cache,
20
+ :@env, :@request, :@response, :@params]
21
+
22
+ Configuration = Struct.new(:request_path, :route_matchers, :view_variables)
23
+
24
+ def config
25
+ # The name of the current Sinatra Application
26
+ app = self.class
27
+
28
+ # The Rack::Request object
13
29
  request_path = request.path
14
30
 
15
- # All GET request routes
16
- route_matchers = self.class.routes['GET'].map { |route| route[0] }
31
+ # All defined GET request routes
32
+ route_matchers = app.routes['GET'].map { |route| route[0] }
17
33
 
18
- # The rest is handled by Breadcrumb class
19
- breadcrumb = Breadcrumb.new(request_path, route_matchers)
20
- breadcrumb.to_html
34
+ Configuration.new(request_path, route_matchers, view_variables)
35
+ end
36
+
37
+ # All user defined instance variables for current request.
38
+ def view_variables
39
+ instance_variables
40
+ .select { |var| additional_var?(var) }
41
+ .map { |var| fetch_ivar_value(var) }
42
+ end
43
+
44
+ # Walk through all instance variables and fetch value.
45
+ def fetch_ivar_value(var)
46
+ name = var.to_s.delete('@').to_sym
47
+ value = instance_eval(var.to_s)
48
+
49
+ { name: name, value: value }
50
+ end
51
+
52
+ # Ignore pre-existing Sinatra instance variables.
53
+ def additional_var?(var)
54
+ !EXCLUDED_VARS.include?(var)
21
55
  end
22
56
  end
23
57
 
@@ -0,0 +1,27 @@
1
+ module EasyBreadcrumbs
2
+ module AutoDetect
3
+ COMMON_NAME_ATTRIBUTES = %i[name title subject]
4
+
5
+ def detect_name(resource)
6
+ name_attribute = find_common_accessor_method(resource)
7
+ return resource[name_attribute] if name_attribute
8
+
9
+ name_attribute = find_common_hash_symbol(resource)
10
+ return resource[name_attribute] if name_attribute
11
+ end
12
+
13
+ private
14
+
15
+ def find_common_accessor_method(resource)
16
+ COMMON_NAME_ATTRIBUTES.find do |method|
17
+ resource.respond_to?(method)
18
+ end
19
+ end
20
+
21
+ def find_common_hash_symbol(resource)
22
+ COMMON_NAME_ATTRIBUTES.find do |method|
23
+ resource.key?(method)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,76 +1,57 @@
1
- require 'erubis'
2
1
  require 'active_support/inflector/methods'
2
+ require_relative 'auto_detect'
3
3
 
4
4
  module EasyBreadcrumbs
5
- # Breadcrumb class. Converts a URL path into Bootstrap breadcrumbs
5
+ # Breadcrumb class properly formats it's data depending on:
6
+ # => Where within the set of breadcrumbs it falls
7
+ # => Whether it's a path to a specific resource
8
+ # => Whether it's a path to a `new` or `edit` view
6
9
  class Breadcrumb
7
10
  include ActiveSupport::Inflector
11
+ include AutoDetect
8
12
 
9
- def initialize(request_path, route_matchers, options = {})
10
- @configuration = options
11
- @routes = route_matchers
12
- @directories = request_path.scan(%r{\/[^\/]+})
13
- @links = []
13
+ attr_reader :path, :text
14
14
 
15
- build_links!
16
- end
17
-
18
- def to_html
19
- path = File.expand_path('../../assets/breadcrumbs.eruby', __FILE__)
20
- template = File.read(path)
15
+ def initialize(directories, directory)
16
+ @directories = directories
17
+ @directory = directory
21
18
 
22
- eruby = Erubis::Eruby.new(template)
23
- eruby.result(binding)
19
+ @path = directory.full_path
20
+ @text = format_anchor_text
24
21
  end
25
22
 
26
23
  private
27
24
 
28
- Link = Struct.new(:path, :text)
25
+ attr_reader :directories, :directory
29
26
 
30
- def build_links!
31
- @directories.each_with_index do |directory, index|
32
- full_path = @directories[0..index].join
27
+ def format_anchor_text
28
+ return specific_resource if directory.ends_in_digit?
29
+ return with_view_prefix if directory.new_or_edit_view?
33
30
 
34
- if defined_route?(full_path)
35
- anchor_text = to_anchor_text(directory, index)
36
- @links << Link.new(full_path, anchor_text)
37
- end
38
- end
31
+ directory.name.capitalize
39
32
  end
40
33
 
41
- def to_anchor_text(directory, index)
42
- if directory =~ /\d/
43
- format_for_specific_resource(index)
44
- elsif %w(/edit /new).include?(directory)
45
- format_with_view_prefix(directory, index)
34
+ def specific_resource
35
+ previous_directory = other_directory(-1)
36
+
37
+ if previous_directory.resource
38
+ detect_name(previous_directory.resource)
46
39
  else
47
- clean_and_capitalize(directory)
40
+ singularize(previous_directory.name).capitalize
48
41
  end
49
42
  end
50
43
 
51
- def format_for_specific_resource(index)
52
- previous_directory = @directories[index - 1]
53
- text_for_anchor = clean_and_capitalize(previous_directory)
54
- singularize(text_for_anchor)
55
- end
56
-
57
- def format_with_view_prefix(directory, index)
58
- previous_index = directory == "/edit" ? index - 2 : index - 1
59
- previous_directory = @directories[previous_index]
60
-
61
- view_prefix = clean_and_capitalize(directory)
62
- rest_of_anchor = clean_and_capitalize(previous_directory)
63
- singularized = singularize(rest_of_anchor)
64
-
65
- "#{view_prefix} #{singularized}"
66
- end
44
+ def with_view_prefix
45
+ relative_index = directory.edit_view? ? -2 : -1
46
+ previous_directory = other_directory(relative_index)
47
+ view_prefix = directory.name.capitalize
48
+ rest_of_anchor = singularize(previous_directory.name).capitalize
67
49
 
68
- def clean_and_capitalize(directory)
69
- directory.delete('/').capitalize
50
+ "#{view_prefix} #{rest_of_anchor}"
70
51
  end
71
52
 
72
- def defined_route?(path)
73
- @routes.any? { |route| path =~ route }
53
+ def other_directory(relative_index)
54
+ directories[directory.index + relative_index]
74
55
  end
75
56
  end
76
57
  end
@@ -0,0 +1,72 @@
1
+ require 'erubis'
2
+ require 'active_support/inflector/methods'
3
+
4
+ require_relative 'breadcrumb'
5
+ require_relative 'directory'
6
+
7
+ module EasyBreadcrumbs
8
+ # Breadcrumbs class: Converts a URL path into Bootstrap breadcrumbs.
9
+ class Breadcrumbs
10
+ include ActiveSupport::Inflector
11
+
12
+ TEMPLATE = 'breadcrumbs.eruby'.freeze
13
+
14
+ def initialize(configuration)
15
+ @view_variables = configuration.view_variables
16
+ @routes = configuration.route_matchers
17
+ @path = configuration.request_path
18
+
19
+ @directories = []
20
+ @breadcrumbs = []
21
+
22
+ build_directories!
23
+ build_breadcrumbs!
24
+ end
25
+
26
+ def to_html
27
+ path = File.expand_path('../../assets/' + TEMPLATE, __FILE__)
28
+ template = File.read(path)
29
+ eruby = Erubis::Eruby.new(template)
30
+
31
+ eruby.result(binding)
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :view_variables, :routes, :path,
37
+ :directories, :breadcrumbs
38
+
39
+ def build_directories!
40
+ parsed = path.scan(%r{\/[^\/]+})
41
+
42
+ parsed.map.with_index do |current, index|
43
+ full_path = parsed[0..index].join
44
+ name = current.delete('/')
45
+ resource = fetch_variable_value(name)
46
+
47
+ data = { full_path: full_path, name: name,
48
+ resource: resource, index: index }
49
+
50
+ @directories << Directory.new(data)
51
+ end
52
+ end
53
+
54
+ def build_breadcrumbs!
55
+ directories.each do |directory|
56
+ next unless defined_route?(directory.full_path)
57
+ @breadcrumbs << Breadcrumb.new(directories, directory)
58
+ end
59
+ end
60
+
61
+ def defined_route?(path)
62
+ routes.any? { |route| path =~ route }
63
+ end
64
+
65
+ def fetch_variable_value(resource_name)
66
+ symbol = singularize(resource_name).to_sym
67
+ variable = view_variables.find { |var| var[:name] == symbol }
68
+
69
+ variable[:value] if variable
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,33 @@
1
+ module EasyBreadcrumbs
2
+ # Directory class makes things easier on the Breadcrumb class.
3
+ class Directory
4
+ attr_reader :full_path, :name, :index, :resource
5
+
6
+ def initialize(data)
7
+ @full_path = data.fetch(:full_path)
8
+ @name = data.fetch(:name)
9
+ @resource = data.fetch(:resource)
10
+ @index = data.fetch(:index)
11
+ end
12
+
13
+ def root_path?
14
+ index.zero?
15
+ end
16
+
17
+ def ends_in_digit?
18
+ name =~ %r{\d+\/?$}
19
+ end
20
+
21
+ def new_view?
22
+ name == 'new'
23
+ end
24
+
25
+ def edit_view?
26
+ name == 'edit'
27
+ end
28
+
29
+ def new_or_edit_view?
30
+ new_view? || edit_view?
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module EasyBreadcrumbs
2
- VERSION = "0.4.0"
2
+ VERSION = '0.5.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_breadcrumbs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eliathah Boda
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-01-30 00:00:00.000000000 Z
11
+ date: 2017-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -128,9 +128,12 @@ files:
128
128
  - easy_breadcrumbs.gemspec
129
129
  - lib/assets/breadcrumbs.eruby
130
130
  - lib/easy_breadcrumbs.rb
131
+ - lib/easy_breadcrumbs/auto_detect.rb
131
132
  - lib/easy_breadcrumbs/breadcrumb.rb
133
+ - lib/easy_breadcrumbs/breadcrumbs.rb
134
+ - lib/easy_breadcrumbs/directory.rb
132
135
  - lib/easy_breadcrumbs/version.rb
133
- homepage: ''
136
+ homepage: https://github.com/nerboda/easy_breadcrumbs
134
137
  licenses:
135
138
  - MIT
136
139
  metadata: {}