fcrepo_admin 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY.rdoc +10 -2
  3. data/README.rdoc +59 -14
  4. data/app/controllers/fcrepo_admin/datastreams_controller.rb +8 -46
  5. data/app/controllers/fcrepo_admin/objects_controller.rb +1 -1
  6. data/app/views/fcrepo_admin/datastreams/_alert.html.erb +4 -0
  7. data/app/views/fcrepo_admin/datastreams/_content.html.erb +1 -1
  8. data/app/views/fcrepo_admin/datastreams/_datastreams_list.html.erb +3 -3
  9. data/app/views/fcrepo_admin/datastreams/_profile.html.erb +4 -5
  10. data/app/views/fcrepo_admin/datastreams/content.html.erb +2 -1
  11. data/app/views/fcrepo_admin/datastreams/edit.html.erb +4 -3
  12. data/app/views/fcrepo_admin/datastreams/history.html.erb +3 -8
  13. data/app/views/fcrepo_admin/datastreams/index.html.erb +4 -1
  14. data/app/views/fcrepo_admin/datastreams/upload.html.erb +4 -3
  15. data/app/views/fcrepo_admin/objects/_direct_permissions.html.erb +1 -1
  16. data/app/views/fcrepo_admin/objects/_permissions_list.html.erb +1 -1
  17. data/app/views/fcrepo_admin/objects/permissions.html.erb +8 -2
  18. data/app/views/fcrepo_admin/shared/_context_nav.html.erb +2 -2
  19. data/app/views/layouts/fcrepo_admin/datastreams.html.erb +5 -7
  20. data/app/views/layouts/fcrepo_admin/objects.html.erb +1 -1
  21. data/config/locales/fcrepo_admin.en.yml +33 -22
  22. data/config/routes.rb +5 -2
  23. data/lib/fcrepo_admin.rb +51 -1
  24. data/lib/fcrepo_admin/decorators/active_fedora/base_decorator.rb +33 -0
  25. data/lib/fcrepo_admin/decorators/active_fedora/datastream_decorator.rb +35 -0
  26. data/lib/fcrepo_admin/engine.rb +6 -0
  27. data/lib/fcrepo_admin/helpers/datastreams_helper_behavior.rb +132 -8
  28. data/lib/fcrepo_admin/helpers/objects_helper_behavior.rb +47 -8
  29. data/lib/fcrepo_admin/version.rb +1 -1
  30. data/spec/controllers/datastreams_controller_spec.rb +53 -29
  31. data/spec/controllers/objects_controller_spec.rb +1 -1
  32. data/spec/features/datastreams/content.html.erb_spec.rb +7 -0
  33. data/spec/features/datastreams/edit.html.erb_spec.rb +1 -1
  34. data/spec/features/datastreams/index.html.erb_spec.rb +3 -3
  35. data/spec/features/datastreams/show.html.erb_spec.rb +44 -12
  36. data/spec/features/datastreams/upload.html.erb_spec.rb +1 -1
  37. data/spec/internal/app/models/item.rb +3 -0
  38. data/spec/internal/app/models/solr_document.rb +0 -2
  39. data/spec/internal/spec/fixtures/files/hydra.jpg +0 -0
  40. metadata +9 -8
  41. data/app/views/fcrepo_admin/datastreams/_context_nav.html.erb +0 -9
  42. data/app/views/fcrepo_admin/datastreams/_context_nav_items.html.erb +0 -38
  43. data/app/views/fcrepo_admin/objects/_context_nav.html.erb +0 -9
  44. data/app/views/fcrepo_admin/objects/_context_nav_datastreams.html.erb +0 -13
  45. data/app/views/fcrepo_admin/objects/_context_nav_items.html.erb +0 -19
  46. data/lib/fcrepo_admin/helpers/fcrepo_admin_helper_behavior.rb +0 -27
@@ -1,17 +1,15 @@
1
1
  <% content_for :main do %>
2
2
  <h1><%= object_title %></h1>
3
- <h3>
4
- <%= t("fcrepo_admin.datastream.title") %>: <%= @datastream.dsid %>
5
- </h3>
6
- <% unless ds_is_current_version? %>
3
+ <h3><%= datastream_title %></h3>
4
+ <% unless @datastream.current_version? %>
7
5
  <p>
