# Ruby methods question

**URL:** <https://www.ruby-forum.com/t/ruby-methods-question/88477>\
**Category:** Ruby\
**Created:** [March 11, 2007, 8:25pm UTC](https://www.ruby-forum.com/t/ruby-methods-question/88477 "2007-03-11T20:25:44Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [March 11, 2007, 8:25pm UTC](https://www.ruby-forum.com/t/ruby-methods-question/88477/1 "2007-03-11T20:25:44Z")

</div>

I followed the online tutorials on how to write plugins. So I have  
acts\_as\_fox.rb:

require ‘active\_record’

module Foo  
module Acts #:nodoc:  
module Fox #:nodoc:

```
  def self.included(mod)
    mod.extend(ClassMethods)
  end

  # declare the class level helper methods which
  # will load the relevant instance methods
  # defined below when invoked
  module ClassMethods
    def acts_as_fox
      class_eval do
        extend Foo::Acts::Fox::SingletonMethods
      end
      include Foo::Acts::Fox::InstanceMethods
    end
  end

  # Adds a catch_chickens class method which finds
  # all records which have a 'chickens' field set
  # to true.
  module SingletonMethods
    def catch_chickens
      find(:all, :conditions => ['chickens = ?', true])
    end
    # etc...
  end

  # Adds instance methods.
  module InstanceMethods
    def eat_chicken
      puts "Fox with ID #{self.id} just ate a chicken"
    end
  end

end

```

end  
end

# reopen ActiveRecord and include all the above to make

# them available to all our models if they want it

ActiveRecord::Base.class\_eval do  
include Foo::Acts::Fox  
end

and Thing.rb

class Thing \< ActiveRecord::Base  
acts\_as\_fox  
end

My question I want to change the acts\_as\_fox to something like:

acts\_as\_fox :pass\_something

where I can pass a symbol as a value to the acts\_as\_fox method.

I tried to modify the working example with no luck. Can someone please  
point me in the right direction?

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [March 11, 2007, 10:33pm UTC](https://www.ruby-forum.com/t/ruby-methods-question/88477/2 "2007-03-11T22:33:58Z")

</div>

On 3/11/07, removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> mod.extend(ClassMethods)
> include Foo::Acts::Fox::InstanceMethods
> # etc...
> 
> ```
> 
> end
> 
> I tried to modify the working example with no luck. Can someone please  
> point me in the right direction?

Don’t know anything about plugins, though I suppose

```
  module ClassMethods
    def acts_as_fox(arg)
      do_something(arg)
      class_eval do
        extend Foo::Acts::Fox::SingletonMethods
      end
      include Foo::Acts::Fox::InstanceMethods
    end
  end

```

should suffice. If it doesn’t work, please specify 1. what are you  
trying to achieve, 2. what did you try (preferably include the code)  
and 3. what did you get (include error messages and/or describe the  
wrong behaviour)

This code is a copy-paste from the tutorial. To find out what’s wrong  
it’s important to see your changes.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [March 11, 2007, 11:11pm UTC](https://www.ruby-forum.com/t/ruby-methods-question/88477/3 "2007-03-11T23:11:04Z")

</div>

Your code works. I want to make the acts\_as\_chicken :something to be  
available only to those ActiveRecord subclasses that uses the  
acts\_as\_chicken declaration. How can I accomplish that?

> ```
> extend Foo::Acts::Fox::SingletonMethods
> end
> include Foo::Acts::Fox::InstanceMethods
> end
> end
> 
> ```

Loading development environment.

> > t = Thing.new  
> > =\> #\<Thing:0x31e3dec @new\_record=true, @attributes={“chickens”=\>nil}
> 
> > t = Thing.new :chickens =\> true  
> > =\> #\<Thing:0x31d7b28 @new\_record=true, @attributes={“chickens”=\>true}
> 
> > t.catch\_chickens  
> > NoMethodError: undefined method `catch_chickens' for #<Thing: 0x31d7b28> from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/ active_record/base.rb:1861:in`method\_missing’  
> > from (irb):3
> 
> > Thing.catch\_chickens  
> > =\> [#\<Thing:0x31d3618 @attributes={“id”=\>“1”, “chickens”=\>“1”}]
> 
> > t.eat\_chicken  
> > ArgumentError: wrong number of arguments (0 for 1)  
> > from (irb):5:in `eat\_chicken’  
> > from (irb):5
> 
> >

?\> df  
NameError: undefined local variable or method `df’ for #\<Object:  
0x3349ec\>  
from (irb):7

> > t.eat\_chicken(:booie)  
> > Fox with ID just ate a chicken with name booie  
> > =\> nil
> 
> > t = Thing.new :chickens =\> true  
> > =\> #\<Thing:0x31cb29c @new\_record=true, @attributes={“chickens”=\>true}
> 
> > t.eat\_chicken  
> > ArgumentError: wrong number of arguments (0 for 1)  
> > from (irb):10:in `eat\_chicken’  
> > from (irb):10
> 
> > quit  
> > 14:07:07:~/work/plugins/fox \> script/console  
> > Loading development environment.
> 
> > t = Thing.new :chickens =\> true  
> > =\> #\<Thing:0x31e2ac8 @new\_record=true, @attributes={“chickens”=\>true}
> 
> > t.eat\_chicken  
> > NameError: undefined local variable or method `name' for #<Thing: 0x31e2ac8> from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/ active_record/base.rb:1861:in`method\_missing’  
> > from ./script/…/config/…/config/…/vendor/plugins/  
> > acts\_as\_fox/lib/acts\_as\_fox.rb:36:in `eat\_chicken’  
> > from (irb):2
> 
> >

?\> k  
NameError: undefined local variable or method `k’ for #\<Object:  
0x3349ec\>  
from (irb):4  
17:54:47:~/work/plugins/fox \> script/console  
Loading development environment.

> > t = Thing.new :chickens =\> true  
> > good  
> > =\> #\<Thing:0x31e29b0 @new\_record=true, @attributes={“chickens”=\>true}

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [March 12, 2007, 6:25am UTC](https://www.ruby-forum.com/t/ruby-methods-question/88477/4 "2007-03-12T06:25:38Z")

</div>

I don’t want to pollute the ActiveRecord class by making the  
acts\_as\_chicken available to all of its classes. It must be made  
available only to the sub-classes of the ActiveRecord that has the  
acts\_as\_chicken declaration.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [March 12, 2007, 6:41am UTC](https://www.ruby-forum.com/t/ruby-methods-question/88477/5 "2007-03-12T06:41:40Z")

</div>

On Mon, 12 Mar 2007, removed\_email\_address@domain.invalid wrote:

> I don’t want to pollute the ActiveRecord class by making the acts\_as\_chicken  
> available to all of its classes. It must be made available only to the  
> sub-classes of the ActiveRecord that has the acts\_as\_chicken declaration.

module ActsAsChicken

# stuff

end

class ActiveRecord  
def self.inherited other  
super  
ensure  
other.extend ActsAsChicken  
end  
end

-a

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [March 12, 2007, 2:34am UTC](https://www.ruby-forum.com/t/ruby-methods-question/88477/6 "2007-03-12T02:34:23Z")

</div>

It’s still really unclear what you’re asking (at least to me). Are  
you saying you want acts\_as\_fox to work only if the object has fox ==  
true (and the same for chicken)?

Or, are you talking about single table inheritance? If so, you can  
just add acts\_as\_XXX to your sub-classes as appropriate…

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [March 12, 2007, 9:55am UTC](https://www.ruby-forum.com/t/ruby-methods-question/88477/7 "2007-03-12T09:55:55Z")

</div>

> end  
> end

What is happening in the opened up ActiveRecord class? I am still  
learning Ruby. TIA.
