Module: DuckMap::SitemapObject

Extended by:
ActiveSupport::Concern
Included in:
Config
Defined in:
lib/duck_map/sitemap_object.rb

Overview

Module used to add Sitemap methods and attributes to an object.

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#sitemap_capture_attributes(attributes = {}) ⇒ Object

Returns a Hash containing key/value pairs from the current object.

This method loops through all of the key/value pairs contained in the attributes Hash.

Each pair is inspected.

  • if the value is a Symbol

    • the current object is asked if it has a matching method name matching the value.

      • if true, then, the method is called to obtain a value.

        • if the new value is NOT nil, then, it is paired with the key of the current pair being processed and assigned to the returning Hash.

  • otherwise, if the value is not nil, then, it is considered to be a static value and is assigned to the returning Hash using the key of the current pair being processed.

    # let's pretend this class exists and has the following attributes.
    object = MyObject.new
    object.my_title = "my title"
    object.tags = "this that other"
    object.content = "this is a test"
    object.last_updated_at = Time.now
    
    attributes = {title: :my_title,
                  keywords: nil,
                  description: "this is my desc",
                  lastmod: :invalid_method_name}
    
    values = object.sitemap_capture_attributes(attributes)
    
    puts YAML.dump values        # => {title => "my title", description => "this is my desc"}
    

The result:

  • :my_title is a Symbol and attribute exists on object and value is not nil, so, it is included in the returning Hash.

  • :keywords is nil, so, it is ignored and not included in the returning Hash.

  • :description is a String and considered a static value, so, it is included in the returning Hash “as is”.

  • :my_title is a Symbol, however, a matching attribute/method does NOT exist on the target object, so, it is ignored and not included in the returning Hash.

return [Hash]

Parameters:

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

    Options hash. Can be any combination of key/value pairs (one-dimensional).



333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
# File 'lib/duck_map/sitemap_object.rb', line 333

def sitemap_capture_attributes(attributes = {})
  values = {}

  attributes.each do |pair|

    # if the value of the pair is a Symbol, then, it is implied to be
    # an attribute of the object we are working on.
    # therefore, we will attempt to get the value of that attribute from the object.
    if pair.last.kind_of?(Symbol)

      # if the object has the attribute/method we are looking for, then, capture the value
      # by calling the attribute/method and assign the return value to the return Hash
      # using pair.first as the key.
      if self.respond_to?(pair.last)

        # ask the object for the attribute value
        value = self.send(pair.last)

        # ignore nil values
        unless value.blank?
          values[pair.first] = value
        end

      end

    elsif !pair.last.blank?
      values[pair.first] = pair.last
    end

  end

  return values
end

#sitemap_capture_segments(segment_mappings = {}, segments = []) ⇒ Object

Segment keys are placeholders for the values that are plugged into a named route when it is constructed.

The following Rails route has a two segment keys: :id and :format.

book GET    /books/:id(.:format)   books#show

:id is the row.id of a Book and :format is the extension to be used when constructing a path or url.

book_path(1)                      #=> /book/1
book_path(1, "html")              #=> /book/1.html
book_path(id: 1, format: "html")  #=> /book/1.html
book_path(id: 2, format: "xml")   #=> /book/2.xml

sitemap_capture_segments attempts to populate a Hash with values associated with the required segment keys.

row = Book.create(title: "Duck is a self-proclaimed resident moron...")
puts row.id                                #=> 1
row.sitemap_capture_segments(nil, [:id])   #=> {:id => 1}

You have the ability to map attributes of an object to segment keys. This could be useful for routes that do not follow standard convention or cases where you have some deeply nested resources.

class BooksController < ApplicationController
  sitemap_segments :show, id: :my_id
end

class Book < ActiveRecord::Base
  attr_accessible :my_id, :author, :title

  before_save :generate_my_id

  def generate_my_id
    # do some magic
    self.my_id = 2
  end

end

row = Book.create(title: "Please ignore the first title :)")
puts row.id                                #=> 1
puts row.my_id                             #=> 2
# normally, you would get the attributes via:
# controller.sitemap_attributes("show")[:segments]
attributes = {id: :my_id}
row.sitemap_capture_segments(attributes, [:id])   #=> {:id => 2}

Segment values are obtained in two stages.

  • Stage one asks the current object (controller or model) for attributes from segment_mappings and places those key/values in the returning hash.

  • Stage two asks the current object (controller or model) for attributes from segments array that have not already been found via segment_mappings and places those key/values in the returning hash.

return [Hash]

Parameters:

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

    A Hash containing one-to-one attribute mappings for segment keys to object attributes.

  • segments (Array) (defaults to: [])

    The segments Array of a Rails Route.



424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
# File 'lib/duck_map/sitemap_object.rb', line 424

def sitemap_capture_segments(segment_mappings = {}, segments = [])
  values = {}

  # do nothing if there are no segments to work on
  if segments.kind_of?(Array)

    # first, look for mappings
    unless segment_mappings.blank?
      segments.each do |key|

        attribute_name = segment_mappings[key.to_sym].blank? ? key : segment_mappings[key.to_sym]

        if self.respond_to?(attribute_name)
          values[key] = self.send(attribute_name)
        end

      end
    end

    # second, look for attributes that have not already been found.
    segments.each do |key|

      unless values.has_key?(key)
        if self.respond_to?(key)
          values[key] = self.send(key)
        end
      end

    end

  end

  return values
end