Friendly has gotten a bunch of attention since we released it last week. We're already over 200 watchers on the github project. Thanks to everybody who wrote or tweeted about it.

Since then, I've been hacking away on features that were sorely missing. Today, I've got a handful of those to release.

Scopes

The star of Friendly 0.4.0 is scopes. Here's how they work.

Assuming the following model:

class Post attribute : author , String indexes : author , : created_at end

To create a scope on the fly, just call YourDocument.scope.

@ scope = Post . scope ( : author => " Stewie Griffin " )

You'll get back an instance of Friendly::Scope. That object supports almost all of the query and creation API that a Document class does.

@ scope . all == Post . all ( : author => " Stewie Griffin " ) @ scope . first == Post . first ( : author => " Stewie Griffin " ) @ scope . build == Post . new ( : author => " Stewie Griffin " ) @ scope . create == Post . create ( : author => " Stewie Griffin " )

It's also possible to create reusable, named scopes.

Named Scopes

The named scope syntax is pretty well identical to ActiveRecord's:

class Post named_scope : by_stewie , : name => " Stewie Griffin "

Then, you can get an instance of that scope with:

Post . by_stewie

A named scope instance is just another instance of Friendly::Scope. Unlike with ActiveRecord, you must call scope.all to get the target of the scope. You can also use any of the other scope methods:

Post . by_stewie . all == Post . all ( : name => " Stewie Griffin " ) Post . by_stewie . create . name == " Stewie Griffin "

Named scopes are also chainable arbitrarily.

class Post named_scope : recent , : order! => : created_at . desc end Post . by_stewie . recent == Post . all ( : name => " Stewie Griffin " , : order! => : created_at . desc )

If there are conflicts, the right-most scope takes precedence.

class Post named_scope : by_peter , : name => " Peter Griffin " end Post . by_stewie . by_peter == Post . all ( : name => " Peter Griffin " )

Associations

Currently, only has_many associations are supported.

class User has_many : posts end class Post attribute : user_id , Friendly :: UUID indexes : user_id , : created_at end

The cool thing is that associations are just another instance of Friendly::Scope.

User . new . posts

So, all of the Friendly::Scope methods are supported. You can also chain named_scopes on an association.

@ user = User . create @ user . posts . recent == Post . all ( : user_id => @ user . id , : order! => : created_at . desc )

Those are the basics. Check out the docs for Friendly::Scope and Friendly::Associations::Association for more info.

Misc Stuff

Jeff Rafter contributed a few awesome patches.

Most notably, Friendly was previously unable to create an index table for a field of type Friendly::UUID. Jeff added support for mapping custom types to database field types.

There are no docs yet, but the method signature for Friendly::Attribute.register_type should be clear enough. For most purposes, though, the big win is that Friendly should now be able to create tables for you more consistently.

Jeff also added a spec/config.yml for putting your spec db settings in.

Get it while it's hot!