# Stymied trying to extend AR with Plugin

**URL:** <https://www.ruby-forum.com/t/stymied-trying-to-extend-ar-with-plugin/165279>\
**Category:** Rails\
**Created:** [April 11, 2009, 8:08am UTC](https://www.ruby-forum.com/t/stymied-trying-to-extend-ar-with-plugin/165279 "2009-04-11T08:08:42Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [April 11, 2009, 8:08am UTC](https://www.ruby-forum.com/t/stymied-trying-to-extend-ar-with-plugin/165279/1 "2009-04-11T08:08:42Z")

</div>

Lots of code below, since it’s usually the details that matter. Bit of a  
long one, but I think it’s generic enough to be a good one for the  
archives.

Experimenting with how to extend ActiveRecord. So I picked a little  
example project of an input scrubber. The purpose for the code is to  
automatically sanitize attribute data prior to it being saved. Don’t  
focus on the scrubber itself, it’s just a arbitrary task for something  
to play with (obviously it’s not a full scale sanitizer).

I have the Peepcode plugins book, and I have checked several blogs. I  
have tinkered for hours now, trying simple Ruby-only steps to understand  
the various ruby dynamics with extend, include, included, etc. So I’m  
generally getting the concepts (and working simple examples), but  
getting lost in the details of how to get this particular idea to work.

So let’s start with an implementation hard coded inside one model which  
works just fine.

class Example \< ActiveRecord::Base

@@scrub\_attributes = [:author\_name, :title, :content]

def before\_save  
self.attributes.each do |key,value|  
if @@scrub\_attributes.include?(key.to\_sym)  
scrub\_value(value) if !value.nil?  
end  
end  
end

def scrub\_value(input\_value)  
input\_value.gsub!(/"/,’"’)  
input\_value.gsub!(/`/,’’’)  
input\_value.gsub!(/’/,’’’)  
input\_value.gsub!(/(/,’(’)  
input\_value.gsub!(/)/,’)’)  
input\_value.gsub!(/\</,’\<’)  
input\_value.gsub!(/\>/,’\>’)  
input\_value.gsub!(/j\s_a\s_v\s_a\s_s\s_c\s_r\s_i\s_p\s_t\s_:/i,’’)  
end

end

#================================================================

But, of course, what I really want for the model code API is this:

class Example \< ActiveRecord::Base  
scrub\_attributes :author\_name, :title, :content  
end

So, I started work on a plugin. Below is where I am at so far. I have  
boiled (or rather logged) the problem down to two details. I have marked  
a few points of reference to talk about. Have a gander, and I’ll meet  
you at the end of the code…

#================================================================

Plugin structure:  
/plugins  
init.rb  
/ar\_extensions  
/lib  
/gw  
attribute\_scrubber.rb

init.rb contains  
ActiveRecord::Base.send(:include, GW::AttributeScrubber)

module GW  
module AttributeScrubber

```
def self.included(base_module)
   class << base_module
     @@attributes_to_scrub = []
   end
  base_module.extend ClassMethods
  base_module.send(:include, InstanceMethods) # <---- (1)
end

module ClassMethods
  def scrub_attributes(*attr_names)
    @@attributes_to_scrub = attr_names
  end
  def attributes_to_scrub
    return @@attributes_to_scrub
  end
end

module InstanceMethods
  def scrub_value(input_value) # <---- (2)
    input_value.gsub!(/\"/,'&#34;')
    input_value.gsub!(/`/,'&#39;')
    input_value.gsub!(/\'/,'&#39;')
    input_value.gsub!(/\(/,'&#40;')
    input_value.gsub!(/\)/,'&#41;')
    input_value.gsub!(/</,'&lt;')
    input_value.gsub!(/>/,'&gt;')
    input_value.gsub!(/j\s*a\s*v\s*a\s*s\s*c\s*r\s*i\s*p\s*t\s*\:/i,'')
  end
end

def self.append_features(base_module)
  base_module.before_save do |model|
    model.attributes.each do |key,value|
      if @@attributes_to_scrub.include?(key.to_sym) #<--- (3)
        scrub_value(value) if !value.nil? # <---- (4)
      end
    end
  end
end

```

end  
end

#================================================================

So, the problem I am having starts with (1). The PeepCode book says this  
code should be

```
def self.included(base_module)
  base_module.extend ClassMethods
  base_module.include InstanceMethods
end

```

But that generates an error  
`included': private method`include’ called

Thus, I’m trying base\_module.send(:include, InstanceMethods), but that  
doesn’t seem to be working either because down at (4) I get errors that  
method scrub\_value doesn’t exist.

Before we get to (4) though, it turns out that at (3)  
@@attributes\_to\_scrub, which I am expecting to be a class var for  
ActiveRecord doesn’t exist for the before\_save method. I discovered that  
even though the @@attributes\_to\_scrub contained in scrub\_attributes does  
havethe values I expect, at (3) there are no values. Namespace problem?

I hard coded an array in place of the class var at (3), and then I get  
the error that the method scrub\_value doesn’t exist, so I know the  
InstanceMethods are not being included, or at least not in the namespace  
I’m expecting. But I can get some simple Ruby-only code to work this way  
just fine. So, I’m confused about that.

Other than running into the snags at (3) and (4), it all seems to run.

Clues appreciated. Thanks.

– gw

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [April 11, 2009, 8:57am UTC](https://www.ruby-forum.com/t/stymied-trying-to-extend-ar-with-plugin/165279/2 "2009-04-11T08:57:27Z")

</div>

Greg W. wrote:

> Lots of code below, since it’s usually the details that matter. Bit of a  
> long one, but I think it’s generic enough to be a good one for the  
> archives.

OK, nevermind – got it sorted out.

required this change:

def self.append\_features(base\_module)  
base\_module.before\_create do |model|  
model.attributes.each do |key,value|  
if model.class.attributes\_to\_scrub.include?(key.to\_sym)  
model.scrub\_value(value) if !value.nil?  
end  
end  
end  
end

– gw

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [April 11, 2009, 10:25am UTC](https://www.ruby-forum.com/t/stymied-trying-to-extend-ar-with-plugin/165279/3 "2009-04-11T10:25:21Z")

</div>

On Apr 11, 7:57 am, Greg W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> base\_module.before\_create do |model|  
> model.attributes.each do |key,value|  
> if model.class.attributes\_to\_scrub.include?(key.to\_sym)  
> model.scrub\_value(value) if !value.nil?  
> end  
> end  
> end  
> end

In case you’re curious why, that;s because blocks are closures - in  
particular they remember self, so you were trying to call scrub\_value  
on the module, read that variable form the module etc.

Fred

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [April 11, 2009, 11:24am UTC](https://www.ruby-forum.com/t/stymied-trying-to-extend-ar-with-plugin/165279/4 "2009-04-11T11:24:57Z")

</div>

Frederick C. wrote:

> On Apr 11, 7:57ï¿½am, Greg W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> wrote:
> 
> > ï¿½ base\_module.before\_create do |model|  
> > ï¿½ ï¿½ model.attributes.each do |key,value|  
> > ï¿½ ï¿½ ï¿½ if model.class.attributes\_to\_scrub.include?(key.to\_sym)  
> > ï¿½ ï¿½ ï¿½ ï¿½ model.scrub\_value(value) if !value.nil?  
> > ï¿½ ï¿½ ï¿½ end  
> > ï¿½ ï¿½ end  
> > ï¿½ end  
> > end
> 
> In case you’re curious why, that;s because blocks are closures - in  
> particular they remember self, so you were trying to call scrub\_value  
> on the module, read that variable form the module etc.

Thx. Always curious as to why! 🙂

What was most curious is that the @@var created by the class \<\< block is  
different than the @@var in the scrub\_attributes method. By using  
model.class.attributes\_to\_scrub I don’t even need the class \<\<  
statements anymore.

So, yeah, I need to do more atomic experiments to understand the scoping  
of modules & classes. I thought modules didn’t hold vars, but I get they  
hold at least class vars (or something else is going on I didn’t pick up  
on).

– gw