8
- <%= render :partial => 'version', :locals => {:datastream => @datastream} %>
6
+ <%= render_datastream_version %>
9
7
  </p>
10
8
  <% end %>
11
9
  <%= yield %>
12
10
  <% end %>
13
11
  <% content_for :sidebar do %>
14
- <%= render 'fcrepo_admin/objects/context_nav' %>
15
- <%= render 'context_nav' %>
12
+ <%= object_nav %>
13
+ <%= datastream_nav %>
16
14
  <% end %>
17
15
  <%= render :template => 'layouts/fcrepo_admin/default' %>
@@ -3,6 +3,6 @@
3
3
  <%= yield %>
4
4
  <% end %>
5
5
  <% content_for :sidebar do %>
6
- <%= render 'fcrepo_admin/objects/context_nav' %>
6
+ <%= object_nav %>
7
7
  <% end %>
8
8
  <%= render :template => 'layouts/fcrepo_admin/default' %>
@@ -66,6 +66,16 @@ en:
66
66
  title: 'Datastream'
67
67
  not_persisted: 'Not persisted to Fedora'
68
68
  version: 'Version'
69
+ current_version: 'current version'
70
+ content:
71
+ title: 'Content'
72
+ alerts:
73
+ inactive: 'This datastream is in the inactive state.'
74
+ deleted: 'This datastream is in the deleted state.'
75
+ caution: 'Caution!'
76
+ not_versionable: 'This datastream is not versionable. Changes cannot be reverted.'
77
+ system_managed: 'This datastream is managed by Fedora and/or Hydra and should be modified only with great care.'
78
+ not_persisted: 'This datastream has not been persisted to Fedora.'
69
79
  nav:
70
80
  header: 'Datastream Admin'
71
81
  items:
@@ -81,27 +91,28 @@ en:
81
91
  content_not_text: 'The datastream content is not text'
82
92
  profile:
83
93
  title: 'Profile'
84
- dsLabel: 'Label'
85
- dsMIME: 'MIME Type'
86
- dsVersionID: 'Version'
87
- dsCreateDate: 'Create Date'
88
- dsState: 'State'
89
- dsFormatURI: 'Format URI'
90
- dsControlGroup: 'Control Group'
91
- dsSize: 'Size'
92
- dsVersionable: 'Versionable'
93
- dsInfoType: 'Info Type'
94
- dsLocation: 'Location'
95
- dsLocationType: 'Location Type'
96
- dsChecksumType: 'Checksum Type'
97
- dsChecksum: 'Checksum'
94
+ keys:
95
+ dsLabel: 'Label'
96
+ dsMIME: 'MIME Type'
97
+ dsVersionID: 'Version'
98
+ dsCreateDate: 'Create Date'
99
+ dsState: 'State'
100
+ dsFormatURI: 'Format URI'
101
+ dsControlGroup: 'Control Group'
102
+ dsSize: 'Size'
103
+ dsVersionable: 'Versionable'
104
+ dsInfoType: 'Info Type'
105
+ dsLocation: 'Location'
106
+ dsLocationType: 'Location Type'
107
+ dsChecksumType: 'Checksum Type'
108
+ dsChecksum: 'Checksum'
98
109
  edit:
99
- header: 'Edit Content'
100
- confirm: "These changes are not validated and cannot be undone!"
101
- submit: 'Update'
110
+ title: 'Edit Content'
111
+ form:
112
+ confirm: "These changes are not validated and cannot be undone!"
113
+ submit: 'Update'
102
114
  upload:
103
- header: 'Upload Content'
104
- confirm: "These changes are not validated and cannot be undone!"
105
- submit: 'Upload'
106
-
107
-
115
+ title: 'Upload Content'
116
+ form:
117
+ confirm: "These changes are not validated and cannot be undone!"
118
+ submit: 'Upload'
data/config/routes.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  FcrepoAdmin::Engine.routes.draw do
2
2
 
3
+ datastreams_resources = [:index, :show]
4
+ datastreams_resources += [:edit, :update] unless FcrepoAdmin.read_only
5
+
3
6
  scope :module => "fcrepo_admin" do
4
7
  resources :objects, :only => :show do
5
8
  member do
@@ -7,10 +10,10 @@ FcrepoAdmin::Engine.routes.draw do
7
10
  get 'permissions'
