Capistrano 2 rolling task

This took a long time to track down, but this will allow rolling deploys or tasks with Capistrano 2.x.

task :rolling, roles: :web do 
    find_servers_for_task(current_task).each do |s|
        puts roles[:web].clear()
        server s.host, :web
        puts "Deploying to #{s.host}..."
        find_and_execute_task('deploy')
    end
end

Ref: https://groups.google.com/forum/#!topic/capistrano/H-tizsMN2Tk

AngularJS dynamic filter

/*
 * Use this to dynamically pass a filter from a controller or somewhere else 
 * as a string. It will use DI to lookup the filter and apply it.
 *
 * In the template:
 *
 *     {{row.label | date | dynamic:nameFilter }}
 *
 * In the controller:
 *
 *     $scope.nameFilter = 'mycustomerfilter'; 
 */
app.filter('dynamic', ['$injector', function($injector) {
  return function(text, filter) {
    var result = text;
    if (filter) {
      var f = $injector.get(filter + "Filter");
      if (f) { result = f(text); }
    }
    return result;
  }
}]);

Short MongoDB Fields with Mongoid

Need to have shorter field name in MongoDB, but still use readable names in code?

# Mongoid Timestamps
include Mongoid::Timestamps::Short

# fields
field :aid, as: :application_id, type:String

# one to one
embeds_one :address, :store_as => :ad

# collections
field :aid, as: :application_id
belongs_to :application, foreign_key: :aid

On Writing – Steven King

Part biography and part writing advice. Both were interesting.

The advise that jumped out is, Do The Work. For writing that’s writing and reading. Which translates well for most things into doing and learning/observing.

On Writing

Rails Blog Engines

A list of mountable blog engines for Rails.

Blogit

Blogit Engine

Blogit is a flexible blogging solution for Rails apps. It:

  • Is Rack based;
  • Is a complete MVC solution based on Rails engines;
  • Aims to work right out of the box but remain fully customisable.

JABE

JABE Blog Engine

JABE is a bare bones blogging engine that is installed as a gem. It will grow as its needs do.

This version is for Rails 3.1+

Squeaky

Squeaky Blog Engine

Squeaky is a simple mountable Rails engine for making a squeaky clean blog.

Hitchens

Hitchens Blog Engine

  • Mountable blog engine for Rails 3.1+
  • Design/style agnostic – just a blog backend
  • Inspired by radar/forem
  • MIT-LICENSE.

Kublog

Kublog Blog Engine

Kublog is a simple yet complete way to have a Product Blog that integrates with your apps user base. It includes social sharing, atom feeds and moderated comments.

Built for Rails 3.1, Kublog is a complete stack, fully configurable solution.

  • Publish posts with the most basic and simple wysiwyg
  • Attach multiple images to your content
  • Share your posts on your Product’s Twitter Page and Facebook Fan Page
  • E-mail personalized versions of your posts to all your users
  • Optional background processing with Delayed Job
  • Moderated comments from apps users, apps admins, and visitors
  • Atom feed for main blog and individual post categories

Rails Routes used in an Isolated Engine

The Problem

I have a rails application an want to add a blog engine to it. In this case the blogit engine. Things are working well until the layout is rendered. It uses the parent applications layout, which is what I want, but because it’s an isolated engine, it doesn’t have access to any of the parent applications helpers, including url helpers.

My Solution

If there’s a better way, please post in the comments.

In the engines config block, I open it’s application helper and add a method_missing definition. Then I check the main_app helper, which is added when the engine is mounted, for a matching helper method, if found use it.

/config/initializers/blogit.rb

...
  module Blogit
    module ApplicationHelper
      def method_missing method, *args, &block
        puts "LOOKING FOR ROUTES #{method}"
        if method.to_s.end_with?('_path') or method.to_s.end_with?('_url')
          if main_app.respond_to?(method)
            main_app.send(method, *args)
          else
            super
          end
        else
          super
        end
      end

      def respond_to?(method)
        if method.to_s.end_with?('_path') or method.to_s.end_with?('_url')
          if main_app.respond_to?(method)
            true
          else
            super
          end
        else
          super
        end
      end
    end
  end
...

As a side note, the engine layout can be specified in /app/views/layouts/blogit/application.html.haml.

Gotchas

root_path and root_url are defined for the engine, so those still need to be handled differently. This issue could happend for any routes that overlap.

(main_app||self).root_path

And the other way if you want to link to the engines root_path. blogit is the engine_name.

(blogit||self).root_path

Basic Rails Sitemap Setup

A basic sitemap generator for building a sitemap on the fly. I’d like a better way, but since it’s hosted on heroku and the map isn’t too big yet, this should work for now.

Add a route to handle building the XML

# /app/controllers/static_controller.rb
def sitemap
  xml = ::SitemapGenerator.create!('http://fixmycarin.com') do |map|
    map.add '', priority:0.9 , changefreq: :daily
    map.add '/faq', priority:0.7 , changefreq: :weekly
    map.add '/places', priority:0.7, changefreq: :weekly 
    map.add '/contact', priority:0.7, changefreq: :weekly 

    places = Place.all
    places.each{|u| map.add(place_path(u), lastmod:u.updated_at, changefreq: :weekly)}
  end
  render :xml => xml
end

Add a route to point to the above action

#/config/routes.rb
get 'sitemap.xml' => "static#sitemap"

Add a link in the robots.txt file

Sitemap: http://fixmycarin.com/sitemap.xml

Add the class that creates the XML. I put it in app/lib or app/services. This was adapted from this gist

# from: https://gist.github.com/288069
require 'builder'

class SitemapGenerator
  def initialize url
    @url = url
    yield(self) if block_given?
  end

  def add url, options = {}
    (@pages_to_visit ||= []) << options.merge(url:url)
    
  end

  def generate_sitemap
    xml_str = ""
    xml = Builder::XmlMarkup.new(:target => xml_str, :indent => 2)

    xml.instruct!
    xml.urlset(:xmlns=>'http://www.sitemaps.org/schemas/sitemap/0.9') {
      @pages_to_visit.each do |hash|
        unless @url == hash[:url]
          xml.url {
            xml.loc(@url + hash[:url])
            xml.lastmod(hash[:lastmod].utc.strftime("%Y-%m-%dT%H:%M:%S+00:00")) if hash.include? :lastmod
            xml.priority(hash[:priority]) if hash.include? :priority
            xml.changefreq(hash[:changefreq].to_s) if hash.include? :changefre
           }
        end
      end
    }

    return xml_str
  end

  # Notify popular search engines of the updated sitemap.xml
  def update_search_engines
    sitemap_uri = @url + 'sitemap.xml'
    escaped_sitemap_uri = CGI.escape(sitemap_uri)
    Rails.logger.info "Notifying Google"
    res = Net::HTTP.get_response('www.google.com', '/webmasters/tools/ping?sitemap=' + escaped_sitemap_uri)
    Rails.logger.info res.class
    Rails.logger.info "Notifying Yahoo"
    res = Net::HTTP.get_response('search.yahooapis.com', '/SiteExplorerService/V1/updateNotification?appid=SitemapWriter&url=' + escaped_sitemap_uri)
    Rails.logger.info res.class
    Rails.logger.info "Notifying Bing"
    res = Net::HTTP.get_response('www.bing.com', '/webmaster/ping.aspx?siteMap=' + escaped_sitemap_uri)
    Rails.logger.info res.class
    Rails.logger.info "Notifying Ask"
    res = Net::HTTP.get_response('submissions.ask.com', '/ping?sitemap=' + escaped_sitemap_uri)
    Rails.logger.info res.class
  end
end