RubyAMF 1.0 – Stability + Rails

See the release notes or keep reading.

With RubyAMF 1.0 I’m bringing a Rails Remoting gateway into the mix. I know some people thought it was cool that RubyAMF was not a Rails hitch-hiker. I thought so too. But I think what I’ve done is a really good rails implementation, and it will only get better folks. And I’m still supporting the standalone application servers bundled with RubyAMF.

The RubyAMF standalone app server is usually faster than using it through Rails. And quite honestly, most of the time a Flex app doesn’t need Flex and HTML versions. So why use Rails? ActiveRecord through Rails is dead slow, using straight mysql is so much faster.

The Rails gateway is really just hooking into everything else I’ve done with RubyAMF and wasn’t a lot of work to get it into Rails. Keep reading for a breakdown of everything that this gateway brings to Rails.

Gateway and Services Path
The Gateway for RubyAMF is located here: http://localhost:3000/rubyamf/gateway. The gateway is just a controller with a “gateway” action. So technically you could put it in any controller as any action. There is a small amount of code in the action so I’d just leave this as the default.

The services path is app/controllers so RubyAMF maps requests to your controller. Intelligently though.

Sniffing a RubyAMF Remoting request
What if you call a method on a controller that doesn’t send a correct response for AMF? RubyAMF injects an instance variable in your class called “@is_amf”, which is set to true when the RubyAMF gateway is hit. This helps so you can place some logic in your controller methods to respond to AMF. Heres a quick example:

class MyTestController < ActionController::Base
 def test
  if @is_amf
   return User.find(1)
  else
   #do some more processing, etc
  end
end

So that helps a lot. No more duplication of methods just to return AMF only content. And no more creating service classes just to house methods that already have functionality in your controller. Cool.

Remoting parameters map to params[] hash
Another feature is parameter hash mapping. From your remoting request, parameters get mapped into the params[] hash. So if you send 2 parameters, they get mapped to the params[0], params[1] hash.

The reason for this is that if I didn't map them into params, they would have to be declared in the method definition like so "def show(id)". But that will break Rails if say; you're viewing it through a browser or an XML REST there will be no parameters so it would break. You can shut this functionality off in the rubyamf_controller and have it be mapped into method parameters as well.

There isn't a way to supply symbols for hash keys. Like params[:id], because the parameters from remoting are just the values and no names associated with them.

Handle faults easily and effectively
Handling Model errors gracefully and sending back a useful error object to Flash is cake too. Here's an example:

require RUBYAMF_HELPERS + 'fault_object'
class MyTestController < ActionController::Base
  def test
   if @is_amf
    @u = User.find(1)
    if @u.update_attributes(:id => 45) == false
     return FaultObject.new(1, 'Error updating ID')
    end
   end
  end
end

This is a pretty simple example, but the point is that fault objects get mapped to your onFault handlers correctly in Flex or Flash. An object with the code, message, faultCode, and faultString properties are set.

Not only can you specifically return a FaultObject, but any exception that happens in rails will get sent back to Flash as a valid FaultObject. No more shots in the dark.

Why no REST with "render :amf => @ar.to_amf"?
I thought about doing this. There is one problem. HTTPRequest doesn't expect AMF data as a response. I started to write a wrapper for HTTPRequest to allow AMF as a response. And internally I would deserialize the AMF and provide that as a result.

But then I got thinking. Why the hell am I doing this? Flash Remoting is already implemented. Just because some kid wants to call localhost:3000/controller/show/4.amf because it looks cool doesn't mean it's the best implementation. In the case of Flash Remoting it's not a good option. Don't be a REST snob and assume it would be better.

So for now, @is_amf is how you sniff for a RubyAMF request. In the future I might implement a "render :amf => obj". But I think right now people would be confused in thinking it's REST, which it's not. So just exposing it like this at first and how to use it is key.

ActionController Filters
Most filter types are supported. Here is a list of supported ones:

-before_filter

-append_before_filter

-prepend_before_filter

-before_filter{|controller| ...}

-append_before_filter{ |controller| ...}

-prepend_before_filter{ |controller| ... }

-after_filter

-append_after_filter

-prepend_after_filter

-after_filter{ |controller| ... }

-append_after_filter{ |controller| ... }

-prepend_after_filter{ |controller| ... }