8
11
  end
9
12
  resources :associations, :only => [:index, :show]
10
- resources :datastreams, :only => [:index, :show, :edit, :update] do
13
+ resources :datastreams, :only => datastreams_resources do
11
14
  member do
12
15
  get 'content'
13
- get 'upload'
16
+ get 'upload' unless FcrepoAdmin.read_only
14
17
  get 'download'
15
18
  get 'history'
16
19
  end
data/lib/fcrepo_admin.rb CHANGED
@@ -3,8 +3,56 @@ require 'blacklight'
3
3
  require 'hydra/head'
4
4
 
5
5
  module FcrepoAdmin
6
- autoload :SolrDocumentExtension, 'fcrepo_admin/solr_document_extension'
6
+
7
+ #
8
+ # FcrepoAdmin configuration settings
9
+ #
10
+ mattr_accessor :read_only
11
+ self.read_only = false
12
+
13
+ # MIME types representing text content that do not have "text" media type.
14
+ mattr_accessor :extra_text_mime_types
15
+ self.extra_text_mime_types = ['application/xml', 'application/rdf+xml', 'application/json']
16
+
17
+ # Datastream profile keys for values to display on datastream index view
18
+ mattr_accessor :datastream_index_columns
19
+ self.datastream_index_columns = ["dsLabel", "dsMIME", "dsSize", "dsCreateDate"]
20
+
21
+ # Datastream profile keys for values to display on datastream history view
22
+ mattr_accessor :datastream_history_columns
23
+ self.datastream_history_columns = ["dsCreateDate"]
24
+
25
+ # Datastream context navigation items
26
+ mattr_accessor :datastream_nav_items
27
+ self.datastream_nav_items = [:dsid, :version, :current_version, :summary, :content, :download, :edit, :upload, :history]
28
+
29
+ mattr_accessor :datastream_show_profile_keys
30
+ self.datastream_show_profile_keys = ["dsLabel", "dsMIME", "dsVersionID", "dsCreateDate", "dsState",
31
+ "dsFormatURI", "dsControlGroup", "dsSize", "dsVersionable",
32
+ "dsInfoType", "dsLocation", "dsLocationType", "dsChecksumType",
33
+ "dsChecksum"]
34
+
35
+ # Sanity check on amount of text data to make editable via web form
36
+ mattr_accessor :max_editable_datastream_size
37
+ self.max_editable_datastream_size = 1024 * 64
38
+
39
+ # Object context navigation items
40
+ mattr_accessor :object_nav_items
41
+ self.object_nav_items = [:pid, :summary, :datastreams, :permissions, :associations, :audit_trail]
42
+
43
+ # Datastream profile values to display on object show view
44
+ mattr_accessor :object_show_datastream_columns
45
+ self.object_show_datastream_columns = ["dsLabel"]
46
+
47
+ # Methods on ActiveFedora::Base objects that represent Fcrepo object properties
48
+ mattr_accessor :object_properties
49
+ self.object_properties = [:label, :state, :create_date, :modified_date, :owner_id]
50
+
51
+ #
52
+ # Autoloading
53
+ #
7
54
  autoload :Ability, 'fcrepo_admin/ability'
55
+
8
56
  module Helpers
9
57
  autoload :BlacklightHelperBehavior, 'fcrepo_admin/helpers/blacklight_helper_behavior'
10
58
  autoload :ObjectsHelperBehavior, 'fcrepo_admin/helpers/objects_helper_behavior'
@@ -12,7 +60,9 @@ module FcrepoAdmin
12
60
  autoload :AssociationsHelperBehavior, 'fcrepo_admin/helpers/associations_helper_behavior'
13
61
  autoload :FcrepoAdminHelperBehavior, 'fcrepo_admin/helpers/fcrepo_admin_helper_behavior'
14
62
  end
63
+
15
64
  module Controller
16
65
  autoload :ControllerBehavior, 'fcrepo_admin/controller/controller_behavior'
17
66
  end
67
+
18
68
  end
