Class Facebooker::Rails::Publisher
In: lib/facebooker/rails/publisher.rb
Parent: Object

ActionMailer like module for publishing Facbook messages

To use, create a subclass and define methods Each method should start by calling send_as to specify the type of message Valid options are :email and :notification, :user_action, :profile, :ref, :publish_stream

Below is an example of each type

  class TestPublisher < Facebooker::Rails::Publisher
    # The new message templates are supported as well
    # First, create a method that contains your templates:
    # You may include multiple one line story templates and short story templates
    # but only one full story template
    #  Your most specific template should be first
    #
    # Before using, you must register your template by calling register. For this example
    #  You would call TestPublisher.register_publish_action
    #  Registering the template will store the template id returned from Facebook in the
    # facebook_templates table that is created when you create your first publisher
    def publish_action_template
      one_line_story_template "{*actor*} did stuff with {*friend*}"
      one_line_story_template "{*actor*} did stuff"
      short_story_template "{*actor*} has a title {*friend*}", render(:partial=>"short_body")
      short_story_template "{*actor*} has a title", render(:partial=>"short_body")
      full_story_template "{*actor*} has a title {*friend*}", render(:partial=>"full_body")
      action_links action_link("My text {*template_var*}","{*link_url*}")
    end

    # To send a registered template, you need to create a method to set the data
    # The publisher will look up the template id from the facebook_templates table
    def publish_action(f)
      send_as :user_action
      from f
      story_size SHORT # or ONE_LINE or FULL
      data :friend=>"Mike"
    end

    # Provide a from user to send a general notification
    # if from is nil, this will send an announcement
    def notification(to,f)
      send_as :notification
      recipients to
      from f
      fbml "Not"
    end

    def email(to,f)
      send_as :email
      recipients to
      from f
      title "Email"
      fbml 'text'
      text fbml
    end
    # This will render the profile in /users/profile.fbml.erb
    #   it will set @user to user_to_update in the template
    #  The mobile profile will be rendered from the app/views/test_publisher/_mobile.erb
    #   template
    def profile_update(user_to_update,user_with_session_to_use)
      send_as :profile
      from user_with_session_to_use
      recipients user_to_update
      profile render(:file=>"users/profile.fbml.erb",:assigns=>{:user=>user_to_update})
      profile_action "A string"
      mobile_profile render(:partial=>"mobile",:assigns=>{:user=>user_to_update})
  end

    #  Update the given handle ref with the content from a
    #   template
    def ref_update(user)
      send_as :ref
      from user
      fbml render(:file=>"users/profile",:assigns=>{:user=>user_to_update})
      handle "a_ref_handle"
  end

    #  Publish a post into the stream on the user's Wall and News Feed.
    def publish_stream(user_with_session_to_use, user_to_update, params)
      send_as :publish_stream
      from  user_with_session_to_use
      target user_to_update
      attachment params[:attachment]
      message params[:message]
      action_links params[:action_links]
    end

To send a message, use ActionMailer like semantics

   TestPublisher.deliver_action(@user)

For testing, you may want to create an instance of the underlying message without sending it

 TestPublisher.create_action(@user)

will create and return an instance of Facebooker::Feeds::Action

Publisher makes many helpers available, including the linking and asset helpers

Methods

Included Modules

ActionView::Helpers::UrlHelper ActionView::Helpers::TextHelper ActionView::Helpers::TagHelper ActionView::Helpers::FormHelper ActionView::Helpers::FormTagHelper ActionView::Helpers::AssetTagHelper ActionView::Helpers::NumberHelper Facebooker::Rails::Helpers

Classes and Modules

Class Facebooker::Rails::Publisher::Email
Class Facebooker::Rails::Publisher::FacebookTemplate
Class Facebooker::Rails::Publisher::ImageHolder
Class Facebooker::Rails::Publisher::InvalidSender
Class Facebooker::Rails::Publisher::Notification
Class Facebooker::Rails::Publisher::Profile
Class Facebooker::Rails::Publisher::PublishStream
Class Facebooker::Rails::Publisher::PublisherController
Class Facebooker::Rails::Publisher::Ref
Class Facebooker::Rails::Publisher::UnknownBodyType
Class Facebooker::Rails::Publisher::UnspecifiedBodyType
Class Facebooker::Rails::Publisher::UserAction

Constants

ONE_LINE = 1   story sizes from the Facebooker API
SHORT = 2
FULL = 4

Attributes

_body  [RW] 
action_links  [W] 
one_line_story_templates  [RW] 
short_story_templates  [RW] 

Public Class methods

[Source]

# File lib/facebooker/rails/publisher.rb, line 558
        def controller_path
          self.to_s.underscore
        end

