Module: DuckMap::SitemapObject::ClassMethods

Defined in:
lib/duck_map/sitemap_object.rb

Instance Method Summary collapse

Instance Method Details

#acts_as_sitemap(action_name = nil, options = {}, &block) ⇒ Nil

Note:

The syntax is always the same regardless if you define acts_as_sitemap in config/routes.rb or directly on a controller or model.

Sets default values, attributes and mappings for sitemap objects. All SitemapObject attributes are maintained in a master Hash. Attributes for each action are stored in the master Hash and accessed via action_name as the key.

All attributes are broken into two categories.

  • Configuration level: These attributes are defined within the config/routes.rb block and are considered global default values for ALL sitemap related classes and objects.

  • Controller level: These attributes are exactly the same as Configuration level with one difference. They apply to each controller class ONLY. Setting attributes at the controller level will make a copy of the Configuration level attributes and merge with the values you pass to acts_as_sitemap.

When a sitemap is created or meta tag data is needed, the controller is “asked” to provide the required data for a specific action on the controller. The mechanism that makes the request is called a “handler”. Handlers are mapped to standard Rails controller actions.

  • The index action is mapped to sitemap_index.

  • The show action is mapped to sitemap_show.

Attributes have two meanings:

  • If the attribute value is set to a Symbol, then, it is considered to point to an attribute/method name of the target SitemapObject (self).

  • If the attribute value is set to anything other than a Symbol, then, the value is used “as is”.

In the example below, we are setting meta data attributes.

acts_as_sitemap :index, title: "List of my pages..."    #=> static title for the index page.
acts_as_sitemap :edit,  title: :title                   #=> returns the value of the title attribute/method.
acts_as_sitemap :new,   title: "New page"               #=> static title for the new page.
acts_as_sitemap :show,  title: :title                   #=> returns the value of the title attribute/method.

Here, we are setting sitemap attributes.

acts_as_sitemap :index, changefreq: "always",   priority: "1.0"
acts_as_sitemap :edit,  changefreq: "never",    priority: "0.0"
acts_as_sitemap :new,   changefreq: "never",    priority: "0.0"
acts_as_sitemap :show,  changefreq: "monthly",  priority: "7.0"

# here we are telling ALL handlers to get the last modified date
# for a sitemap and meta tag from 
acts_as_sitemap lastmod: :last_updated_at

The sitemap / meta tag handlers will attempt to extract attributes values from the first model found on a controller. To make meeting special needs a little easier, you can use a block to return a single model or an Array of model objects to include in your sitemap.

This example is worth a few extra words.

  • When building a sitemap for the index action of a controller, you only need to build one url.

  • When building a sitemap for the show action of a controller, you will typically need to build an entire set of urls to represent the rows in your table. However, when showing the meta tag data, you will need the attributes from the specific model for the current page.

    acts_as_sitemap :index do
      Book.where(title: "my latest book").first
    end
    
    acts_as_sitemap :show do
      Book.all
    end
    

Let’s say you the show action of your controller just won’t fit into the standard behavior and you need to build the url using a custom method. Simply build the method on your object and point to it.

acts_as_sitemap :show, canonical: :my_special_method

The full syntax would include handlers and segments.

acts_as_sitemap :index, title: "My App",
                        changefreq: "always",
                        priority: "1.0",
                        handler: {action_name: :my_index, first_model: false},
                        segments: {id: :my_id, sub_id: :belongs_to_id}

However, there are convenience methods to make things a little cleaner.

acts_as_sitemap  :index, title: "My App", changefreq: "always", priority: "1.0"
sitemap_handler  :index, action_name: :my_index, first_model: false
sitemap_segments :index, id: :my_id, sub_id: :belongs_to_id

So far, we have only discussed the attributes that are used by the standard handlers. However, you do have the option of building and using your own handlers to meet special needs or to completely change the default behavior of ALL handlers. Let’s say the default behavior for the index handler does not meet your needs. You could build your own index handler and set it in the config/routes.rb

MyApp::Application.routes.draw do

  # defining attributes in config/routes.rb are used globally
  # your action handler method will be used throughout the entire app.
  # simply create your own handler method and make it accessible to every controller
  # in your app.  Maybe include in your ApplicationController or something.
  sitemap_handler :index, action_name: :my_index

end

Parameters:

  • action_name (String, Symbol) (defaults to: nil)

    The action name is used as a key when looking for attributes. When sitemap or meta tag needs data for the index action it will use :index as the key. Omitting the action_name will default to :all which will assign the values you pass to “all” actions for the controller.

  • options (Hash) (defaults to: {})

    Options hash.

    • Setting to a Symbol will attempt to access attribute method name on the SitemapObject itself.

    • Setting to any value other than a Symbol will use that value “as is”.

  • block (Block)

    A block to assign to all handlers associated with action_name. The block should return an Array of ActiveRecord::Base models. The model objects server as sitemap content for the given action name.