@@ -0,0 +1,33 @@
1
+ ActiveFedora::Base.class_eval do
2
+
3
+ def active?
4
+ state == 'A'
5
+ end
6
+
7
+ def auditable?
8
+ begin
9
+ self.is_a? ActiveFedora::Auditable
10
+ rescue
11
+ false
12
+ end
13
+ end
14
+
15
+ def has_permissions?
16
+ self.is_a? Hydra::ModelMixins::RightsMetadata
17
+ end
18
+
19
+ def governable?
20
+ !is_governed_by_association.nil?
21
+ end
22
+
23
+ private
24
+
25
+ def governed_by_association
26
+ self.reflections.each do |name, reflection|
27
+ # FIXME add class name condition, i.e.:
28
+ # && reflection.class_name == [Hydra configured policy class or Hydra::AdminPolicy]
29
+ return reflection if reflection.macro == :belongs_to && reflection.options[:property] == :is_governed_by
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,35 @@
1
+ ActiveFedora::Datastream.class_eval do
2
+
3
+ def active?
4
+ dsState == 'A'
5
+ end
6
+
7
+ def current_version?
8
+ @current_version ||= (new? || versions.empty? || dsVersionID == versions.first.dsVersionID)
9
+ end
10
+
11
+ def content_is_url?
12
+ external? || redirect?
13
+ end
14
+
15
+ def content_is_downloadable?
16
+ has_content? && (managed? || inline?)
17
+ end
18
+
19
+ def modifiable?
20
+ !FcrepoAdmin.read_only && active? && current_version?
21
+ end
22
+
23
+ def content_is_uploadable?
24
+ modifiable? && (managed? || inline?)
25
+ end
26
+
27
+ def content_is_editable?
28
+ modifiable? && !content_is_url? && content_is_text? && dsSize <= FcrepoAdmin.max_editable_datastream_size
29
+ end
30
+
31
+ def content_is_text?
32
+ has_content? && !mimeType.blank? && (mimeType.start_with?('text/') || FcrepoAdmin.extra_text_mime_types.include?(mimeType))
33
+ end
34
+
35
+ end
@@ -8,5 +8,11 @@ module FcrepoAdmin
8
8
  g.helper false
9
9
  end
10
10
 
11
+ config.before_initialize do
12
+ # load ActiveFedora decorators
13
+ require 'fcrepo_admin/decorators/active_fedora/base_decorator'
14
+ require 'fcrepo_admin/decorators/active_fedora/datastream_decorator'
15
+ end
16
+
11
17
  end
12
18
  end
@@ -1,28 +1,152 @@
1
1
  module FcrepoAdmin::Helpers
2
2
  module DatastreamsHelperBehavior
3
- include FcrepoAdmin::Helpers::FcrepoAdminHelperBehavior
4
3
 
5
- def datastream_context_nav_header
4
+ def datastream_title
5
+ "#{t('fcrepo_admin.datastream.title')}: #{@datastream.dsid}"
6
+ end
7
+
8
+ def datastream_show_profile_keys
9
+ FcrepoAdmin.datastream_show_profile_keys
10
+ end
11
+
12
+ def datastream_nav
13
+ render :partial => 'fcrepo_admin/shared/context_nav', :locals => {:header => datastream_nav_header, :items => datastream_nav_items}
14
+ end
15
+
16
+ def datastream_nav_header
6
17
  t("fcrepo_admin.datastream.nav.header")
7
18
  end
8
19
 
9
- def datastream_context_nav_items
10
- render :partial => 'fcrepo_admin/datastreams/context_nav_items', :locals => {:object => @object, :datastream => @datastream}
20
+ def datastream_nav_items
21
+ FcrepoAdmin.datastream_nav_items.collect { |item| datastream_nav_item(item) }.reject { |item| item.nil? }
11
22
  end
12
23
 
13
- # List of ds profile keys for ds index view
14
24
  def datastream_index_columns
15
- ["dsLabel", "dsMIME", "dsSize", "dsCreateDate"]
25
+ FcrepoAdmin.datastream_index_columns
16
26
  end
17
27
 
18
- # List of ds profile keys for ds history view
19
28
  def datastream_history_columns
20
- ["dsCreateDate"]
29
+ FcrepoAdmin.datastream_history_columns
21
30
  end
22
31
 
23
32
  def datastream_params
24
33
  params.has_key?(:asOfDateTime) ? {:asOfDateTime => params[:asOfDateTime]} : {}
25
34
  end
26
35
 
