Sanity for free 5

Posted by pratik
on Sunday, October 05

Just an experiment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
require 'erb'

class ActionView::Base
  def _copy_ivars_from_controller_with_sanity
    variables = _copy_ivars_from_controller_without_sanity
    variables.each do |v|
      ivar = instance_variable_get(v)
      if ivar.is_a?(Array)
        values = ivar.map do |subivar|
          subivar.respond_to?(:to_sanity) ? subivar.to_sanity : subivar
        end
        instance_variable_set(v, values)
      elsif ivar.respond_to?(:to_sanity)
        instance_variable_set(v, ivar.to_sanity)
      end
    end
  end

  alias_method_chain :_copy_ivars_from_controller, :sanity
end

module Sanity
  class Cleaner
    Object.instance_methods.each do |m|
      delegate m, :to => :@model unless m =~ /^__/
    end
    
    def initialize(model)
      @model = model
    end

    def method_missing(method_id, *arguments, &block)
      if @model.class.sanitizable_columns.include?(method_id)
        value = @model.send(method_id)
        arguments.first == false ? value : ERB::Util.h(value)
      else
        @model.send(method_id, *arguments, &block)
      end
    end
  end

  module Model
    def self.included(base)
      base.send :include, InstanceMethods
      base.send :extend, ClassMethods
    end
    
    module InstanceMethods
      def to_sanity
        Cleaner.new(self)
      end
    end
    
    module ClassMethods
      def sanitizable_columns
        @sanitizable_columns ||= content_columns.find_all {|c| c.text? }.map(&:name).map(&:to_sym)
      end
    end
  end
end

ActiveRecord::Base.send :include, Sanity::Model

And then..

1
2
<%= @item.name # sanitized name %>
<%= @item.name(false) # unsanitized name  %>

I know, too many methods are missing, edge cases and what not. But hey, it’s just an idea/experiment.

Comments

Leave a response

  1. edOctober 19, 2008 @ 04:40 AM

    Great code.. I really like the way you code…

    I would recommend you to consider using markaby instead of erb!

    Thanks

  2. dan quotesOctober 20, 2008 @ 05:00 AM

    I like every coder who uses instance_variable_set! It is great… I honestly used instance_variable_set a lot in many hard problems.

    Thanks, Dan

  3. MislavOctober 21, 2008 @ 01:25 AM

    Hello, nice site. Great to see you using the ternary operator. I think more coders should use the ternary operator

  4. samOctober 21, 2008 @ 10:26 PM

    I am kinda of interested in using _ in method names? i feel it can be tricky to remember… i like the use of send.. generally well written code..

    Thanks

  5. senseiOctober 25, 2008 @ 04:28 AM

    You know that the noun of sanitize is sanitization, not sanity, don’t you? ;-)

Comment