ManOpen – Mac OS X Man Pages Viewer
I just wanted to throw a spotlight on this app ManOpen. I use it quite often. It’s much easier to read than using terminal.
I just wanted to throw a spotlight on this app ManOpen. I use it quite often. It’s much easier to read than using terminal.
Check out Crank. It’s a wicked cool way to get RSS and HTML output from SVN repositories. Especially when used in post commit hooks.
I finally had some time to re-organize the SVN repo and create a rails installer. Here’s the install command / path:
ruby script/plugin install svn://rubyforge.org/var/svn/rubyamf/tags/current/rubyamf
The new repo is laid out with the suggested standard directories.
/trunk -> development
/tags -> previous revisions. Always defined like: rubyamf_{version}_{revision}
/tags/current/rubyamf -> rails installer directory
Also; thanks to Simeon Bateman for a quick tip on re-arranging the SVN for some better organization, tags for previous version, and the rails installer.
Check out the screencasts section on the wiki. I just added a bunch more. They’re nothing intense but I included a couple Flex examples as well.
RubyAMF-1.2 folks.
With so many requests for respond_to/format.amf functionality, I’m supporting it. Here is an example of using it in a class:
def MyController < ActionController::Base
def list
respond_to do |format|
format.amf { render :amf => User.find(:all) }
end
end
end
You also need to declare a new mime type in the rails/config/envirionment.rb file (towards the end of the file). Like so:
Mime::Type.register "application/x-amf", :amf
Nice new feature for SSR. Authentication failure events. Heres an EX:
import org.rubyamf.remoting.ssr.*;
var service = new RemotingService('http://localhost:8024/gateway.rb','some.package.MyService',3);
service.setCredentials('userid','pass');
service.addEventListener(FaultEvent.AUTHENTICATION_FAILED, handleAuthFailure);
function handleAuthFailure(e:*)
{
trace("AUTHENTICATION FAILED");
}
There are a couple ways you can tell the Flash client that authentication failed. Here are RubyAMF examples:
EX: 1 import RUBYAMF_SERVICES + 'fault_object' class MyService def _authenticate(user,pass) FaultObject.new(1,'Authentication Failed') end end EX: 2 class MyService def before_filter @auth = false end def auth_fail return FaultObject.new(1, 'Authentication Failed') end def _authenticate(user,pass) if #someprocessing @auth = true else false #returning false from _authenticate triggers the exception back to the flash player as well end end def myRestrictedMethod if !@auth auth_fail else #some processing end end end
You can also trigger authentication errors from AMFPHP. EX:
<?php
class MyService
function someMethod
return {'faultString' => 'Authentication Failed', 'faultCode' => 1};
end
end
?>
All of these examples will trigger the authentication failed event. Using this for authentication failure is nice so that you can handle authentication errors in on place. Not having to handle them in every onFault handler.
Here is an introduction to RubyAMF on Rails screencast. Definitely check it out.
Update: here is a compressed version of the same screencast
Couple notes that weren’t mentioned in the screen-cast.
- RubyAMF works the same with Flex, Flash 9 / Flash 8.
- Specifying recordset formats is not neccessary for Flex RemoteObject’s.
- Around filters, and Class filters will be implemented in a future release
- Having to restart Rails is a pain, sometimes it’s needed. sometimes not. A fix for this will be released as well.
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