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,146 @@
|
|
1
|
+
module DuckMap
|
2
|
+
|
3
|
+
class SitemapStaticRequest < ActionDispatch::Request
|
4
|
+
end
|
5
|
+
|
6
|
+
class SitemapStaticResponse < ActionDispatch::Response
|
7
|
+
end
|
8
|
+
|
9
|
+
class ActionViewTestObject < ActionView::Base
|
10
|
+
include DuckMap::ActionViewHelpers
|
11
|
+
include DuckMap::SitemapControllerHelpers
|
12
|
+
include DuckMap::Model
|
13
|
+
include DuckMap::SitemapHelpers
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
##################################################################################
|
18
|
+
class Static
|
19
|
+
|
20
|
+
##################################################################################
|
21
|
+
def build(options = {})
|
22
|
+
key = options[:key].blank? ? :all : options[:key].to_s.downcase.to_sym
|
23
|
+
|
24
|
+
begin
|
25
|
+
|
26
|
+
attributes = DuckMap::Config.attributes
|
27
|
+
|
28
|
+
compressed = attributes[:compression].blank? ? :compressed : attributes[:compression]
|
29
|
+
|
30
|
+
# command line override config
|
31
|
+
compressed = options[:compression].blank? ? compressed : options[:compression]
|
32
|
+
|
33
|
+
compressed = compressed.blank? ? :compressed : compressed.to_s.downcase.to_sym
|
34
|
+
compressed = compressed.eql?(:compressed) ? true : false
|
35
|
+
|
36
|
+
static_host = attributes[:static_host].blank? ? attributes[:canonical_host] : attributes[:static_host]
|
37
|
+
|
38
|
+
# command line override config
|
39
|
+
static_host = options[:static_host].blank? ? static_host : options[:static_host]
|
40
|
+
|
41
|
+
static_port = attributes[:static_port].blank? ? attributes[:canonical_port] : attributes[:static_port]
|
42
|
+
|
43
|
+
# command line override config
|
44
|
+
static_port = options[:static_port].blank? ? static_port : options[:static_port]
|
45
|
+
|
46
|
+
static_target = attributes[:static_target].blank? ? File.join(Rails.root, "public") : attributes[:static_target]
|
47
|
+
|
48
|
+
# command line override config
|
49
|
+
static_target = options[:static_target].blank? ? static_target : options[:static_target]
|
50
|
+
|
51
|
+
if !static_host.blank?
|
52
|
+
|
53
|
+
request_options = {
|
54
|
+
"rack.input" => StringIO.new,
|
55
|
+
"rack.errors" => StringIO.new,
|
56
|
+
"rack.multithread" => true,
|
57
|
+
"rack.multiprocess" => true,
|
58
|
+
"rack.run_once" => false,
|
59
|
+
"CONTENT_TYPE" => "application/xml",
|
60
|
+
"HTTP_HOST" => static_host,
|
61
|
+
"SERVER_PORT" => static_port}
|
62
|
+
|
63
|
+
DuckMap.console "Searching for route: #{key}"
|
64
|
+
|
65
|
+
routes = []
|
66
|
+
if key.eql?(:all)
|
67
|
+
|
68
|
+
routes = Rails.application.routes.sitemap_routes_only
|
69
|
+
|
70
|
+
else
|
71
|
+
|
72
|
+
route = Rails.application.routes.find_route_via_name("#{key}_sitemap")
|
73
|
+
if route.blank?
|
74
|
+
DuckMap.console "Unable to find route: #{key}"
|
75
|
+
else
|
76
|
+
routes.push(route)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
routes.each do |route|
|
82
|
+
|
83
|
+
DuckMap.console "Processing route: #{route.name}"
|
84
|
+
|
85
|
+
clazz = ClassHelpers.get_controller_class(route.controller_name)
|
86
|
+
|
87
|
+
if clazz.blank?
|
88
|
+
DuckMap.logger.debug "sorry, could not determine controller class...: route name: #{route.name} controller: #{route.controller_name} action: #{route.action_name}"
|
89
|
+
else
|
90
|
+
|
91
|
+
controller = clazz.new
|
92
|
+
|
93
|
+
controller.request = SitemapStaticRequest.new(request_options)
|
94
|
+
controller.response = SitemapStaticResponse.new
|
95
|
+
|
96
|
+
# man, I am getting lazy...
|
97
|
+
request_path = route.path.spec.to_s.gsub(":format", "xml")
|
98
|
+
|
99
|
+
controller.sitemap_build(request_path)
|
100
|
+
|
101
|
+
view = ActionViewTestObject.new(File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "app", "views")))
|
102
|
+
|
103
|
+
view.controller = controller
|
104
|
+
|
105
|
+
view.assign(sitemap_model: controller.sitemap_model)
|
106
|
+
|
107
|
+
parts = request_path.split("/")
|
108
|
+
parts.insert(0, static_target)
|
109
|
+
|
110
|
+
file_spec = File.join(parts)
|
111
|
+
|
112
|
+
File.open(file_spec, "w") do |file|
|
113
|
+
|
114
|
+
file.write view.render(:template => "sitemap/default_template.xml.erb")
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
if compressed
|
119
|
+
|
120
|
+
Zlib::GzipWriter.open("#{file_spec}.gz") do |gz|
|
121
|
+
gz.mtime = File.mtime(file_spec)
|
122
|
+
gz.orig_name = file_spec
|
123
|
+
gz.write IO.binread(file_spec)
|
124
|
+
end
|
125
|
+
|
126
|
+
FileUtils.rm_rf file_spec
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
else
|
135
|
+
DuckMap.console "Sorry, cannot build sitemap. You need to set static_host in config/routes.rb or on the command-line..."
|
136
|
+
end
|
137
|
+
|
138
|
+
rescue Exception => e
|
139
|
+
puts "#{e.message}"
|
140
|
+
puts e.backtrace
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
module DuckMap
|
2
|
+
|
3
|
+
##################################################################################
|
4
|
+
# Extracts the timestamp of each action for all of the controllers within the application
|
5
|
+
# and stores it in config/locales/sitemap.yml
|
6
|
+
class Sync
|
7
|
+
|
8
|
+
##################################################################################
|
9
|
+
# Extract and store timestamps for all of the actions in the in app.
|
10
|
+
# @param [Hash] options An options Hash passed to the generator via the command line.
|
11
|
+
# returns [Nil]
|
12
|
+
def build(options = {})
|
13
|
+
DuckMap.logger.info "\r\n\r\n====================================================================="
|
14
|
+
DuckMap.logger.info "#{self.class.name} session begin at: #{Time.now}"
|
15
|
+
DuckMap.logger.info "options: #{options}"
|
16
|
+
|
17
|
+
verbose = options[:verbose].blank? ? false : true
|
18
|
+
|
19
|
+
# always replace ALL of the existing content, so, the list is always current.
|
20
|
+
# actions / views may have been deleted, renamed, etc.
|
21
|
+
content = {sitemap: {}}
|
22
|
+
grand_total = 0
|
23
|
+
|
24
|
+
# controllers full physical path for the current app.
|
25
|
+
base_dir = File.join(Rails.root, "app", "controllers").to_s
|
26
|
+
|
27
|
+
# this is a little bit complex.
|
28
|
+
# - traverse the entire directory structure for controllers.
|
29
|
+
# - for each
|
30
|
+
# - inline gsub! to remove the base_dir.
|
31
|
+
# - inline gsub! to remove _controller.
|
32
|
+
# - then, prevent the application controller from making it into the list as
|
33
|
+
# there should not be any actions / views for the application controller.
|
34
|
+
|
35
|
+
|
36
|
+
list = Dir["#{File.join(base_dir, "**", "*.rb")}"].each {|f| f.gsub!("#{base_dir}/", "").gsub!("_controller.rb", "")}.map.find_all {|x| x.eql?("application") ? false : true}
|
37
|
+
|
38
|
+
DuckMap.console "Total number of controllers found within the app: #{list.length}"
|
39
|
+
DuckMap.console "Views Controller"
|
40
|
+
DuckMap.console "-------------------------------------------------------------"
|
41
|
+
|
42
|
+
DuckMap.logger.show_console = verbose ? true : false
|
43
|
+
|
44
|
+
list.each do |controller|
|
45
|
+
|
46
|
+
file_spec = File.join("app", "views", controller)
|
47
|
+
|
48
|
+
clazz = "#{controller}_controller".camelize.constantize
|
49
|
+
|
50
|
+
DuckMap.console "===================================================================================="
|
51
|
+
DuckMap.console "controller: #{controller.ljust(30)} path: #{file_spec}"
|
52
|
+
|
53
|
+
actions = {}
|
54
|
+
methods = clazz.action_methods
|
55
|
+
|
56
|
+
methods.each do |action|
|
57
|
+
|
58
|
+
latest_timestamp = nil
|
59
|
+
winner = nil
|
60
|
+
|
61
|
+
DuckMap.console " action: #{action}"
|
62
|
+
|
63
|
+
Dir["#{File.join(file_spec, action)}.html.*"].each do |view|
|
64
|
+
|
65
|
+
begin
|
66
|
+
view_timestamp = File.stat(File.join(Rails.root, view)).mtime
|
67
|
+
if view_timestamp.blank?
|
68
|
+
DuckMap.console " : cannot stat file: #{view}"
|
69
|
+
else
|
70
|
+
|
71
|
+
if latest_timestamp.blank? || view_timestamp > latest_timestamp
|
72
|
+
latest_timestamp = view_timestamp
|
73
|
+
winner = "timestamp from file"
|
74
|
+
DuckMap.console " : Using file timestamp? YES #{view}"
|
75
|
+
DuckMap.console " : file timestamp #{view_timestamp} greater than: #{latest_timestamp}"
|
76
|
+
else
|
77
|
+
DuckMap.console " : Using file timestamp? NO #{view}"
|
78
|
+
DuckMap.console " : file timestamp #{view_timestamp} less than: #{latest_timestamp}"
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
rescue Exception => e
|
83
|
+
DuckMap.logger.debug "#{e}"
|
84
|
+
end
|
85
|
+
|
86
|
+
begin
|
87
|
+
output = %x(git log --format='%ci' -- #{view} | head -n 1)
|
88
|
+
if output.blank?
|
89
|
+
DuckMap.console " : cannot get date from GIT for file: #{view}"
|
90
|
+
else
|
91
|
+
|
92
|
+
view_timestamp = LastMod.to_date(output)
|
93
|
+
if latest_timestamp.blank? || view_timestamp > latest_timestamp
|
94
|
+
latest_timestamp = view_timestamp
|
95
|
+
winner = "timestamp from GIT"
|
96
|
+
DuckMap.console " : Using GIT timestamp? YES #{view}"
|
97
|
+
DuckMap.console " : file timestamp #{view_timestamp} greater than: #{latest_timestamp}"
|
98
|
+
else
|
99
|
+
DuckMap.console " : Using GIT timestamp? NO #{view}"
|
100
|
+
DuckMap.console " : file timestamp #{view_timestamp} less than: #{latest_timestamp}"
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
rescue Exception => e
|
105
|
+
DuckMap.logger.debug "#{e}"
|
106
|
+
end
|
107
|
+
|
108
|
+
begin
|
109
|
+
view_timestamp = LastMod.to_date(I18n.t("#{controller.gsub("/", ".")}.#{action}", :locale => :sitemap))
|
110
|
+
|
111
|
+
if view_timestamp.blank?
|
112
|
+
DuckMap.console " : cannot find item in locale sitemap.yml for file: #{view}"
|
113
|
+
else
|
114
|
+
|
115
|
+
view_timestamp = LastMod.to_date(output)
|
116
|
+
if latest_timestamp.blank? || view_timestamp > latest_timestamp
|
117
|
+
latest_timestamp = view_timestamp
|
118
|
+
winner = "timestamp from locale sitemap.yml"
|
119
|
+
DuckMap.console " : Using locale timestamp? YES #{view}"
|
120
|
+
DuckMap.console " : file timestamp #{view_timestamp} greater than: #{latest_timestamp}"
|
121
|
+
else
|
122
|
+
DuckMap.console " : Using locale timestamp? NO #{view}"
|
123
|
+
DuckMap.console " : file timestamp #{view_timestamp} less than: #{latest_timestamp}"
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
rescue Exception => e
|
129
|
+
DuckMap.logger.debug "#{e}"
|
130
|
+
end
|
131
|
+
|
132
|
+
DuckMap.console " : winner #{winner}"
|
133
|
+
|
134
|
+
begin
|
135
|
+
actions.merge!(action => latest_timestamp.strftime("%m/%d/%Y %H:%M:%S"))
|
136
|
+
rescue Exception => e
|
137
|
+
DuckMap.logger.debug "#{e}"
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# add all of the actions found for the current controller to the :sitemap section of the yaml file.
|
144
|
+
if actions.length > 0
|
145
|
+
grand_total += actions.length
|
146
|
+
namespaces = controller.split("/")
|
147
|
+
content[:sitemap] = merge_controller(content[:sitemap], namespaces, 0, actions)
|
148
|
+
|
149
|
+
DuckMap.logger.show_console = true
|
150
|
+
DuckMap.console "#{actions.length.to_s.rjust(5)} #{controller}"
|
151
|
+
DuckMap.logger.show_console = verbose ? true : false
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
DuckMap.logger.show_console = true
|
158
|
+
DuckMap.console "\r\nTotal number of views synchronized: #{grand_total}\r\n"
|
159
|
+
DuckMap.logger.info "#{self.class.name} session end at: #{Time.now}"
|
160
|
+
DuckMap.logger.info "---------------------------------------------------------------------"
|
161
|
+
|
162
|
+
# done.
|
163
|
+
write_config(content)
|
164
|
+
DuckMap.console "done."
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
##################################################################################
|
169
|
+
# Recursive method
|
170
|
+
def merge_controller(content, namespaces, index, values = {})
|
171
|
+
|
172
|
+
if (index == (namespaces.length - 1))
|
173
|
+
content[namespaces[index]] = {} unless content.has_key?(namespaces[index])
|
174
|
+
content[namespaces[index]].merge!(values)
|
175
|
+
else
|
176
|
+
content[namespaces[index]] = {} unless content.has_key?(namespaces[index])
|
177
|
+
content[namespaces[index]] = merge_controller(content[namespaces[index]], namespaces, index + 1, values)
|
178
|
+
end
|
179
|
+
return content
|
180
|
+
end
|
181
|
+
|
182
|
+
##################################################################################
|
183
|
+
def write_config(values = {})
|
184
|
+
File.open(File.join(Rails.root, "config", "locales", "sitemap.yml"), "w") do |file|
|
185
|
+
file.puts "# Although this file is automatically generated, it is ok to edit."
|
186
|
+
YAML.dump(values, file)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# DONE
|
2
|
+
require 'active_support/concern'
|
3
|
+
|
4
|
+
module DuckMap
|
5
|
+
|
6
|
+
##################################################################################
|
7
|
+
# Contains methods for generating the contants of a sitemap.
|
8
|
+
module SitemapHelpers
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
##################################################################################
|
12
|
+
# View helper method to generate the content of a sitemap. Loops through all of the current
|
13
|
+
# Hashes contained in {DuckMap::Model#sitemap_model}.
|
14
|
+
# @param [Block] A block to execute for each row contained in {DuckMap::Model#sitemap_model}.
|
15
|
+
#
|
16
|
+
#
|
17
|
+
# To see it in action, have a look at the file.
|
18
|
+
#
|
19
|
+
# /app/views/sitemap/default_template.xml.erb
|
20
|
+
#
|
21
|
+
# @return [NilClass]
|
22
|
+
def sitemap_content(&block)
|
23
|
+
|
24
|
+
if defined?(self.sitemap_model) && self.sitemap_model.kind_of?(Array)
|
25
|
+
|
26
|
+
self.sitemap_model.each do |row|
|
27
|
+
block.call(row)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
return nil
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
##################################################################################
|
38
|
+
# Support for seo related meta tags in page headers.
|
39
|
+
module ActionViewHelpers
|
40
|
+
extend ActiveSupport::Concern
|
41
|
+
|
42
|
+
##################################################################################
|
43
|
+
# Generates a title tag for use inside HTML header area.
|
44
|
+
# @return [String] HTML safe title tag.
|
45
|
+
def sitemap_meta_title
|
46
|
+
return controller.sitemap_meta_data[:title].blank? ? nil : content_tag(:title, controller.sitemap_meta_data[:title], false)
|
47
|
+
end
|
48
|
+
|
49
|
+
def sitemap_meta_title=(value)
|
50
|
+
controller.sitemap_meta_data[:title] = value
|
51
|
+
end
|
52
|
+
|
53
|
+
##################################################################################
|
54
|
+
# Generates a keywords meta tag for use inside HTML header area.
|
55
|
+
# @return [String] HTML safe keywords meta tag.
|
56
|
+
def sitemap_meta_keywords
|
57
|
+
return controller.sitemap_meta_data[:keywords].blank? ? nil : tag(:meta, {name: :keywords, content: controller.sitemap_meta_data[:keywords]}, false, false)
|
58
|
+
end
|
59
|
+
|
60
|
+
def sitemap_meta_keywords=(value)
|
61
|
+
controller.sitemap_meta_data[:keywords] = value
|
62
|
+
end
|
63
|
+
|
64
|
+
##################################################################################
|
65
|
+
# Generates a description meta tag for use inside HTML header area.
|
66
|
+
# @return [String] HTML safe description meta tag.
|
67
|
+
def sitemap_meta_description
|
68
|
+
return controller.sitemap_meta_data[:description].blank? ? nil : tag(:meta, {name: :description, content: controller.sitemap_meta_data[:description]}, false, false)
|
69
|
+
end
|
70
|
+
|
71
|
+
def sitemap_meta_description=(value)
|
72
|
+
controller.sitemap_meta_data[:description] = value
|
73
|
+
end
|
74
|
+
|
75
|
+
##################################################################################
|
76
|
+
# Generates a Last-Modified meta tag for use inside HTML header area.
|
77
|
+
# @return [String] HTML safe Last-Modified meta tag.
|
78
|
+
def sitemap_meta_lastmod
|
79
|
+
return controller.sitemap_meta_data[:lastmod].blank? ? nil : tag(:meta, {name: "Last-Modified", content: controller.sitemap_meta_data[:lastmod]}, false, false)
|
80
|
+
end
|
81
|
+
|
82
|
+
def sitemap_meta_lastmod=(value)
|
83
|
+
controller.sitemap_meta_data[:lastmod] = value
|
84
|
+
end
|
85
|
+
|
86
|
+
##################################################################################
|
87
|
+
# Generates a canonical link tag for use inside HTML header area.
|
88
|
+
# @return [String] HTML safe canonical link tag.
|
89
|
+
def sitemap_meta_canonical
|
90
|
+
return controller.sitemap_meta_data[:canonical].blank? ? nil : tag(:link, {rel: :canonical, href: controller.sitemap_meta_data[:canonical]}, false, false)
|
91
|
+
end
|
92
|
+
|
93
|
+
def sitemap_meta_canonical=(value)
|
94
|
+
controller.sitemap_meta_data[:canonical] = value
|
95
|
+
end
|
96
|
+
|
97
|
+
##################################################################################
|
98
|
+
# Generates a meta tags title, keywords, description and Last-Modified for use inside HTML header area.
|
99
|
+
# @return [String] HTML safe title tag.
|
100
|
+
def sitemap_meta_tag
|
101
|
+
buffer = "#{self.sitemap_meta_title}\r\n #{self.sitemap_meta_keywords}\r\n #{self.sitemap_meta_description}\r\n #{self.sitemap_meta_lastmod}\r\n #{self.sitemap_meta_canonical}\r\n".html_safe
|
102
|
+
return buffer.html_safe
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
data/lib/duck_map.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Description:
|
2
|
+
|
3
|
+
Lists all of the sitemap route(s) configured via config/routes.rb
|
4
|
+
|
5
|
+
You have the option of including the route(s) contained within a sitemap. This can be helpful for debugging.
|
6
|
+
|
7
|
+
If you specify a single route name, then, displaying the route(s) contained within the sitemap is implied and
|
8
|
+
|
9
|
+
overrides the --contents option.
|
10
|
+
|
11
|
+
Example:
|
12
|
+
|
13
|
+
# Lists all of the sitemap route(s) configured via config/routes.rb
|
14
|
+
|
15
|
+
rails g duckmap:sitemaps
|
16
|
+
|
17
|
+
# Lists all of the sitemap route(s) configured via config/routes.rb including route(s) contained in each sitemap route.
|
18
|
+
|
19
|
+
rails g duckmap:sitemaps --contents
|
20
|
+
|
21
|
+
# Lists the route(s) contained within sitemap route named mysitemap.
|
22
|
+
|
23
|
+
rails g duckmap:sitemaps mysitemap
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "rails/generators"
|
2
|
+
|
3
|
+
module Duckmap
|
4
|
+
module Generators
|
5
|
+
|
6
|
+
class SitemapsGenerator < Rails::Generators::Base
|
7
|
+
|
8
|
+
argument :key,
|
9
|
+
banner: "[sitemap route name]",
|
10
|
+
desc: "[sitemap route name]",
|
11
|
+
default: :all,
|
12
|
+
required: false,
|
13
|
+
optional: true
|
14
|
+
|
15
|
+
class_option :contents, desc: "Include the routes contained in a sitemap"
|
16
|
+
|
17
|
+
def self.source_root
|
18
|
+
File.join(File.dirname(__FILE__), "templates")
|
19
|
+
end
|
20
|
+
|
21
|
+
def build
|
22
|
+
|
23
|
+
config = {key: key}
|
24
|
+
|
25
|
+
unless options[:contents].blank?
|
26
|
+
config[:contents] = options[:contents]
|
27
|
+
end
|
28
|
+
|
29
|
+
DuckMap::List.new.build(config)
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
Description:
|
2
|
+
|
3
|
+
Generates a sitemap(s) based on :key. The default key is: all
|
4
|
+
|
5
|
+
Key is the route name of a sitemap route defined in config/routes.rb
|
6
|
+
|
7
|
+
To list all of the available sitemaps including name and contents use: rails g duckmap:sitemaps
|
8
|
+
|
9
|
+
You can override the static_host and static_port settings in config/routes.rb by passing them
|
10
|
+
|
11
|
+
to the generator on the command line.
|
12
|
+
|
13
|
+
Also, you can specify the target base directory to use when writing files. The default target is the public
|
14
|
+
|
15
|
+
directory of your Rails app.
|
16
|
+
|
17
|
+
#{Rails.root}/public/sitemap.xml
|
18
|
+
|
19
|
+
Example:
|
20
|
+
|
21
|
+
# generates all sitemaps configured via config/routes.rb
|
22
|
+
|
23
|
+
rails g duckmap:static
|
24
|
+
|
25
|
+
- or -
|
26
|
+
|
27
|
+
rails g duckmap:static all
|
28
|
+
|
29
|
+
# generates a specific sitemap using the route name.
|
30
|
+
|
31
|
+
rails g duckmap:static mysitemap
|
32
|
+
|
33
|
+
# overrides static_host and static_port defined in config/routes.rb
|
34
|
+
|
35
|
+
rails g duckmap:static mysitemap --static-host=example.com --static-port=8080
|
36
|
+
|
37
|
+
# generates and compresses the output file(s). Overrides setting in config/routes.rb
|
38
|
+
|
39
|
+
rails g duckmap:static mysitemap --compression=compressed
|
40
|
+
|
41
|
+
# disables compression for the output file(s). Overrides setting in config/routes.rb
|
42
|
+
|
43
|
+
rails g duckmap:static mysitemap --compression=none
|
44
|
+
|
45
|
+
# generates sitemap files in a specific target directory
|
46
|
+
|
47
|
+
rails g duckmap:static mysitemap --static-target=/tmp/mysitemaps
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "rails/generators"
|
2
|
+
|
3
|
+
module Duckmap
|
4
|
+
module Generators
|
5
|
+
|
6
|
+
class StaticGenerator < Rails::Generators::Base
|
7
|
+
|
8
|
+
argument :key,
|
9
|
+
banner: "[sitemap route name]",
|
10
|
+
desc: "[sitemap route name]",
|
11
|
+
default: :all,
|
12
|
+
required: false,
|
13
|
+
optional: true
|
14
|
+
|
15
|
+
class_option :compression, desc: "Indicates if the generated file(s) should be compressed"
|
16
|
+
class_option :static_host, desc: "Static hostname to use when building <url><loc> nodes"
|
17
|
+
class_option :static_port, desc: "Static port to use when building <url><loc> nodes"
|
18
|
+
class_option :static_target, desc: "Target base directory to write sitemap files."
|
19
|
+
|
20
|
+
def self.source_root
|
21
|
+
File.join(File.dirname(__FILE__), "templates")
|
22
|
+
end
|
23
|
+
|
24
|
+
def build
|
25
|
+
|
26
|
+
config = {key: key}
|
27
|
+
|
28
|
+
unless options[:compression].blank?
|
29
|
+
config[:compression] = options[:compression]
|
30
|
+
end
|
31
|
+
|
32
|
+
unless options[:static_host].blank?
|
33
|
+
config[:static_host] = options[:static_host]
|
34
|
+
end
|
35
|
+
|
36
|
+
unless options[:static_port].blank?
|
37
|
+
config[:static_port] = options[:static_port]
|
38
|
+
end
|
39
|
+
|
40
|
+
unless options[:static_target].blank?
|
41
|
+
config[:static_target] = options[:static_target]
|
42
|
+
end
|
43
|
+
|
44
|
+
DuckMap::Static.new.build(config)
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Description:
|
2
|
+
|
3
|
+
Synchronizes date/time stamps of all views for a Rails app.
|
4
|
+
|
5
|
+
There are three sources of timestamps for views.
|
6
|
+
|
7
|
+
- The physical timestamp of the view file on disk.
|
8
|
+
|
9
|
+
- The timestamp of the view found in the local Git repo for the app.
|
10
|
+
|
11
|
+
- The last known timestamp already stored in config/locales/sitemaps.yml
|
12
|
+
|
13
|
+
All three sources are compared and the source that has the latest timestamp wins and that value
|
14
|
+
|
15
|
+
is stored in config/locales/sitemaps.yml
|
16
|
+
|
17
|
+
Example:
|
18
|
+
|
19
|
+
# Performs a synchronization
|
20
|
+
|
21
|
+
rails g duckmap:sync
|
22
|
+
|
23
|
+
# Performs a synchronization and shows all activity
|
24
|
+
|
25
|
+
rails g duckmap:sync --verbose
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "rails/generators"
|
2
|
+
|
3
|
+
module Duckmap
|
4
|
+
module Generators
|
5
|
+
|
6
|
+
class SyncGenerator < Rails::Generators::Base
|
7
|
+
|
8
|
+
class_option :verbose, desc: "Show all operations"
|
9
|
+
|
10
|
+
def self.source_root
|
11
|
+
File.join(File.dirname(__FILE__), "templates")
|
12
|
+
end
|
13
|
+
|
14
|
+
def build
|
15
|
+
|
16
|
+
config = {}
|
17
|
+
|
18
|
+
unless options[:verbose].blank?
|
19
|
+
config[:verbose] = options[:verbose]
|
20
|
+
end
|
21
|
+
|
22
|
+
DuckMap::Sync.new.build(config)
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|