duck_map 0.8.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.
- data/app/controllers/sitemap_base_controller.rb +13 -0
- data/app/controllers/sitemap_controller.rb +3 -0
- data/app/views/sitemap/default_template.xml.erb +10 -0
- data/config/routes.rb +5 -0
- data/lib/duck_map/array_helper.rb +50 -0
- data/lib/duck_map/attributes.rb +182 -0
- data/lib/duck_map/class_helpers.rb +55 -0
- data/lib/duck_map/config.rb +367 -0
- data/lib/duck_map/controller_helpers.rb +206 -0
- data/lib/duck_map/engine.rb +92 -0
- data/lib/duck_map/filter_stack.rb +200 -0
- data/lib/duck_map/handlers/base.rb +102 -0
- data/lib/duck_map/handlers/index.rb +140 -0
- data/lib/duck_map/handlers/show.rb +231 -0
- data/lib/duck_map/last_mod.rb +45 -0
- data/lib/duck_map/list.rb +82 -0
- data/lib/duck_map/logger.rb +193 -0
- data/lib/duck_map/mapper.rb +216 -0
- data/lib/duck_map/model.rb +27 -0
- data/lib/duck_map/route.rb +275 -0
- data/lib/duck_map/route_filter.rb +177 -0
- data/lib/duck_map/route_set.rb +209 -0
- data/lib/duck_map/sitemap_object.rb +457 -0
- data/lib/duck_map/static.rb +146 -0
- data/lib/duck_map/sync.rb +192 -0
- data/lib/duck_map/version.rb +3 -0
- data/lib/duck_map/view_helpers.rb +107 -0
- data/lib/duck_map.rb +3 -0
- data/lib/generators/duckmap/sitemaps/USAGE +23 -0
- data/lib/generators/duckmap/sitemaps/sitemaps_generator.rb +36 -0
- data/lib/generators/duckmap/static/USAGE +47 -0
- data/lib/generators/duckmap/static/static_generator.rb +51 -0
- data/lib/generators/duckmap/sync/USAGE +25 -0
- data/lib/generators/duckmap/sync/sync_generator.rb +29 -0
- metadata +96 -0
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module DuckMap
|
4
|
+
|
5
|
+
##################################################################################
|
6
|
+
# NOT empty anymore...
|
7
|
+
# This module is empty on purpose. Sitemap::Mapper will create a sitemap method on this
|
8
|
+
# module when a sitemap is actually created via config/routes.rb. This module is included in the SitemapBaseController
|
9
|
+
# and therefore will have all of the methods defined via config/routes.rb.
|
10
|
+
# Originally, methods were defined directly on SitemapBaseController, however, it was creating
|
11
|
+
# some wierd problems during development. Meaning, if you tried to edit and refresh (Rails standard)
|
12
|
+
# the Rails stack would blow up. Adding the methods to a module and including the module seemed to fix
|
13
|
+
# the problem.
|
14
|
+
module SitemapControllerHelpers
|
15
|
+
|
16
|
+
##################################################################################
|
17
|
+
def sitemap_build(request_path = nil)
|
18
|
+
|
19
|
+
self.sitemap_model = []
|
20
|
+
|
21
|
+
begin
|
22
|
+
|
23
|
+
request_path = request_path.blank? ? request.path : request_path
|
24
|
+
|
25
|
+
sitemap_route = Rails.application.routes.find_sitemap_route(request_path)
|
26
|
+
unless sitemap_route.blank?
|
27
|
+
Rails.application.routes.sitemap_routes(sitemap_route).each do |route|
|
28
|
+
|
29
|
+
begin
|
30
|
+
|
31
|
+
DuckMap.logger.info "processing route: name: #{route.name} controller: #{route.controller_name} action: #{route.action_name}"
|
32
|
+
|
33
|
+
clazz = ClassHelpers.get_controller_class(route.controller_name)
|
34
|
+
|
35
|
+
if clazz.blank?
|
36
|
+
DuckMap.logger.debug "sorry, could not determine controller class...: route name: #{route.name} controller: #{route.controller_name} action: #{route.action_name}"
|
37
|
+
else
|
38
|
+
|
39
|
+
controller_object = clazz.new
|
40
|
+
controller_object.request = request
|
41
|
+
controller_object.response = ActionDispatch::Response.new
|
42
|
+
|
43
|
+
begin
|
44
|
+
|
45
|
+
options = { action_name: route.action_name,
|
46
|
+
controller_name: route.controller_name,
|
47
|
+
model: ClassHelpers.get_model_class(route.controller_name),
|
48
|
+
route: route,
|
49
|
+
source: :sitemap}
|
50
|
+
|
51
|
+
rows = controller_object.sitemap_setup(options)
|
52
|
+
if rows.kind_of?(Array) && rows.length > 0
|
53
|
+
self.sitemap_model.concat(rows)
|
54
|
+
end
|
55
|
+
|
56
|
+
rescue Exception => e
|
57
|
+
DuckMap.logger.exception(e)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
rescue Exception => e
|
63
|
+
DuckMap.logger.exception(e)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
self.sitemap_model.each do |item|
|
70
|
+
unless item[:lastmod].kind_of?(String)
|
71
|
+
item[:lastmod] = item[:lastmod].to_s(:sitemap)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
rescue Exception => e
|
76
|
+
DuckMap.logger.exception(e)
|
77
|
+
end
|
78
|
+
|
79
|
+
return nil
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
##################################################################################
|
85
|
+
module ControllerHelpers
|
86
|
+
extend ActiveSupport::Concern
|
87
|
+
|
88
|
+
##################################################################################
|
89
|
+
# Determines all of the attributes defined for a controller, then, calls the handler method on the controller
|
90
|
+
# to generate and return an Array of Hashes representing all of the url nodes to be included in the sitemap
|
91
|
+
# for the current route being processed.
|
92
|
+
# @return [Array] An Array of Hashes.
|
93
|
+
def sitemap_setup(options = {})
|
94
|
+
rows = []
|
95
|
+
|
96
|
+
DuckMap.logger.debug "sitemap_setup: action_name => #{options[:action_name]} source => #{options[:source]} model => #{options[:model]}"
|
97
|
+
|
98
|
+
attributes = self.sitemap_attributes(options[:action_name])
|
99
|
+
|
100
|
+
DuckMap.logger.debug "sitemap_setup: attributes => #{attributes}"
|
101
|
+
|
102
|
+
if attributes.kind_of?(Hash) && attributes[:handler].kind_of?(Hash) && !attributes[:handler][:action_name].blank?
|
103
|
+
config = {handler: attributes[:handler]}.merge(options)
|
104
|
+
rows = self.send(attributes[:handler][:action_name], config)
|
105
|
+
end
|
106
|
+
|
107
|
+
return rows
|
108
|
+
end
|
109
|
+
|
110
|
+
##################################################################################
|
111
|
+
# Returns the current value of the instance variable {#sitemap_meta_data}.
|
112
|
+
def sitemap_meta_data
|
113
|
+
unless defined?(@sitemap_meta_data)
|
114
|
+
@sitemap_meta_data = {}
|
115
|
+
self.sitemap_setup({action_name: action_name,
|
116
|
+
controller_name: controller_name,
|
117
|
+
route: nil,
|
118
|
+
source: :meta_data})
|
119
|
+
end
|
120
|
+
return @sitemap_meta_data
|
121
|
+
end
|
122
|
+
|
123
|
+
def sitemap_meta_data=(value)
|
124
|
+
@sitemap_meta_data = value
|
125
|
+
end
|
126
|
+
|
127
|
+
##################################################################################
|
128
|
+
def find_first_model_object
|
129
|
+
model_object = self.find_model_object
|
130
|
+
|
131
|
+
if model_object.kind_of?(Array) && model_object.first.kind_of?(ActiveRecord::Base)
|
132
|
+
model_object = model_object.first
|
133
|
+
end
|
134
|
+
|
135
|
+
return model_object
|
136
|
+
end
|
137
|
+
|
138
|
+
##################################################################################
|
139
|
+
def find_model_object
|
140
|
+
model_object = nil
|
141
|
+
candidate = nil
|
142
|
+
skip_vars = ["@_config",
|
143
|
+
"@view_renderer",
|
144
|
+
"@_routes",
|
145
|
+
"@_assigns",
|
146
|
+
"@_request",
|
147
|
+
"@view_flow",
|
148
|
+
"@output_buffer",
|
149
|
+
"@virtual_path"]
|
150
|
+
|
151
|
+
list = self.instance_variables.map.find_all {|x| !skip_vars.include?(x.to_s)}
|
152
|
+
|
153
|
+
list.each do |obj_sym|
|
154
|
+
obj = self.instance_variable_get(obj_sym)
|
155
|
+
if obj
|
156
|
+
if obj.kind_of?(ActiveRecord::Base)
|
157
|
+
model_object = obj
|
158
|
+
break
|
159
|
+
elsif obj.kind_of?(Array) &&
|
160
|
+
obj.first.kind_of?(ActiveRecord::Base) &&
|
161
|
+
candidate.blank?
|
162
|
+
candidate = obj
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
if model_object.blank? && !candidate.blank?
|
168
|
+
model_object = candidate
|
169
|
+
end
|
170
|
+
|
171
|
+
return model_object
|
172
|
+
end
|
173
|
+
|
174
|
+
##################################################################################
|
175
|
+
# Returns the date / time value from config/locale/sitemap.yml associated with the current controller / action.
|
176
|
+
# The static date/times are actual timestamps extracted from the date of the view on disk and from a .git repository if used.
|
177
|
+
# Be sure to run the generator or rake task: duck_map:sync to populate the locale file at: config/locale/sitemap.yml
|
178
|
+
# @return [DateTime] The timestamp associated with the controller / action.
|
179
|
+
def sitemap_static_lastmod(my_controller_name = nil, my_action_name = nil)
|
180
|
+
value = nil
|
181
|
+
|
182
|
+
unless my_controller_name.blank? || my_action_name.blank?
|
183
|
+
|
184
|
+
unless my_controller_name.blank?
|
185
|
+
my_controller_name = my_controller_name.underscore
|
186
|
+
my_controller_name = my_controller_name.gsub("/", ".")
|
187
|
+
end
|
188
|
+
|
189
|
+
begin
|
190
|
+
|
191
|
+
value = I18n.t("#{my_controller_name.downcase}.#{my_action_name.downcase}", default: "", locale: :sitemap)
|
192
|
+
|
193
|
+
rescue Exception => e
|
194
|
+
DuckMap.logger.exception(e)
|
195
|
+
end
|
196
|
+
|
197
|
+
value = value.blank? ? nil : LastMod.to_date(value)
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
return value
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'journey'
|
2
|
+
|
3
|
+
module DuckMap
|
4
|
+
extend ActiveSupport::Autoload
|
5
|
+
|
6
|
+
eager_autoload do
|
7
|
+
|
8
|
+
autoload :ActionViewHelpers, 'duck_map/view_helpers'
|
9
|
+
autoload :ArrayHelper, 'duck_map/array_helper'
|
10
|
+
autoload :Attributes, 'duck_map/attributes'
|
11
|
+
autoload :ClassHelpers, 'duck_map/class_helpers'
|
12
|
+
autoload :Config, 'duck_map/config'
|
13
|
+
autoload :ConfigHelpers, 'duck_map/config'
|
14
|
+
autoload :ControllerHelpers, 'duck_map/controller_helpers'
|
15
|
+
autoload :Expressions, 'duck_map/expressions'
|
16
|
+
autoload :FilterStack, 'duck_map/filter_stack'
|
17
|
+
autoload :Handlers, 'duck_map/handlers/base'
|
18
|
+
autoload :InheritableClassAttributes, 'duck_map/attributes'
|
19
|
+
autoload :LastMod, 'duck_map/last_mod'
|
20
|
+
autoload :List, 'duck_map/list'
|
21
|
+
autoload :Logger, 'duck_map/logger'
|
22
|
+
autoload :Mapper, 'duck_map/mapper'
|
23
|
+
autoload :Model, 'duck_map/model'
|
24
|
+
autoload :Route, 'duck_map/route'
|
25
|
+
autoload :RouteFilter, 'duck_map/route_filter'
|
26
|
+
autoload :RouteSet, 'duck_map/route_set'
|
27
|
+
autoload :SitemapControllerHelpers, 'duck_map/controller_helpers'
|
28
|
+
autoload :SitemapHelpers, 'duck_map/view_helpers'
|
29
|
+
autoload :SitemapObject, 'duck_map/sitemap_object'
|
30
|
+
autoload :Static, 'duck_map/static'
|
31
|
+
autoload :Sync, 'duck_map/sync'
|
32
|
+
autoload :Version, 'duck_map/version'
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class DuckMapEngine < Rails::Engine
|
37
|
+
|
38
|
+
# # this is so I can develop the gem
|
39
|
+
# # run dev.com, make changes to files in lib/duck_captcha, refresh browser.
|
40
|
+
# unless Rails.env.to_sym.eql?(:production)
|
41
|
+
# auto_path_spec = File.expand_path(File.dirname(__FILE__))
|
42
|
+
# config.autoload_paths << auto_path_spec.slice(0, auto_path_spec.rindex("/"))
|
43
|
+
# end
|
44
|
+
|
45
|
+
initializer "duck_map" do
|
46
|
+
Time::DATE_FORMATS.merge!(meta: "%a, %d %b %Y %H:%M:%S %Z",
|
47
|
+
sitemap: "%Y-%m-%dT%H:%M:%S+00:00",
|
48
|
+
sitemap_locale: "%m/%d/%Y %H:%M:%S",
|
49
|
+
seo: "%a, %d %b %Y %H:%M:%S %Z")
|
50
|
+
end
|
51
|
+
|
52
|
+
Journey::Route.send :include, Route
|
53
|
+
|
54
|
+
ActionDispatch::Routing::RouteSet.send :include, RouteSet
|
55
|
+
ActionDispatch::Routing::RouteSet.send :include, RouteFilter
|
56
|
+
|
57
|
+
ActionDispatch::Routing::Mapper.send :include, ConfigHelpers
|
58
|
+
ActionDispatch::Routing::Mapper.send :include, Mapper
|
59
|
+
ActionDispatch::Routing::Mapper.send :include, MapperMethods
|
60
|
+
|
61
|
+
ActiveSupport.on_load(:active_record) do
|
62
|
+
ActiveRecord::Base.send :include, InheritableClassAttributes
|
63
|
+
ActiveRecord::Base.send :include, Attributes
|
64
|
+
ActiveRecord::Base.send :include, SitemapObject
|
65
|
+
end
|
66
|
+
|
67
|
+
ActiveSupport.on_load(:action_controller) do
|
68
|
+
ActionController::Base.send :include, InheritableClassAttributes
|
69
|
+
ActionController::Base.send :include, Attributes
|
70
|
+
ActionController::Base.send :include, ControllerHelpers
|
71
|
+
ActionController::Base.send :include, Handlers::Base
|
72
|
+
ActionController::Base.send :include, Handlers::Index
|
73
|
+
ActionController::Base.send :include, Handlers::Show
|
74
|
+
ActionController::Base.send :include, Model
|
75
|
+
ActionController::Base.send :include, SitemapObject
|
76
|
+
end
|
77
|
+
|
78
|
+
ActiveSupport.on_load(:action_view) do
|
79
|
+
ActionView::Base.send :include, ActionViewHelpers
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.logger
|
85
|
+
return Logger.logger
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.console(msg)
|
89
|
+
logger.console msg
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
# DONE
|
2
|
+
require 'active_support/concern'
|
3
|
+
|
4
|
+
module DuckMap
|
5
|
+
|
6
|
+
##################################################################################
|
7
|
+
class FilterStack
|
8
|
+
|
9
|
+
#DEFAULT_FILTER = {actions: [:new, :create, :edit, :update, :destroy],
|
10
|
+
#verbs: [:post, :put, :delete], names: [], controllers: []}
|
11
|
+
DEFAULT_FILTER = {actions: [:index, :show], verbs: [], names: [], controllers: []}
|
12
|
+
|
13
|
+
##################################################################################
|
14
|
+
def initialize
|
15
|
+
super
|
16
|
+
self.reset
|
17
|
+
end
|
18
|
+
|
19
|
+
##################################################################################
|
20
|
+
# A Hash containing all of the values for exlude sitemap_filters.
|
21
|
+
# @return [Hash]
|
22
|
+
def stack
|
23
|
+
return @stack ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
##################################################################################
|
27
|
+
# Sets the entire Hash for exclude sitemap_filters.
|
28
|
+
# @return [Nil]
|
29
|
+
def stack=(value)
|
30
|
+
@stack = value
|
31
|
+
end
|
32
|
+
|
33
|
+
##################################################################################
|
34
|
+
# Resets the stack.
|
35
|
+
# @return [NilClass]
|
36
|
+
def reset
|
37
|
+
self.stack = [copy_filter(DEFAULT_FILTER)]
|
38
|
+
end
|
39
|
+
|
40
|
+
##################################################################################
|
41
|
+
# Copies a filter
|
42
|
+
# @return [Hash]
|
43
|
+
def copy_filter(filter)
|
44
|
+
buffer = {}
|
45
|
+
filter.each do |part|
|
46
|
+
buffer[part[0]] = part[1].dup
|
47
|
+
end
|
48
|
+
return buffer
|
49
|
+
end
|
50
|
+
|
51
|
+
##################################################################################
|
52
|
+
# Pushes a copy of the current filter onto the end of the stack.
|
53
|
+
# @return [Hash]
|
54
|
+
def push
|
55
|
+
self.stack.push(copy_filter(self.current_filter))
|
56
|
+
end
|
57
|
+
|
58
|
+
##################################################################################
|
59
|
+
# Pops the last item from the stack. However, the list can never be empty, so, it pops
|
60
|
+
# the last item ONLY if the stack has more than ONE item.
|
61
|
+
# @return [Hash]
|
62
|
+
def pop
|
63
|
+
return self.stack.length > 1 ? self.stack.pop : self.current_filter
|
64
|
+
end
|
65
|
+
|
66
|
+
##################################################################################
|
67
|
+
# Returns the current filter. The current filter is ALWAYS the last item in the stack.
|
68
|
+
# @return [Hash]
|
69
|
+
def current_filter
|
70
|
+
return self.stack.last
|
71
|
+
end
|
72
|
+
|
73
|
+
##################################################################################
|
74
|
+
# Sets the entire Hash for the {#current_filter}.
|
75
|
+
# @return [NilClass]
|
76
|
+
def current_filter=(value)
|
77
|
+
self.stack.pop
|
78
|
+
self.stack.push(value)
|
79
|
+
return nil
|
80
|
+
end
|
81
|
+
|
82
|
+
##################################################################################
|
83
|
+
# Adds a value(s) to the {#current_filter}. The filter stack is implemented as an Array of Hashes.
|
84
|
+
# The {#current_filter} will always be a Hash of key/value pairs. Each key represents a type of filter:
|
85
|
+
#
|
86
|
+
# The filter types are:
|
87
|
+
# - :actions
|
88
|
+
# - :verbs
|
89
|
+
# - :names
|
90
|
+
# - controllers
|
91
|
+
#
|
92
|
+
# Each key has an associated Array of Strings or Symbols. The default filter is:
|
93
|
+
#
|
94
|
+
# {actions: [:index, :show], verbs: [:get], names: [], controllers: []}
|
95
|
+
#
|
96
|
+
# The default is to include all routes that have an :action of :index or :show or include routes that have
|
97
|
+
# a verb of :get. Basically, including urls that a search engine would crawl.
|
98
|
+
# The Array of values added to the filter can be mixed. However, the convention is to use Symbols for
|
99
|
+
# :actions and :verbs and use Strings for :names and :controllers. Values are automagically converted to Symbols
|
100
|
+
# if the key is :actions or :verbs.
|
101
|
+
#
|
102
|
+
# include_filter(:actions, :edit) # => {actions: [:index, :show, :edit], verbs: [:get], names: [], controllers: []}
|
103
|
+
# include_filter(:actions, [:edit, :update]) # => {actions: [:index, :show, :edit, :update], verbs: [:get], names: [], controllers: []}
|
104
|
+
# include_filter(:actions, "edit") # => {actions: [:index, :show, :edit], verbs: [:get], names: [], controllers: []}
|
105
|
+
# include_filter(:actions, ["edit", "update"]) # => {actions: [:index, :show, :edit], verbs: [:get], names: [], controllers: []}
|
106
|
+
# include_filter(:actions, [:edit, "update"]) # => {actions: [:index, :show, :edit], verbs: [:get], names: [], controllers: []}
|
107
|
+
# include_filter(:verbs, :post) # => {actions: [:index, :show], verbs: [:get, :post], names: [], controllers: []}
|
108
|
+
#
|
109
|
+
# @overload include_filter(key, value)
|
110
|
+
# @param [Symbol, String] key The type of filter to update. :actions, :verbs, :names, :controllers.
|
111
|
+
# @param [String, Symbol, Array] value A single or Array of items to be added to the filter section specified via key.
|
112
|
+
# @return [NilClass]
|
113
|
+
def include_filter(*args)
|
114
|
+
args.insert(0, :include)
|
115
|
+
return update_filter(*args)
|
116
|
+
end
|
117
|
+
|
118
|
+
##################################################################################
|
119
|
+
# Adds or removes value(s) to or from the {#current_filter}. This method is called by {#include_filter} and {#exclude_filter}.
|
120
|
+
# @overload update_filter(action, key, value)
|
121
|
+
# @param [Symbol, String] action The action to perform: :include or :exclude.
|
122
|
+
# @param [Symbol, String] key The type of filter to update. :actions, :verbs, :names, :controllers.
|
123
|
+
# @param [String, Symbol, Array] value A single or Array of items to be added to the filter section specified via key.
|
124
|
+
# @return [NilClass]
|
125
|
+
def update_filter(*args)
|
126
|
+
|
127
|
+
action = args.shift
|
128
|
+
action = action.kind_of?(Symbol) ? action : action.to_sym
|
129
|
+
|
130
|
+
key = args.shift
|
131
|
+
key = key.kind_of?(Symbol) ? key : key.to_sym
|
132
|
+
|
133
|
+
# list will always be concatenated to the target array
|
134
|
+
list = []
|
135
|
+
|
136
|
+
# build the list array depending on what the user passed to the method
|
137
|
+
args.each do |item|
|
138
|
+
if item.kind_of?(Array) && item.any?
|
139
|
+
list.concat(item)
|
140
|
+
else
|
141
|
+
list.push(item)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# convert all of the items in the list to symbols
|
146
|
+
# for :actions or :verbs
|
147
|
+
if key.eql?(:actions) || key.eql?(:verbs)
|
148
|
+
list.each_with_index do |item, index|
|
149
|
+
unless item.kind_of?(Symbol)
|
150
|
+
list[index] = item.to_sym
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
if action == :include
|
156
|
+
|
157
|
+
# now, simply concatenate the resulting list and make sure the final array is unique
|
158
|
+
self.current_filter[key].concat(list)
|
159
|
+
self.current_filter[key].uniq!
|
160
|
+
|
161
|
+
elsif action == :exclude
|
162
|
+
|
163
|
+
self.current_filter[key].reject! {|item| list.include?(item)}
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
return nil
|
168
|
+
end
|
169
|
+
|
170
|
+
##################################################################################
|
171
|
+
# Removes value(s) from the {#current_filter}. Basically, the opposite of {#include_filter}.
|
172
|
+
# @overload exclude_filter(key, value)
|
173
|
+
# @param [Symbol, String] key The type of filter to update. :actions, :verbs, :names, :controllers.
|
174
|
+
# @param [String, Symbol, Array] value A single or Array of items to be added to the filter section specified via key.
|
175
|
+
# @return [NilClass]
|
176
|
+
def exclude_filter(*args)
|
177
|
+
args.insert(0, :exclude)
|
178
|
+
return update_filter(*args)
|
179
|
+
end
|
180
|
+
|
181
|
+
##################################################################################
|
182
|
+
# Clears all types (:actions, :verbs, :names, :controllers) for the {#current_filter}.
|
183
|
+
# @return [Nil]
|
184
|
+
def clear_filters
|
185
|
+
self.current_filter = {actions: [], verbs: [], names: [], controllers: []}
|
186
|
+
return nil
|
187
|
+
end
|
188
|
+
|
189
|
+
##################################################################################
|
190
|
+
# Clears a single type of filter.
|
191
|
+
# @param [Symbol, String] key The type of filter to update. :actions, :verbs, :names, :controllers.
|
192
|
+
# @return [Nil]
|
193
|
+
def clear_filter(key)
|
194
|
+
key = key.kind_of?(Symbol) ? key : key.to_sym
|
195
|
+
self.current_filter[key] = []
|
196
|
+
return nil
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module DuckMap
|
4
|
+
module Handlers
|
5
|
+
|
6
|
+
autoload :Index, "duck_map/handlers/index"
|
7
|
+
autoload :Show, "duck_map/handlers/show"
|
8
|
+
|
9
|
+
##################################################################################
|
10
|
+
# Base module containing common code for all sitemap handler modules.
|
11
|
+
module Base
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
##################################################################################
|
15
|
+
# Finds the first instance of a model object on the current controller object.
|
16
|
+
# sitemap_first_model will respect the current setting of :first_model. If :first_model
|
17
|
+
# is true, then, it will continue the search and return the first instance of a model object
|
18
|
+
# on the current controller object. Otherwise, it will return nil.
|
19
|
+
#
|
20
|
+
# @param [Hash] handler The handler Hash of a sitemap configuration.
|
21
|
+
# @return [ActiveRecord::Base]
|
22
|
+
def sitemap_first_model(handler = {})
|
23
|
+
value = nil
|
24
|
+
|
25
|
+
begin
|
26
|
+
|
27
|
+
# determine if we are suppose to look for the first model on the current controller.
|
28
|
+
if handler.kind_of?(Hash) && handler[:first_model]
|
29
|
+
|
30
|
+
first_model_object = self.find_first_model_object
|
31
|
+
|
32
|
+
unless first_model_object.blank?
|
33
|
+
value = first_model_object
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
rescue Exception => e
|
39
|
+
# expect this exception to occur EVERYTIME...
|
40
|
+
end
|
41
|
+
|
42
|
+
return value
|
43
|
+
end
|
44
|
+
|
45
|
+
##################################################################################
|
46
|
+
# Returns a copy of the current values held by {DuckMap::Config.attributes}
|
47
|
+
# @return [Hash]
|
48
|
+
def sitemap_defaults(options = {})
|
49
|
+
return DuckMap::Config.copy_attributes
|
50
|
+
end
|
51
|
+
|
52
|
+
##################################################################################
|
53
|
+
# Applies the current url limit to a result set. This is really a helper method used
|
54
|
+
# by all of the handler methods that return a Array of Hashes numbering greater than one.
|
55
|
+
# Handler methods that would normally return one row need not use this helper method.
|
56
|
+
# Use it if you implement a custom handler method.
|
57
|
+
# @param [Array] rows An Array of Hashes representing the contents of a sitemap.
|
58
|
+
# @param [Hash] options The :handler section of a sitemap configuration.
|
59
|
+
# @option options [Symbol] :url_limit An integer limiting the number of rows to return.
|
60
|
+
# @return [Array]
|
61
|
+
def sitemap_url_limit(rows, options = {})
|
62
|
+
|
63
|
+
unless options[:url_limit].blank?
|
64
|
+
if rows.length > options[:url_limit]
|
65
|
+
rows.slice!(options[:url_limit], rows.length)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
return rows
|
70
|
+
end
|
71
|
+
|
72
|
+
##################################################################################
|
73
|
+
# @return [Hash]
|
74
|
+
def sitemap_url_options(options = {})
|
75
|
+
values = {}
|
76
|
+
|
77
|
+
unless options[:url_format].blank?
|
78
|
+
values[:format] = options[:url_format]
|
79
|
+
end
|
80
|
+
|
81
|
+
return values.merge(sitemap_host_options(options))
|
82
|
+
end
|
83
|
+
|
84
|
+
##################################################################################
|
85
|
+
# @return [Hash]
|
86
|
+
def sitemap_host_options(options = {})
|
87
|
+
values = {}
|
88
|
+
|
89
|
+
unless options[:canonical_host].blank?
|
90
|
+
values[:host] = options[:canonical_host]
|
91
|
+
end
|
92
|
+
unless options[:canonical_port].blank?
|
93
|
+
values[:port] = options[:canonical_port]
|
94
|
+
end
|
95
|
+
|
96
|
+
return values
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|