[Source]

# File lib/facebooker/rails/publisher.rb, line 116
      def self.default_url_options
        {:host => Facebooker.canvas_server_base + Facebooker.facebook_path_prefix}
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 562
        def helper(*args)
          args.each do |arg|
            case arg
            when Symbol,String
              add_template_helper("#{arg.to_s.camelcase}Helper".constantize)
            when Module
              add_template_helper(arg)
            end
          end
        end

[Source]

# File lib/facebooker/rails/publisher.rb, line 579
        def inherited(child)
          super
          child.master_helper_module=Module.new
          child.master_helper_module.__send__(:include,self.master_helper_module)
          child.send(:include, child.master_helper_module)
          FacebookTemplate.clear_cache!
        end

[Source]

# File lib/facebooker/rails/publisher.rb, line 533
        def method_missing(name,*args)
          should_send = false
          method = ''
          if md = /^create_(.*)$/.match(name.to_s)
            method = md[1]
          elsif md = /^deliver_(.*)$/.match(name.to_s)
            method = md[1]
            should_send = true            
          elsif md = /^register_(.*)$/.match(name.to_s)
            return FacebookTemplate.register(self, md[1])
          else
            super
          end
      
          #now create the item
          (publisher=new).send(method,*args)
          case publisher._body
          when UserAction
            publisher._body.template_name = method
            publisher._body.template_id ||= FacebookTemplate.bundle_id_for_class_and_method(self,method)
          end
          
          should_send ? publisher.send_message(method) : publisher._body
        end

[Source]

# File lib/facebooker/rails/publisher.rb, line 107
      def initialize
        @from                 = nil
        @full_story_template  = nil
        @recipients           = nil
        @action_links         = nil
        @controller           = PublisherController.new(self)
        @action_links         = nil
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 507
        def register_all_templates
          all_templates = instance_methods.grep(/_template$/) - %w(short_story_template full_story_template one_line_story_template) 
          all_templates.each do |template|
            template_name=template.sub(/_template$/,"")
            puts "Registering #{template_name}"
            send("register_"+template_name)
          end
        end

[Source]

# File lib/facebooker/rails/publisher.rb, line 500
        def register_all_templates_on_all_applications
          Facebooker.with_all_applications do
            puts "Registering templates for #{Facebooker.api_key}"
            register_all_templates
          end
        end

[Source]

# File lib/facebooker/rails/publisher.rb, line 525
        def respond_to?(method_symbol, include_private=false)
          if match = /^(create|deliver|register)_([_a-z]\w*)/.match(method_symbol.to_s)
            instance_methods.include?(match[2])
          else
            super(method_symbol, include_private)
          end
        end

[Source]

# File lib/facebooker/rails/publisher.rb, line 516
        def unregister_inactive_templates
          session = Facebooker::Session.create
          active_template_ids = FacebookTemplate.all.map(&:bundle_id)
          all_template_ids = session.active_template_bundles.map {|t| t["template_bundle_id"]}
          (all_template_ids - active_template_ids).each do |template_bundle_id|
            session.deactivate_template_bundle_by_id(template_bundle_id)
          end
        end

Public Instance methods

[Source]

# File lib/facebooker/rails/publisher.rb, line 377
      def action_link(text,target)
        {:text=>text, :href=>target}
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 335
      def action_links(*links)
        if self._body and self._body.respond_to?(:action_links)
          self._body.send(:action_links,*links)
        end
        if links.blank?
          @action_links
        else
          @action_links = *links
        end
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 393
      def announcement_notification?(from,body)
        from.nil? and body.is_a?(Notification)
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 120
      def default_url_options
        self.class.default_url_options
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 283
      def from(*args)
        if args.size==0
          @from
        else
          @from=args.first
        end        
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 317
      def full_story_template(title=nil,body=nil,params={})
        if title.nil?
          @full_story_template
        else
          @full_story_template=params.merge(:template_title=>title, :template_body=>body)
        end
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 373
      def image(src,target)
        ImageHolder.new(image_path(src),target.respond_to?(:to_str) ? target : url_for(target))
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 448
      def initialize_template_class(assigns)
        template_root = "#{RAILS_ROOT}/app/views"
        controller_root = File.join(template_root,self.class.controller_path)
        #only do this on Rails 2.1
        if ActionController::Base.respond_to?(:append_view_path)
          # only add the view path once
          unless ActionController::Base.view_paths.include?(controller_root)
            ActionController::Base.append_view_path(controller_root) 
            ActionController::Base.append_view_path(controller_root+"/..") 
          end
          view_paths = ActionController::Base.view_paths
        else
          view_paths = [template_root, controller_root]
        end
        returning ActionView::Base.new(view_paths, assigns, self) do |template|
          template.controller=self
          template.extend(self.class.master_helper_module)
          def template.request_comes_from_facebook?
            true
          end
        end
      end

