
-----------------------------------
wtd
Fri Sep 23, 2005 10:30 pm

Tip/Trick: a bit of Javascript in Ruby
-----------------------------------
In Javascript, what look like properties of an object can also be accessed as if they were part of an associative array (hash).

foo.bar

Is the same as:

foo["bar"]

And we can go the other way.

Now, Ruby doesn't work the same way normally, but we can hack it rather simply to do the same thing.

Now, in Ruby, when we have something like:

foo.bar

It's a call of the method "bar" on the object "foo".

So, how can we turn that into a hash lookup?

Well, let's look at what happens when a method is called that doesn't exist.

insaneones@ubuntu:~ $ irb
irb(main):001:0> class Foo
irb(main):002:1>    def bar
irb(main):003:2>       "hello"
irb(main):004:2>    end
irb(main):005:1> end
=> nil
irb(main):006:0> Foo.new.bar
=> "hello"
irb(main):007:0> Foo.new.baz
NoMethodError: undefined method `baz' for #
        from (irb):7
irb(main):008:0>

We get an exception, which makes sense.

So, how can we deal with this?

Wel, Ruby's very dynamic nature means that it shouldn't surprise anyone to find out there is a way.  If we define a method called method_missing which takes a method name and the arguments sent to it, that method will be called when an undefined method is called.

Behold.  :)

class Foo
   def initialize
      @internal = {}
   end

   def method_missing(name, *args)
      name = name.to_s
      if name =~ /\=$/
         @internal[name.sub /\=$/, ''] = args.first
      else
         @internal[name]
      end
   end
end

Questions?

-----------------------------------
timmytheturtle
Sun Sep 25, 2005 12:34 am


-----------------------------------
I got a question, since I'm still learning Ruby what is this ~ /\=$/. I havent seen it before

-----------------------------------
wtd
Sun Sep 25, 2005 1:07 am


-----------------------------------
I got a question, since I'm still learning Ruby what is this ~ /\=$/. I havent seen it before

/\=$/

Is a regular expression.  Consider the 

/ /

As being like:

" "

For regular expressions.  :)

The actual regular expression is:

\=$

This is a pattern.  The backslash escapes the = sign.  As it turns out, I didn't need the backslash.  Backslash is meant to escape characters which otherwise would have some significant meaning.

The $ indicates the end of the string.

The pattern therefore specifies an equals sign at the end of a string.

=~

This is the match operator which checks if a string matches the pattern (regular expression).

-----------------------------------
timmytheturtle
Sun Sep 25, 2005 1:11 am


-----------------------------------
Alright makes sense, thanks wtd. This language is starting to become easier than I first expected

-----------------------------------
wtd
Sun Sep 25, 2005 1:36 am


-----------------------------------
Nifty.

-----------------------------------
Tony
Mon Sep 26, 2005 11:15 am


-----------------------------------
nifty indeed. Catching "missing" Rails pages :wink:

-----------------------------------
Tony
Wed Nov 16, 2005 4:57 pm


-----------------------------------
today I was building integrated help feature for my applicatioin. Quite simple, it's just a load of (?) links that would call help/category/topic controller/method/id, and that should render appropriate information. Hardcoding reference information into a controller is a pretty horrible idea.


def method_missing(name, *args)
	category = name
	topic = params
So now when you call help/foo/bar, Rails will attempt to locate foo.yml file, and find bar entry within the file. viewtopic action then renders the page.

Furthermore if there's a complicated topic to be explained, an appropriate method could be created (it will no longer be missing) and another set of instructions will be used to render a specialized page.

Ofcourse the above code looks out for missing files and entries, so looking up an arbitrary entry will not break the application.

-----------------------------------
wtd
Wed Nov 16, 2005 5:42 pm


-----------------------------------
YAML::load(File::open("helpinfo/" + category.to_s + ".yml")

And we clean that up a bit...

YAML::load(File::open("helpinfo/#{category}.yml")
