Forum: Ruby on Rails calling dynamic method from symbol or string

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A2c85dc5ee81b12e3cc0a6522e8d079d?d=identicon&s=25 Chris Hall (au5lander)
on 2007-02-26 14:42
(Received via mailing list)
i have several dynamic methods such as:

def assign!

def close!

being added to my models via a plugin.  my question is how might i
call these methods if the method name is passed as a symbol or string
parameter to another method?

def do_something(options = {})
  if options.has_key?(:event)
    # call the dynamic! method specified by options[:event]
    # would it
  end
end

so if i do

model.do_something(:event => :assign)

i want assign! method called
34f26dde337f0a0d2d380e11117e82f6?d=identicon&s=25 Vishnu Gopal (Guest)
on 2007-02-26 15:14
(Received via mailing list)
def do_something(options = {})
 if options.has_key?(:event)
   send(options[:event])
 end
end

See ri Object#send

Vish
A2c85dc5ee81b12e3cc0a6522e8d079d?d=identicon&s=25 Chris Hall (au5lander)
on 2007-02-26 15:30
(Received via mailing list)
i know i need to use object.send

it's just that i am passing in, say { :event => :assign }

where my method is named assign!

i figured out, unless there is an easier way, to do

send "#{options[:event].to_s + "!"}".to_sym

which is ugly in my opinion, so if someone has a prettier way, please
let me know.
34f26dde337f0a0d2d380e11117e82f6?d=identicon&s=25 Vishnu Gopal (Guest)
on 2007-02-26 15:37
(Received via mailing list)
Okay, didn't realize that. Try this :-)

class Symbol
  def +(a)
    (self.to_s + a.to_s).to_sym
  end
end

and then,

send(options[:event] + :"!")

Vish
D0cd6b10e01bacb976b3b815a9c660bc?d=identicon&s=25 Alex Wayne (squeegy)
on 2007-02-26 16:49
Vishnu Gopal wrote:
> Okay, didn't realize that. Try this :-)
>
> class Symbol
>   def +(a)
>     (self.to_s + a.to_s).to_sym
>   end
> end
>
> and then,
>
> send(options[:event] + :"!")
>
> Vish

This is way more complicated then it needs to be.  You don't need to
hack the Symbol class at all.  all you need is:

  send "#{options[:event]}!"

If a string is entirely dynamic you don't need quotes. So this:

  "#{ foo.bar + '123' }"

is the same as:

  foo.bar + '123'

Use the dynamic string for what its good for, combining static parts
with changing parts:

  "#{foo.bar}123"
A2c85dc5ee81b12e3cc0a6522e8d079d?d=identicon&s=25 Chris Hall (au5lander)
on 2007-02-26 17:50
(Received via mailing list)
yeah, much cleaner

send "#{options[:event]}!"

for some reason, i thought send had to take a symbol

now, my other problem is this...

the method i am sending to accepts a block.  how can i pass the block
off to send?

i currently using this way, method i am sending gets called, but the
block isn't so i figure i am missing something

def do_something(options => { :event => nil, :by => nil })
  # validate options
  ...
  send("#{options[:event}!") do
    # expecting this to get passed to the method in send
    audit(options[:by])
  end
end

# dynamic method
def assign!
  ..
  yield(self) if block_given?
end

def audit(user)
  ...
end
A2c85dc5ee81b12e3cc0a6522e8d079d?d=identicon&s=25 Chris Hall (au5lander)
on 2007-02-26 20:21
(Received via mailing list)
nm, figured it out

def do_something(options => { :to => nil, :by => nil, :event => nil,
:audit => true })
  ...
  event_params = ...
  prc = options[:audit] ? Proc.new { |o| o.audit(options[:by] } : nil
  send("#{options[:event]}!", event_params, &prc)
end

def audit(user)
  ...
end

def some_event!(additional_params)
  ...
  yield(self) if block_given?
end
This topic is locked and can not be replied to.