<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DZone Snippets: filters code</title>
    <link>http://snippets.dzone.com/posts</link>
    <pubDate>Thu, 24 Jul 2008 21:27:43 GMT</pubDate>
    <description>DZone Snippets: filters code</description>
    <item>
      <title>MIME Responder before_filter for Rails</title>
      <link>http://snippets.dzone.com/posts/show/5139</link>
      <description>This is abridged for conciseness.  For full post, visit &lt;a href="http://webjazz.blogspot.com/2008/02/mime-responder-filter-for-rails.html"&gt;MIME Responder filter for Rails&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I spent last week integrating &lt;a href="http://www.mobtropolis.com"&gt;Mobtropolis&lt;/a&gt; with facebook. Mobtropolis doesn't require a facebook account to use it, so like other websites, it has its own authentication mechanism, something like:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class PostController &lt; ActionController::Base&lt;br /&gt;  before_filter :website_authenticate_filter, :except =&gt; [:index, :list]&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;When I started using facebooker library, it already came with an authentication before_filter. That means we have two authentication filters, one native, and one for facebook. Mobtropolis users don't have to be in facebook to use it, and facebookers don't have to sign up again in mobtropolis to use it.&lt;br /&gt;&lt;br /&gt;However, since before_filters are executed in succession, it leads to a case where the facebook authentication would be called if html was requested, and vice versa. The alternative was to take apart both authentication filters, and create a monolithic filter to handle the two different cases. Instead, I made a before_filter respond to different MIME types.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class PostController &lt; ActionController::Base&lt;br /&gt;   before_respond_to_filter :except =&gt; [ :index, :list ] do |format|&lt;br /&gt;    format.html :website_authentication_filter&lt;br /&gt;    format.fbml :facebook_authentication_filter&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That way, I didn't have to mix together the guts of each authentication filter, and it solved the problem of the wrong authentication filter being run. You can also use it like:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class PostController &lt; ActionController::Base&lt;br /&gt;  before_responds_to_filter :only =&gt; :home do |format|&lt;br /&gt;    format.html do |controller|&lt;br /&gt;      return if controller.logged_in?&lt;br /&gt;      controller.send(:redirect_to, :controller =&gt; :home)&lt;br /&gt;    end&lt;br /&gt;    format.fbml :ensure_application_is_installed_by_facebook_user&lt;br /&gt;  end   &lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;It ended up the code for this sort of magic was fairly easy. I'm not sure if there's an easier way to do what I wanted, but I'll see if Rails core people would find it useful (or not). In the meanwhile, for those of you Rubyists that have written plugins before that want to play with it. As with the usual mumbo jumbo, it's provided as is, I'm not maintaining it, and do whatever you want with it:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# init.rb&lt;br /&gt;require 'mime_responder_filter'&lt;br /&gt;ActionController::Base.send :include, Threecglabs::Filters::MimeResponderFilter&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# mime_responder_filter.rb&lt;br /&gt;module Threecglabs&lt;br /&gt;  module Filters&lt;br /&gt;&lt;br /&gt;    # MimeResponderFilter &lt;br /&gt;    module MimeResponderFilter&lt;br /&gt;&lt;br /&gt;      def self.included(mod)&lt;br /&gt;        mod.extend(ClassMethods)&lt;br /&gt;      end&lt;br /&gt;  &lt;br /&gt;      # Filters can respond to different mime types, so that you can use &lt;br /&gt;      # different filters depending on which mime type is being requested&lt;br /&gt;      #&lt;br /&gt;      #   before_responds_to_filter :except =&gt; [:login, :signup, :forgot, :invite_request, :profile] do |format|&lt;br /&gt;      #     format.html :authentication_filter&lt;br /&gt;      #     format.fbml :ensure_application_is_installed_by_facebook_user&lt;br /&gt;      #   end&lt;br /&gt;      #&lt;br /&gt;      # This way, one can take the appropriate actions in setting up authentication &lt;br /&gt;      # from different mime types, and still separate the implemenation of the different&lt;br /&gt;      # kinds of implementations&lt;br /&gt;      #&lt;br /&gt;      # The formats also take blocks, like regular filters&lt;br /&gt;      #&lt;br /&gt;      #   before_responds_to_filter :only =&gt; :home do |format|&lt;br /&gt;      #     format.html do |controller|&lt;br /&gt;      #       return if controller.logged_in?&lt;br /&gt;      #       controller.send(:redirect_to, :controller =&gt; :home)&lt;br /&gt;      #     end&lt;br /&gt;      #     format.fbml :ensure_application_is_installed_by_facebook_user&lt;br /&gt;      #   end&lt;br /&gt;      #&lt;br /&gt;      # NOTE: an :all format defaults to :html, therefore, a format.html is required&lt;br /&gt;      module ClassMethods        &lt;br /&gt;        def before_respond_to_filter(options = {}, &amp;block)&lt;br /&gt;          before_filter MimeResponderFilter.new(&amp;block), options&lt;br /&gt;        end&lt;br /&gt;        &lt;br /&gt;        private&lt;br /&gt;        # This is a call that implements a MIME responder filter&lt;br /&gt;        class MimeResponderFilter#:nodoc:&lt;br /&gt;          attr_reader :filters&lt;br /&gt;          &lt;br /&gt;          def initialize(&amp;block)&lt;br /&gt;            @filters = {}&lt;br /&gt;            block.call(self)&lt;br /&gt;          end&lt;br /&gt;          &lt;br /&gt;          def filter(controller)&lt;br /&gt;            filter = @filters[controller.request.format.to_sym] || @filters[:html]&lt;br /&gt;            if filter.kind_of?(Proc)&lt;br /&gt;              filter.call(controller)&lt;br /&gt;            else&lt;br /&gt;              controller.send!(filter)&lt;br /&gt;            end&lt;br /&gt;          end&lt;br /&gt;          &lt;br /&gt;          # implements the "format.#{mime_type}" part of the filter&lt;br /&gt;          def method_missing(mime_type, method_name = nil, &amp;block)&lt;br /&gt;            if block_given?&lt;br /&gt;              @filters[mime_type.to_sym] = block&lt;br /&gt;            else&lt;br /&gt;              @filters[mime_type.to_sym] = method_name.to_sym&lt;br /&gt;            end&lt;br /&gt;          end&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Snippet!</description>
      <pubDate>Wed, 13 Feb 2008 20:34:07 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/5139</guid>
      <author>iamwil (wilhelm)</author>
    </item>
    <item>
      <title>BloominSimple: Ultra-easy, pure Ruby Bloom filter library</title>
      <link>http://snippets.dzone.com/posts/show/4235</link>
      <description>Requires &lt;a href="http://snippets.dzone.com/posts/show/4234"&gt;BitField.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;#        NAME: BloominSimple&lt;br /&gt;#      AUTHOR: Peter Cooper&lt;br /&gt;#     LICENSE: MIT ( http://www.opensource.org/licenses/mit-license.php )&lt;br /&gt;#   COPYRIGHT: (c) 2007 Peter Cooper&lt;br /&gt;# DESCRIPTION: Very basic, pure Ruby Bloom filter. Uses my BitField, pure Ruby&lt;br /&gt;#              bit field library (http://snippets.dzone.com/posts/show/4234).&lt;br /&gt;#              Supports custom hashing (default is 3).&lt;br /&gt;#&lt;br /&gt;#              Create a Bloom filter that uses default hashing with 1Mbit wide bitfield&lt;br /&gt;#                bf = BloominSimple.new(1_000_000)&lt;br /&gt;#              &lt;br /&gt;#              Add items to it&lt;br /&gt;#                File.open('/usr/share/dict/words').each { |a| bf.add(a) }&lt;br /&gt;#&lt;br /&gt;#              Check for existence of items in the filter&lt;br /&gt;#                bf.includes?("people")     # =&gt; true&lt;br /&gt;#                bf.includes?("kwyjibo")    # =&gt; false&lt;br /&gt;#&lt;br /&gt;#              Add better hashing (c'est easy!)&lt;br /&gt;#                require 'digest/sha1'&lt;br /&gt;#                b = BloominSimple.new(1_000_000) do |item|&lt;br /&gt;#                  Digest::SHA1.digest(item.downcase.strip).unpack("VVVV")&lt;br /&gt;#                end&lt;br /&gt;#&lt;br /&gt;#              More&lt;br /&gt;#                %w{wonderful ball stereo jester flag shshshshsh nooooooo newyorkcity}.each do |a|&lt;br /&gt;#                  puts "#{sprintf("%15s", a)}: #{b.includes?(a)}"&lt;br /&gt;#                end&lt;br /&gt;#&lt;br /&gt;#                 #  =&gt;   wonderful: true&lt;br /&gt;#                 #  =&gt;        ball: true&lt;br /&gt;#                 #  =&gt;      stereo: true&lt;br /&gt;#                 #  =&gt;      jester: true&lt;br /&gt;#                 #  =&gt;        flag: true&lt;br /&gt;#                 #  =&gt;  shshshshsh: false&lt;br /&gt;#                 #  =&gt;    nooooooo: false&lt;br /&gt;#                 #  =&gt; newyorkcity: false&lt;br /&gt;&lt;br /&gt;require 'benchmark'&lt;br /&gt;require 'bitfield'&lt;br /&gt;&lt;br /&gt;class BloominSimple&lt;br /&gt;  attr_reader :bitfield, :hasher&lt;br /&gt;  &lt;br /&gt;  def initialize(bitsize, &amp;block)&lt;br /&gt;    @bitfield = BitField.new(bitsize)&lt;br /&gt;    @size = bitsize&lt;br /&gt;    @hasher = block || lambda do |word|&lt;br /&gt;      word = word.downcase.strip&lt;br /&gt;      [h1 = word.sum, h2 = word.hash, h2 + h1 ** 3]&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def add(item)&lt;br /&gt;    @hasher[item].each { |hi| @bitfield[hi % @size] = 1 }&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def includes?(item)&lt;br /&gt;    @hasher[item].each { |hi| return false unless @bitfield[hi % @size] == 1 } and true&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Mon, 02 Jul 2007 02:14:09 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/4235</guid>
      <author>peter (Peter Cooperx)</author>
    </item>
  </channel>
</rss>