36
+ def datastream_nav_item(item)
37
+ case
38
+ when item == :dsid then render_datastream_dsid_label
39
+ when item == :version then render_datastream_version unless @datastream.current_version?
40
+ when item == :current_version then link_to_datastream item, !@datastream.current_version?, false
41
+ when item == :summary then link_to_datastream item
42
+ when item == :content then link_to_datastream item, @datastream.content_is_text?
43
+ when item == :download then link_to_datastream item, @datastream.content_is_downloadable?, false
44
+ when item == :edit then link_to_datastream item, @datastream.content_is_editable? && can?(:edit, @object)
45
+ when item == :upload then link_to_datastream item, @datastream.content_is_uploadable? && can?(:upload, @object)
46
+ when item == :history then link_to_datastream item, !@datastream.new?
47
+ else custom_datastream_nav_item item
48
+ end
49
+ end
50
+
51
+ def link_to_datastream(view, condition=true, unless_current=true)
52
+ return nil unless condition
53
+ path = case
54
+ when view == :current_version then fcrepo_admin.object_datastream_path(@object, @datastream)
55
+ when view == :summary then fcrepo_admin.object_datastream_path(@object, @datastream, datastream_params)
56
+ when view == :content then fcrepo_admin.content_object_datastream_path(@object, @datastream, datastream_params)
57
+ when view == :download then fcrepo_admin.download_object_datastream_path(@object, @datastream, datastream_params)
58
+ when view == :edit then fcrepo_admin.edit_object_datastream_path(@object, @datastream)
59
+ when view == :upload then fcrepo_admin.upload_object_datastream_path(@object, @datastream)
60
+ when view == :history then fcrepo_admin.history_object_datastream_path(@object, @datastream)
61
+ end
62
+ label = t("fcrepo_admin.datastream.nav.items.#{view}")
63
+ unless_current ? link_to_unless_current(label, path) : link_to(label, path)
64
+ end
65
+
66
+ def custom_datastream_nav_item(item)
67
+ # Override this method with your custom item behavior
68
+ end
69
+
70
+ def link_to_datastream_version(dsVersion)
71
+ link_to_unless dsVersion.current_version?, dsVersion.dsVersionID, fcrepo_admin.object_datastream_path(@object, @datastream, :asOfDateTime => dsVersion.asOfDateTime) do |name|
72
+ "#{name} (current version)"
73
+ end
74
+ end
75
+
76
+ def render_datastream_version
77
+ render :partial => 'version', :locals => {:datastream => @datastream}
78
+ end
79
+
80
+ def render_datastream_dsid_label
81
+ content_tag :span, @datastream.dsid, :class => "label"
82
+ end
83
+
84
+ def datastream_alerts(*alerts)
85
+ rendered = ""
86
+ alerts.each do |alert|
87
+ content = datastream_alert(alert)
88
+ rendered << content unless content.nil?
89
+ end
90
+ rendered.html_safe
91
+ end
92
+
93
+ def datastream_alert(alert)
94
+ case
95
+ when alert == :system_managed
96
+ if ["DC", "RELS-EXT", "rightsMetadata", "defaultRights"].include?(@datastream.dsid)
97
+ render_datastream_alert(alert, :caution => true)
98
+ end
99
+ when alert == :not_versionable
100
+ render_datastream_alert(alert, :caution => true) unless @datastream.versionable
101
+ when alert == :inactive
102
+ render_datastream_alert(alert) if @datastream.inactive?
103
+ when alert == :deleted
104
+ render_datastream_alert(alert, :css_class => "alert alert-error") if @datastream.deleted?
105
+ end
106
+ end
107
+
108
+ def render_datastream_alert(alert, opts={})
109
+ render :partial => 'alert', :locals => {:alert => alert, :caution => opts.fetch(:caution, false), :css_class => opts.fetch(:css_class, "alert")}
110
+ end
111
+
112
+ def format_datastream_state(ds)
113
+ state = ds.dsState
114
+ formatted = case
115
+ when state == 'A' then "A (Active)"
116
+ when state == 'I' then "I (Inactive)"
117
+ when state == 'D' then "D (Deleted)"
118
+ end
119
+ formatted
120
+ end
121
+
122
+ def format_datastream_control_group(ds)
123
+ control_group = ds.controlGroup
124
+ formatted = case
125
+ when control_group == 'M' then "M (Managed)"
126
+ when control_group == 'X' then "X (Inline XML)"
127
+ when control_group == 'E' then "E (External Referenced)"
128
+ when control_group == 'R' then "R (Redirect)"
129
+ end
130
+ formatted
131
+ end
132
+
133
+ def format_datastream_version_id(ds)
134
+ version_id = ds.dsVersionID
135
+ version_id += " (#{t('fcrepo_admin.datastream.current_version')})" if ds.current_version?
136
+ version_id
137
+ end
138
+
139
+ def format_datastream_profile_value(ds, key)
140
+ case
141
+ when key == "dsSize" then number_to_human_size(ds.dsSize)
142
+ when key == "dsCreateDate" then ds.dsCreateDate.strftime("%Y-%m-%dT%H:%M:%S.%LZ")
143
+ when key == "dsLocation" && ds.content_is_url? then link_to(ds.dsLocation, ds.dsLocation)
144
+ when key == "dsState" then format_datastream_state(ds)
145
+ when key == "dsControlGroup" then format_datastream_control_group(ds)
146
+ when key == "dsVersionID" then format_datastream_version_id(ds)
147
+ else ds.profile[key]
148
+ end
149
+ end
150
+
27
151
  end