-skip_filter

-skip_after_filter

-skip_before_filter

After filters aren't enabled by default. You must call self.allow_after_filters in your action. That tells RubyAMF to execute all after filters. This was done because most of the time after filters won't be executed. If you do allow after filters, make sure to use @is_amf in one of the after filters and return a valid object to Flash.

A filter can be halted at any time by returning false. If it is halted, an exception is thrown to the player.

I don plan on implementing around filters and class filters. That will be in a another release soon.

Authentication
Yes, authentication is in place. On the client side you need to use either setCredentials or addHeader. In your controller action you can call amf_credentials(). That returns a hash with the username / password set in it ({'username' => 'whatever', 'password' => 'whatevet'})

It should be simple to use authentication plugins as well. You'd just have to update the plugin to use the new amf_credentials method as a way to get the username and password.

Sessions
Sessions should work fine with Rails. I currently don't have sessions in the standalone application server, but will possibly put them back in.

So now that RubyAMF is stable, and there are multiple ways of using it. There are a couple things left needing to be done.

1. One thing I need is some help testing RubyAMF Rails plugin as much as possible, finding what situations may break it, hearing if you like it and what could be changed, etc.

2. Screencasts, tutorials, blogging. (hopefully not just from me. Help!). PS. RubyAMF and myself are making our 2 chapter debut in an upcoming Flex book.

3. C extension. I've been putting this off, like way off. RubyAMF needs to be stable and production quality before even worrying about the C extension. It will happen though folks. And now that 1.0 is done, you can expect me to be a little more serious about it.

4. Build some apps with it. Did you know you can use rubyosa (An Applescript bridge for Ruby) to control apps on your mac? Check it out.

In case you didn't hear - RubyAMF is now under an MIT license. All Free. Stay tuned for whatever the hell else comes up. And get on the forums, or mailing list. I will be putting as much documentation as I can on the wiki but it might take me a couple days to get it all straightened out and the way I like it. So if there are questions, use one of the two.

- Aaron

flexonrails.net » Blog Archive » RubyAMF 1.0 Released - Now with Rails Remoting said,

July 5, 2007 @ 21:07

[...] makes it possible to use AMF right inside your controllers (i.e., no need for service classes).  You can read all about it here.  Aaron has also posted a great screencast tutorial on getting started with RubyAMF on [...]

Gnana said,

July 10, 2007 @ 07:20

Great work.

How does it compare with WebORB for Rails ?

I am interested in a screencast showing Flex and RubyAMF in action.

Thanks and keep up the good work!

-gnana

aaron said,

July 15, 2007 @ 17:12

It’s comparable to WebORB. I’m not going to go into wether or not it’s better. It’s just different. I feel the workflow is much easier.

Robert I. said,

July 22, 2007 @ 00:38

After a day to get Flex2 to talk to Java using OpenAMF, EJBs, and GlassFish, I thought it was pretty cool when I finally did get it to work. Compared to Struts, Flex2 and OpenAMF is a walk in the park.

Until I stumbled upon your site. HOLY S!#$%@, I was up in minutes and not one F!@#%$&* xml config file in sight.

I for one was a bit skeptical about RoR due to its performance compared to Java objects pre-loaded in the JVM, but RubyAMF with Mongrel is actually pretty good.

“…the workflow is much easier” is a huge understatement in my book. WebORB requires xml config files to work, RubyAMF doesn’t. RubyAMF ROCKS!!!!

aaron said,

July 22, 2007 @ 07:30

Hey Robert, Thanks for checking out RubyAMF. Keep rocking.

Steve said,

October 10, 2007 @ 06:46

Hi There, I am a FLEX N00b but I am well versed in rails. I am really interested in using flex as my view layer. One thing I noticed in your screencast was that the controller you called didn’t specify the action it was calling.

In FLEX do you normally create a different service object for each crud action? How do you pass the :id to properly route to a show?

If this is seriously naive stuff can you point me in the right direction to read more?

aaron said,

October 10, 2007 @ 11:03

@Steve, I’d say check out this simple hello world app (http://code.google.com/p/rubyamf/downloads/list)

Sorry but those screencasts are really old. Hang in there we’re al working hard to update everything.

RSS feed for comments on this post · TrackBack URI

Leave a Comment