Options Hash (options):

  • :canonical (Symbol)

    Default value: nil

  • :canonical_host (Symbol)

    Default value: nil

  • :changefreq (Symbol)

    Valid static values are:

    • always

    • hourly

    • daily

    • weekly

    • monthly

    • yearly

    • never

  • :description (Symbol)

    Default value: :description

  • :handler (Symbol)

    Sub-hash containing attributes for the handler. See sitemap_handler

  • :keywords (Symbol)

    Default value: :keywords

  • :lastmod (Symbol)

    Default value: :updated_at

  • :priority (Symbol)

    Valid static values range from 0.0 to 1.0

  • :segments (Symbol)

    Sub-hash containing attributes for the segments. See sitemap_segments

  • :title (Symbol)

    Default value: :title

  • :url_format (Symbol)

    Default value: “html”

  • :url_limit (Symbol)

    Default value: 50000

Returns:

  • (Nil)


142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/duck_map/sitemap_object.rb', line 142

def acts_as_sitemap(*args, &block)
  key = :all

  self.sitemap_attributes_defined = true

  if args.length > 0

    if args.first.kind_of?(Symbol)
      key = args.shift

    elsif args.first.kind_of?(String)
      key = args.shift.to_sym

    end

  end

  values = args.first.kind_of?(Hash) ? args.first : {}

  # delete method should always return nil if the key doesn't exist
  handler = values.delete(:handler)
  segments = values.delete(:segments)

  # i'm going to verify and set a default anyway
  handler = handler.kind_of?(Hash) ? handler : {}

  segments = segments.kind_of?(Hash) ? segments : {}

  # build a list of keys to work on
  # developer can specify :all, which will build a list of all the existing keys in the Hash
  # otherwise, it will just use the key passed to acts_as_sitemap
  keys = []
  if key == :all
    self.sitemap_attributes.each {|pair| keys.push(pair.first)}
  else
    keys.push(key)
  end

  if values[:lastmod].kind_of?(String)
    begin

      buffer = LastMod.to_date(values[:lastmod])
      if buffer.kind_of?(Time)
        values[:lastmod] = buffer
      end

    rescue Exception => e
      # TODO logging
    end
  end

  # process all of the keys in the list.
  keys.each do |key|

    # create defaults unless they exist
    unless self.sitemap_attributes[key].kind_of?(Hash)
      self.sitemap_attributes[key] = {}
    end

    unless self.sitemap_attributes[key][:handler].kind_of?(Hash)
      self.sitemap_attributes[key][:handler] = {}
    end

    unless self.sitemap_attributes[key][:segments].kind_of?(Hash)
      self.sitemap_attributes[key][:segments] = {}
    end

    # merge the main hash.
    self.sitemap_attributes[key].merge!(values)

    # merge the handler
    #unless handler.blank?
    if handler.kind_of?(Hash)

      if block_given?

        handler[:block] = block
      end

      self.sitemap_attributes[key][:handler].merge!(handler)

    end

    # merge the segments
    unless segments.blank?

      self.sitemap_attributes[key][:segments].merge!(segments)

    end

  end

  return nil
end

#sitemap_handler(action_name = nil, options = {}, &block) ⇒ NilClass

Note:

See Handlers for specific details on how each one of these attributes are utilized by each handler.

Wrapper for acts_as_sitemap and accepts the same exact arguments. Basically, sitemap_handler simplifies the syntax needed to define a handler for all or a specific action.

sitemap_handler :index, action_name: :my_index, first_model: false

# is equivalent to:
acts_as_sitemap :index, handler: {action_name: :my_index}

sitemap_handler :index, instance_var: :my_var
sitemap_handler :index, instance_var: "my_var"

sitemap_handler :index, model: Book
sitemap_handler :index, model: "Book"

Parameters:

  • action_name (String, Symbol) (defaults to: nil)

    The action name. See acts_as_sitemap

  • options (Hash) (defaults to: {})

    Options hash.

Options Hash (options):

  • :action_name (Symbol)

    The method name to call. Method name MUST exist on your object!

  • :first_model (Symbol)

    Boolean. Tells the handler to get values from the first available model object found on the controller.

  • :instance_var (Symbol)

    The model

  • :model (Symbol)

    A model object expressed as a String or an actual class reference. See Handlers for details on how this attribute is utilized.

Returns:

  • (NilClass)


267
268
269
270
271
272
# File 'lib/duck_map/sitemap_object.rb', line 267

def sitemap_handler(*args, &block)
  key = args.first.kind_of?(Symbol) ? args.shift : :all
  options = args.first.kind_of?(Hash) ? args.shift : {}
  options = args.last.kind_of?(Hash) ? args.pop : options
  return self.acts_as_sitemap(key, handler: options, &block)
end

#sitemap_segments(*args, &block) ⇒ NilClass

Wrapper for acts_as_sitemap and accepts the same exact arguments. Basically, sitemap_segments simplifies the syntax needed to define segments for all or a specific action.

sitemap_segments :index, id: :my_id

# is equivalent to:
acts_as_sitemap :index, segments: {id: :my_id}

Returns:

  • (NilClass)


285
286
287
288
289
290
# File 'lib/duck_map/sitemap_object.rb', line 285

def sitemap_segments(*args, &block)
  key = args.first.kind_of?(Symbol) ? args.shift : :all
  options = args.first.kind_of?(Hash) ? args.shift : {}
  options = args.last.kind_of?(Hash) ? args.pop : options
  return self.acts_as_sitemap(key, segments: options, &block)
end