28
152
  end
@@ -1,6 +1,5 @@
1
1
  module FcrepoAdmin::Helpers
2
2
  module ObjectsHelperBehavior
3
- include FcrepoAdmin::Helpers::FcrepoAdminHelperBehavior
4
3
 
5
4
  def object_title
6
5
  "#{object_type} #{@object.pid}"
@@ -10,17 +9,57 @@ module FcrepoAdmin::Helpers
10
9
  @object.class.to_s
11
10
  end
12
11
 
13
- def object_properties_keys
14
- [:owner_id, :state, :create_date, :modified_date, :label]
15
- end
16
-
17
12
  def object_properties
18
- object_properties_keys.inject(Hash.new) { |h, p| h[p] = @object.send(p); h }
13
+ FcrepoAdmin.object_properties.inject(Hash.new) { |h, p| h[p] = @object.send(p); h }
19
14
  end
20
15
 
21
- # List of ds profile keys for for object show view
22
16
  def object_show_datastream_columns
23
- ["dsLabel"]
17
+ FcrepoAdmin.object_show_datastream_columns
18
+ end
19
+
20
+ def object_nav
21
+ render :partial => 'fcrepo_admin/shared/context_nav', :locals => {:header => object_nav_header, :items => object_nav_items}
22
+ end
23
+
24
+ def object_nav_header
25
+ t("fcrepo_admin.object.nav.header")
26
+ end
27
+
28
+ def object_nav_items
29
+ FcrepoAdmin.object_nav_items.collect { |item| object_nav_item(item) }.reject { |item| item.nil? }
30
+ end
31
+
32
+ def object_nav_item(item)
33
+ case
34
+ when item == :pid then render_object_pid_label
35
+ when item == :summary then link_to_object item
36
+ when item == :datastreams then link_to_object item
37
+ when item == :permissions then link_to_object item, @object.has_permissions? && can?(:permissions, @object)
38
+ when item == :associations then link_to_object item
39
+ when item == :audit_trail then link_to_object item, @object.auditable? && can?(:audit_trail, @object)
40
+ else custom_object_nav_item item
41
+ end
42
+ end
43
+
44
+ def render_object_pid_label
45
+ content_tag :span, @object.pid, :class => "label"
46
+ end
47
+
48
+ def link_to_object(view, condition=true)
49
+ return nil unless condition
50
+ label = t("fcrepo_admin.object.nav.items.#{view}")
51
+ path = case
52
+ when view == :summary then fcrepo_admin.object_path(@object)
53
+ when view == :datastreams then fcrepo_admin.object_datastreams_path(@object)
54
+ when view == :permissions then fcrepo_admin.permissions_object_path(@object)
55
+ when view == :associations then fcrepo_admin.object_associations_path(@object)
56
+ when view == :audit_trail then fcrepo_admin.audit_trail_object_path(@object)
57
+ end
58
+ link_to_unless_current label, path
59
+ end
60
+
61
+ def custom_object_nav_item(item)
62
+ # Override this method with your custom item behavior
24
63
  end
25
64
 
26
65
  end