How to add a method_missing method into ActiveRecord

i want to write a plugin
that support like following

Book.search_by_author_and_description(keyword)

i must hold method_missing to dynamic find books

but ActiveRecord already used method_missing .

how can i add onother method_misng method ?

I believe you can alias the original method_missing, and then add a
new method_missing which calls the original except when your version
is relevant. it would look something like this:

alias :original_method_missing :method_missing

def method_missing(*args)
  case args
    when /normal stuff/
      original_method_missing(args)
    when /new stuff/
      # your code goes here
  end
end

(please bear in mind this is just a sketch.)

···

--
Giles Bowkett
http://www.gilesgoatboy.org

http://gilesgoatboy.blogspot.com

On 12/12/06, ao tianlong <aotianlong.com@gmail.com> wrote:

i want to write a plugin
that support like following

Book.search_by_author_and_description(keyword)

i must hold method_missing to dynamic find books

but ActiveRecord already used method_missing .

how can i add onother method_misng method ?

ao tianlong wrote:

i want to write a plugin
that support like following

Book.search_by_author_and_description(keyword)
i must hold method_missing to dynamic find books
but ActiveRecord already used method_missing .
how can i add onother method_misng method ?

You could alias the existing method_missing, redefine it to capture the cases you are interested in and forward the rest on to the aliased method. Check out Module#alias_method_chain in Rails 1.2:

Tom

What Giles said, except:
   when /new stuff/: #your code
   else original_method_missing(*args,&blk)
Probably makes more sense.

Giles Bowkett wrote:

···

alias :original_method_missing :method_missing

def method_missing(*args)
case args
   when /normal stuff/
     original_method_missing(args)
   when /new stuff/
     # your code goes here
end
end

(please bear in mind this is just a sketch.)

1 class Book
  2 def method_missing(method_id,*params,&block)
  3 print 'original method missing'
  4 end
  5
  6 alias :original_method_missing :method_missing
  7 def method_missing(method_id,*params,&block)
  8 C(params[:comment])print 'my method missing'
  9 original_method_missing(method_id,*prams,&block)
10 end
11 end
12
13 book = Book.new
14 book.tester

its looks like work , but output is
thod missingmy method missingmy method missingmy method missingmy method
missingmy method missingmy method missingmy method missingmy method
missingmy method missintest.rb:9:in `method_missing': stack level too deep
(SystemStackError)
        from test.rb:9:in `method_missing'
        from test.rb:14

any idia?

thank you for your help

···

On 12/13/06, Devin Mullins <twifkak@comcast.net> wrote:

What Giles said, except:
   when /new stuff/: #your code
   else original_method_missing(*args,&blk)
Probably makes more sense.

Giles Bowkett wrote:
> alias :original_method_missing :method_missing
>
> def method_missing(*args)
> case args
> when /normal stuff/
> original_method_missing(args)
> when /new stuff/
> # your code goes here
> end
> end
>
> (please bear in mind this is just a sketch.)
>

You are calling a missing method from within your new method_missing. Infinite recursion ensues.

The following seems to work:

irb(main):001:0> class Book
irb(main):002:1> def method_missing(mtd,*arg,&blk)
irb(main):003:2> puts "Original"
irb(main):004:2> end
irb(main):005:1> alias :original :method_missing
irb(main):006:1> def method_missing(mtd,*arg,&blk)
irb(main):007:2> puts "New"
irb(main):008:2> original(mtd,*arg,&blk)
irb(main):009:2> end
irb(main):010:1> end
=> nil
irb(main):011:0> Book.new.test
New
Original
=> nil

Alex Gutteridge

Bioinformatics Center
Kyoto University

···

On 13 Dec 2006, at 14:47, ao tianlong wrote:

1 class Book
2 def method_missing(method_id,*params,&block)
3 print 'original method missing'
4 end
5
6 alias :original_method_missing :method_missing
7 def method_missing(method_id,*params,&block)
8 C(params[:comment])print 'my method missing'
9 original_method_missing(method_id,*prams,&block)
10 end
11 end
12
13 book = Book.new
14 book.tester

its looks like work , but output is
thod missingmy method missingmy method missingmy method missingmy method
missingmy method missingmy method missingmy method missingmy method
missingmy method missintest.rb:9:in `method_missing': stack level too deep
(SystemStackError)
       from test.rb:9:in `method_missing'
       from test.rb:14

any idia?

thank you

i find the error

original_method_missing(method_id,*prams,&block)

it's misspelled *params as prams

thank you again.

···

On 12/13/06, Alex Gutteridge <alexg@kuicr.kyoto-u.ac.jp> wrote:

On 13 Dec 2006, at 14:47, ao tianlong wrote:

> 1 class Book
> 2 def method_missing(method_id,*params,&block)
> 3 print 'original method missing'
> 4 end
> 5
> 6 alias :original_method_missing :method_missing
> 7 def method_missing(method_id,*params,&block)
> 8 C(params[:comment])print 'my method missing'
> 9 original_method_missing(method_id,*prams,&block)
> 10 end
> 11 end
> 12
> 13 book = Book.new
> 14 book.tester
>
> its looks like work , but output is
> thod missingmy method missingmy method missingmy method missingmy
> method
> missingmy method missingmy method missingmy method missingmy method
> missingmy method missintest.rb:9:in `method_missing': stack level
> too deep
> (SystemStackError)
> from test.rb:9:in `method_missing'
> from test.rb:14
>
> any idia?
>

You are calling a missing method from within your new method_missing.
Infinite recursion ensues.

The following seems to work:

irb(main):001:0> class Book
irb(main):002:1> def method_missing(mtd,*arg,&blk)
irb(main):003:2> puts "Original"
irb(main):004:2> end
irb(main):005:1> alias :original :method_missing
irb(main):006:1> def method_missing(mtd,*arg,&blk)
irb(main):007:2> puts "New"
irb(main):008:2> original(mtd,*arg,&blk)
irb(main):009:2> end
irb(main):010:1> end
=> nil
irb(main):011:0> Book.new.test
New
Original
=> nil

Alex Gutteridge

Bioinformatics Center
Kyoto University