nodoc needed for actionview

[Source]

# File lib/facebooker/rails/publisher.rb, line 435
      def logger
        RAILS_DEFAULT_LOGGER
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 346
      def method_missing(name,*args)
        if args.size==1 and self._body.respond_to?("#{name}=")
          self._body.send("#{name}=",*args)
        elsif self._body.respond_to?(name)
          self._body.send(name,*args)
        else
          super
        end
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 325
      def one_line_story_template(str)
        @one_line_story_templates ||= []
        @one_line_story_templates << str
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 385
      def profile_update?(body)
        body.is_a?(Profile)
      end

define this for the publisher views

[Source]

# File lib/facebooker/rails/publisher.rb, line 487
        def  protect_against_forgery?protect_against_forgery?
          @paf ||= ActionController::Base.new.send(:protect_against_forgery?)
        end

[Source]

# File lib/facebooker/rails/publisher.rb, line 275
      def recipients(*args)
        if args.size==0
          @recipients
        else
          @recipients=args.first
        end
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 389
      def ref_update?(body)
        body.is_a?(Ref)
      end

nodoc delegate to action view. Set up assigns and render

[Source]

# File lib/facebooker/rails/publisher.rb, line 441
      def render(opts)
        opts = opts.dup
        body = opts.delete(:assigns) || {}
        initialize_template_class(body.dup.merge(:controller=>self)).render(opts)
      end

use facebook options everywhere

[Source]

# File lib/facebooker/rails/publisher.rb, line 125
      def request_comes_from_facebook?
        true
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 381
      def requires_from_user?(from,body)
        ! (announcement_notification?(from,body) or ref_update?(body) or profile_update?(body))
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 292
      def send_as(option)
        self._body=case option
        when :action
          Facebooker::Feed::Action.new
        when :story
          Facebooker::Feed::Story.new
        when :templatized_action
          Facebooker::Feed::TemplatizedAction.new
        when :notification
          Notification.new
        when :email
          Email.new
        when :profile
          Profile.new
        when :ref
          Ref.new
        when :user_action
          UserAction.new
        when :publish_stream
          StreamPost.new
        else
          raise UnknownBodyType.new("Unknown type to publish")
        end
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 397
      def send_message(method)
        @recipients = @recipients.is_a?(Array) ? @recipients : [@recipients]
        if from.nil? and @recipients.size==1 and requires_from_user?(from,_body)
          @from = @recipients.first
        end
        # notifications can 
        # omit the from address
        raise InvalidSender.new("Sender must be a Facebooker::User") unless from.is_a?(Facebooker::User) || !requires_from_user?(from,_body)
        case _body
        when Facebooker::Feed::TemplatizedAction,Facebooker::Feed::Action
          from.publish_action(_body)
        when Facebooker::Feed::Story
          @recipients.each {|r| r.publish_story(_body)}
        when Notification
          (from.nil? ? Facebooker::Session.create : from.session).send_notification(@recipients,_body.fbml)
        when Email
          from.session.send_email(@recipients, 
                                             _body.title, 
                                             _body.text, 
                                             _body.fbml)
        when Profile
         # If recipient and from aren't the same person, create a new user object using the
         # userid from recipient and the session from from
         @from = Facebooker::User.new(Facebooker::User.cast_to_facebook_id(@recipients.first),Facebooker::Session.create) 
         @from.set_profile_fbml(_body.profile, _body.mobile_profile, _body.profile_action, _body.profile_main)
        when Ref
          Facebooker::Session.create.server_cache.set_ref_handle(_body.handle,_body.fbml)
        when UserAction
          @from.session.publish_user_action(_body.template_id,_body.data_hash,_body.target_ids,_body.body_general,_body.story_size)
        when Facebooker::StreamPost
         @from.publish_to(_body.target, {:attachment => _body.attachment, :action_links => @action_links, :message => _body.message })
        else
          raise UnspecifiedBodyType.new("You must specify a valid send_as")
        end
      end

[Source]

# File lib/facebooker/rails/publisher.rb, line 330
      def short_story_template(title,body,params={})
        @short_story_templates ||= []
        @short_story_templates << params.merge(:template_title=>title, :template_body=>body)
      end

url_for calls in publishers tend to want full paths

[Source]

# File lib/facebooker/rails/publisher.rb, line 492
        def url_for(options = {})
          super(options.kind_of?(Hash) ? {:only_path => false}.update(options) : options)
        end

[Validate]