def get_all_chatter_feeds_with_attachments(object_id, object_type, binding, directory_name, limit=100, get_attachment=true, query_string=nil)
      begin
        #e.g. select Id, type, FeedPost.body from UserProfileFeed WITH UserId = '005A0000000S8aIIAS'
        if !object_id.nil?
          qstring = <<-HERE
          SELECT #{BASE_FRAG}, #{FEEDPOST_WITHOUT_CONTENT_DATA_FRAG},
          (#{FEED_TRACKED_CHANGE_FRAG}), (#{FEED_COMMENT_FRAG} LIMIT #{limit})
          FROM #{object_type}Feed where parentid = \'#{object_id}\'
          ORDER BY CreatedDate DESC limit #{limit}
          HERE
        elsif !query_string.nil?
          # this is more like a search....
          qstring = <<-HERE
          SELECT #{BASE_FRAG}, #{FEEDPOST_WITHOUT_CONTENT_DATA_FRAG},
          (#{FEED_TRACKED_CHANGE_FRAG}), (#{FEED_COMMENT_FRAG} LIMIT #{limit})
          FROM #{object_type}Feed where FeedPost.Body like \'%#{query_string}%\'
          ORDER BY CreatedDate DESC limit #{limit}
          HERE
        else
          qstring = <<-HERE
          SELECT #{BASE_FRAG}, #{FEEDPOST_WITHOUT_CONTENT_DATA_FRAG},
          (#{FEED_TRACKED_CHANGE_FRAG}), (#{FEED_COMMENT_FRAG} LIMIT #{limit})
          FROM #{object_type}Feed ORDER BY CreatedDate DESC limit #{limit}
          HERE
        end


        @logger.info('qstring: ' + qstring)
        # Note, if query FeedPost.ContentData, Salesforce only returns 1 entry at
        # a time, you will get a 'queryLocator', which can be used by calling
        # 'queryMore(queryLocator)'

        feed_results = Array.new

        results = binding.query(:queryString => qstring)
        if results.queryResponse.result.records.is_a?(Hash)
          # User has made only one feedpost
          feed = Hash.new
          feed = results.queryResponse.result.records
          if (!feed.FeedPost.nil?) && (feed.FeedPost.ContentSize.to_i > 0)
            feed = get_single_chatter_feed_with_attachment(feed.FeedPost.Id, feed[:type], binding, directory_name)
          end
          feed_results << feed
        elsif results.queryResponse.result.records.is_a?(Array)
          results.queryResponse.result.records.each do |an_feed_entry|
            if (an_feed_entry.is_a?(Hash))
              if (an_feed_entry[:Type] == "TrackedChange")
                # This is a TrackedChange Feed, the FeedPost Body is nil
                feed = Hash.new
                feed = an_feed_entry
                feed_results << feed
              elsif (!an_feed_entry.FeedPost.nil?) && (an_feed_entry.FeedPost.ContentSize.to_i > 0) && (get_attachment)
                # This signifies that:
                #   1. results.queryResponse.result.records.FeedPost.Type is of "ContentPost"
                #   2. results.queryResponse.result.records.FeedPost.type should be of "FeedPost"
                an_entry_with_attachment = get_single_chatter_feed_with_attachment(an_feed_entry.FeedPost.Id, an_feed_entry[:type], binding, directory_name)
                feed_results << an_entry_with_attachment
              else
                feed = Hash.new
                feed = an_feed_entry
                feed_results << feed
              end
            else
              @logger.info "Result #{object_id} has a results.queryResponse that is either not a valid Hash, or with nil FeedPost."
            end
          end
        end

        #if there are more entries, query it again and show it all
        while results.queryResponse.result.done.to_s.upcase != 'TRUE'
          results = binding.queryMore(:queryString => results.queryResponse.result.queryLocator)
          if results.queryResponse.result.records.is_a?(Hash)
            # User has made only one feedpost
            feed = Hash.new
            feed = results.queryResponse.result.records
            if (!feed.FeedPost.nil?) && (feed.FeedPost.ContentSize.to_i > 0)
              feed = get_single_chatter_feed_with_attachment(feed.FeedPost.Id, feed[:type], binding, directory_name)
            end
            feed_results << feed
          elsif results.queryResponse.result.records.is_a?(Array)
            results.queryResponse.result.records.each do |an_feed_entry|
              if (an_feed_entry.is_a?(Hash))
                if (an_feed_entry[:Type] == "TrackedChange")
                  # This is a TrackedChange Feed, the FeedPost Body is nil
                  feed = Hash.new
                  feed = an_feed_entry
                  feed_results << feed
                  # check to see if it has attachments
                elsif  (!an_feed_entry.FeedPost.nil?) && (an_feed_entry.FeedPost.ContentSize.to_i > 0) && (get_attachment)
                  # This signifies that:
                  #   1. results.queryResponse.result.records.FeedPost.Type is of "ContentPost"
                  #   2. results.queryResponse.result.records.FeedPost.type should be of "FeedPost"
                  an_entry_with_attachment = get_single_chatter_feed_with_attachment(an_feed_entry.FeedPost.Id, an_feed_entry[:type], binding, directory_name)
                  feed_results << an_entry_with_attachment
                else
                  feed = Hash.new
                  feed = an_feed_entry
                  feed_results << feed
                end

              else
                @logger.info "Result #{object_id} has a results.queryResponse that is either an invalid Hash or a nil FeedPost."
              end
            end
          end
        end

        return feed_results
      rescue Exception => exception
        @logger.info 'get_all_feed_posts_with_attachments: ' + exception.message
        return feed_results
      end
    end
def get_all_chatter_feeds_with_attachments(object_id, object_type, binding, directory_name, limit=100, get_attachment=true, query_string=nil)
      begin
        #e.g. select Id, type, FeedPost.body from UserProfileFeed WITH UserId = '005A0000000S8aIIAS'
        if !object_id.nil?
          qstring = <<-HERE
          SELECT #{BASE_FRAG}, #{FEEDPOST_WITHOUT_CONTENT_DATA_FRAG},
          (#{FEED_TRACKED_CHANGE_FRAG}), (#{FEED_COMMENT_FRAG} LIMIT #{limit})
          FROM #{object_type}Feed where parentid = \'#{object_id}\'
          ORDER BY CreatedDate DESC limit #{limit}
          HERE
        elsif !query_string.nil?
          # this is more like a search....
          qstring = <<-HERE
          SELECT #{BASE_FRAG}, #{FEEDPOST_WITHOUT_CONTENT_DATA_FRAG},
          (#{FEED_TRACKED_CHANGE_FRAG}), (#{FEED_COMMENT_FRAG} LIMIT #{limit})
          FROM #{object_type}Feed where FeedPost.Body like \'%#{query_string}%\'
          ORDER BY CreatedDate DESC limit #{limit}
          HERE
        else
          qstring = <<-HERE
          SELECT #{BASE_FRAG}, #{FEEDPOST_WITHOUT_CONTENT_DATA_FRAG},
          (#{FEED_TRACKED_CHANGE_FRAG}), (#{FEED_COMMENT_FRAG} LIMIT #{limit})
          FROM #{object_type}Feed ORDER BY CreatedDate DESC limit #{limit}
          HERE
        end


        @logger.info('qstring: ' + qstring)
        # Note, if query FeedPost.ContentData, Salesforce only returns 1 entry at
        # a time, you will get a 'queryLocator', which can be used by calling
        # 'queryMore(queryLocator)'

        feed_results = Array.new

        results = binding.query(:queryString => qstring)
        if results.queryResponse.result.records.is_a?(Hash)
          # User has made only one feedpost
          feed = Hash.new
          feed = results.queryResponse.result.records
          if (!feed.FeedPost.nil?) && (feed.FeedPost.ContentSize.to_i > 0)
            feed = get_single_chatter_feed_with_attachment(feed.FeedPost.Id, feed[:type], binding, directory_name)
          end
          feed_results << feed
        elsif results.queryResponse.result.records.is_a?(Array)
          results.queryResponse.result.records.each do |an_feed_entry|
            if (an_feed_entry.is_a?(Hash))
              if (an_feed_entry[:Type] == "TrackedChange")
                # This is a TrackedChange Feed, the FeedPost Body is nil
                feed = Hash.new
                feed = an_feed_entry
                feed_results << feed
              elsif (!an_feed_entry.FeedPost.nil?) && (an_feed_entry.FeedPost.ContentSize.to_i > 0) && (get_attachment)
                # This signifies that:
                #   1. results.queryResponse.result.records.FeedPost.Type is of "ContentPost"
                #   2. results.queryResponse.result.records.FeedPost.type should be of "FeedPost"
                an_entry_with_attachment = get_single_chatter_feed_with_attachment(an_feed_entry.FeedPost.Id, an_feed_entry[:type], binding, directory_name)
                feed_results << an_entry_with_attachment
              else
                feed = Hash.new
                feed = an_feed_entry
                feed_results << feed
              end
            else
              @logger.info "Result #{object_id} has a results.queryResponse that is either not a valid Hash, or with nil FeedPost."
            end
          end
        end

        #if there are more entries, query it again and show it all
        while results.queryResponse.result.done.to_s.upcase != 'TRUE'
          results = binding.queryMore(:queryString => results.queryResponse.result.queryLocator)
          if results.queryResponse.result.records.is_a?(Hash)
            # User has made only one feedpost
            feed = Hash.new
            feed = results.queryResponse.result.records
            if (!feed.FeedPost.nil?) && (feed.FeedPost.ContentSize.to_i > 0)
              feed = get_single_chatter_feed_with_attachment(feed.FeedPost.Id, feed[:type], binding, directory_name)
            end
            feed_results << feed
          elsif results.queryResponse.result.records.is_a?(Array)
            results.queryResponse.result.records.each do |an_feed_entry|
              if (an_feed_entry.is_a?(Hash))
                if (an_feed_entry[:Type] == "TrackedChange")
                  # This is a TrackedChange Feed, the FeedPost Body is nil
                  feed = Hash.new
                  feed = an_feed_entry
                  feed_results << feed
                  # check to see if it has attachments
                elsif  (!an_feed_entry.FeedPost.nil?) && (an_feed_entry.FeedPost.ContentSize.to_i > 0) && (get_attachment)
                  # This signifies that:
                  #   1. results.queryResponse.result.records.FeedPost.Type is of "ContentPost"
                  #   2. results.queryResponse.result.records.FeedPost.type should be of "FeedPost"
                  an_entry_with_attachment = get_single_chatter_feed_with_attachment(an_feed_entry.FeedPost.Id, an_feed_entry[:type], binding, directory_name)
                  feed_results << an_entry_with_attachment
                else
                  feed = Hash.new
                  feed = an_feed_entry
                  feed_results << feed
                end

              else
                @logger.info "Result #{object_id} has a results.queryResponse that is either an invalid Hash or a nil FeedPost."
              end
            end
          end
        end

        return feed_results
      rescue Exception => exception
        @logger.info 'get_all_feed_posts_with_attachments: ' + exception.message
        return feed_results
      end
    end
1. It returns the attached file.
 2. <b>'object_id'</b> corresponds to the 'parent_id' column in the 'XXXFeed' table
 3. <b>'object_type'</b> can be one of the followings
     Account, Asset, Campaign, Case, Lead, Contact, Contract, Opportunity,
     Product2, Solution, User
     **Note**: UserProfileFeed and NewsFeed are special cases.
       UserProfileFeed  -> select ... from UserProfileFeed with Userid='userid'
       NewsFeed -> select ... from NewsFeed where parentid = 'userid'
 4. <b>'binding'</b> can be passed in directly or using the inherited binding from the
    'Salesforce::SfBase' base class.
 5. <b>'directory_name</b> is the directory in 'public/tmp' for saving the attachment
 6. <b>'limit</b> is the number of records to return
 7. <b>'get_attachment'</b> is a boolean flag, true gets the attachment,
     false does not get the attachment
 8. <b>query_string</b> is used to search against the Salesforce. Note, if "object_id' is specified, query_string is ignored.
 8. returns Ruby Array of matching records
 9. TODO add conditions, e.g.
     search -> where FeedPost.CreatedDate > 2007-08-06T03:23:00.000Z and FeedPost.Body like '%post%'
     pagination ->