What's New in Edge Rails: Source Code Annotations

Posted by ryan
at 2:54 PM on Monday, February 26, 2007

No, not the heavyweight annotations that you see in Java or C# – these are just a way to denote the todos and other mental reminders we often litter in our code comments:

1
2
3
4
5
6
7
8
9
class ContactsController < ApplicationController
  
  # TODO: factor out model verification to a filter
  # OPTIMIZE: optimize this
  # FIXME: it's broken
  def index
    ...
  end
end

With this new rake task we can now spit out a list of items we’ve annotated:

1
2
3
4
5
rake notes
app/controllers/contacts_controller.rb:
  * [ 3] [TODO] factor out model verification to a filter
  * [ 4] [OPTIMIZE] optimize this
  * [ 5] [FIXME] it's broken

You can also only list the annotations of a particular kind with rake notes:todo, rake notes:optimize and rake notes:fixme.

Update: JD has this tip to get this rake task installed in your non-edge Rails app. Thanks, JD!
1
2
cd lib/tasks && \
  wget http://dev.rubyonrails.org/export/7553/trunk/railties/lib/tasks/annotations.rake
Update: You can now search for a custom annotation by passing in the annotation text as follows:

rake notes:custom ANNOTATION=MYTAG

tags: rubyonrails, rails

What's New in Edge Rails: A Better Way to Access Your Helpers

Posted by ryan
at 2:14 PM on Monday, February 26, 2007

If you’ve any sort of organizational sense to you at all chances are you’ve got quite a few helpers tucked in your app/helpers directory (not the stock ones that go one-to-one with your controllers, but other custom ones you’ve written to handle various other common tasks). If so, your application controller probably also has quite a few helper statements to make them available:

1
2
3
4
5
6
7
class ApplicationController < ActionController::Base

  # Our many helpers that need to be available throughout the app
  [:formatting, :highlighting, :i18n].each { |h| helper h }

  ...
end

We’ve now got a convenient way to bulk include our helpers.

1
2
3
4
5
6
7
class ApplicationController < ActionController::Base

  # Make all helpers in app/helpers/**/ available
  helper :all

  ...
end

Update: Feb. 26th: I previously thought you had to have helper sub-directories to get them properly loaded, but DHH has corrected me. Any and all helpers in your helper directories will get pulled in

And to top things off this is now the default behavior – meaning that all helpers in your helpers directory are automatically included for you. (Hey – you wanted opinionated software)

tags: rubyonrails, rails

What's New in Edge Rails: Stop Littering In Your Environment File

Posted by ryan
at 9:37 PM on Thursday, February 22, 2007

Rails got a nice little bit of organizational mojo today. I’m sure we all have litterings of various configs at the bottom or our environment.rb files, like inflections, mail configs etc… Here’s the bottom of one of my projects’ environment files:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Mail
ActionMailer::Base.delivery_method = :sendmail
...

# Exception notification
ExceptionNotifier.exception_recipients = %w([email protected])
...

# Various engine configs
...

# Custom date formats
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(:concise => "%d.%b.%y")
..

Pretty ugly after the structure and conciseness of the Rails::Initializer block, huh? Well now you can place your little bits of initialization code in a config/initializers/ directory and they will get pulled in and loaded after the Rails::Initializer runs.

So now instead of polluting your environment file you can create a single file for each initialization task:

config/initializers/mail.rb:
1
2
ActionMailer::Base.delivery_method = :sendmail
ActionMailer::Base.default_charset = "utf-8"
config/initializers/date_formats.rb:
1
2
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(:concise => "%d.%b.%y")
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(:medium => "%b %e, %Y")

Now go clean your environment file, filthy lil’ runts.

It should be noted that these initialization files are loaded at startup for all environments, it is not a place to put environment-specific (dev, test, prod etc…) configs

tags: rubyonrails, rails

What's New in Edge Rails: ActiveRecord Caching Provided in Actions

Posted by ryan
at 9:36 PM on Wednesday, February 21, 2007

The flavor du jour in edge rails is definitely caching (see here and here). Some of yas commented on how it seemed kind of hackish to add these caching statements in the view, or even as a filter around your controller actions. Well, now ActiveRecord caching is enabled by default for all your controller actions.

What I don’t yet see is an easy way to disable this caching in your actions. Is there even a case where you want to disable this? Just thinking out loud here…

tags: rubyonrails, rails

What's New in Edge Rails: Cookie Based Sessions are the New Default

Posted by ryan
at 11:15 AM on Wednesday, February 21, 2007

Edge rails now has cookie-based session stores enabled by default instead of the file based session store that was the previous default. Why the change? Mostly performance, it seems. Cookie-based sessions are just faster to retrieve and process than hitting the file-system on every request. Plus, I would imagine they scale considerably better as they’re persisted on the client side and have no server-side persistence requirements.

The caveat? Cookies are generally limited to 4K in size. While not an issue for most (proper) usage of the session, this could be a legitimate limit for some scenarios. If your app abuses the session so, you’ll need to decide on a different session store. Your other options are, of course:

Resources

Update: Feb, 22nd 2007

To get your brand new cookie-based session up and running, make sure this bit is in your environment.rb:

1
2
3
4
config.action_controller.session = { 
  :session_key => '_my_app_session', 
  :secret      => 'some_really_long_and_hashed_key' 
}

tags: rubyonrails, rails

What's New in Edge Rails: Expanded Caching Scope

Posted by ryan
at 10:06 PM on Tuesday, February 20, 2007

Last week I pointed out the new ActiveRecord caching feature that lets you cache all ActiveRecord calls on a specific model:

1
2
3
4
User.cache do
  me = User.find(1)   # DB hit
  again = User.find(1)   # Cache hit
end

That’s great, but it only works on the model for which the cache block is applied. If you have a block of code that accesses multiple model classes, you’d have to either nest several cache blocks or this new top-level cache statement :

1
2
3
4
5
6
7
8
9
10
11
ActiveRecord::Base.cache do

  # DB hits
  me = User.find(1)
  companies = Company.find(:all)

  # Cache hits
  me = User.find(1)
  companies = Company.find(:all)

end

and all queries to any active record models within the block will be cached.

tags: rubyonrails, rails

What's New in Edge Rails: .rhtml and .rxml to Die a Slow and Painful Death

Posted by ryan
at 9:52 PM on Tuesday, February 20, 2007

In a bout of semantic house cleaning it’s been revealed that the .rhtml and .rxml file extensions will be deprecated in favor of .erb and .builder, respectively.

Why such a change – well, .rhtml files are not strictly html files. They are generic embedded ruby files that can be used for email templates, csv files, vcards etc… .erb is just a more generic, accurate extension for the file type. The same goes for .rxml – it can be used for more than just xml files. Think of all the rss feeds you’ve written with rxml files. Now you can stop being tied down by the limited .rxml file extension and can start using .builder.

Don’t worry about your existing app breaking though, the ‘old’ extensions won’t be fully deprecated until Rails 3.0. ... whenever that might be.

tags: rubyonrails, rails

What's New in Edge Rails: Mime::Type Convenience Methods

Posted by ryan
at 1:14 PM on Thursday, February 15, 2007

Everybody loves the goodness of respond_to, which encapsulates the mime type of the request into a nice little structure, but there are other places where querying against the request mime-type is useful. For instance, applying different filter behaviors depending on the request type is often useful. Starting today you now have a convenient way of doing so with the new request.format.html?, request.format.xml? etc… convenience methods.

1
2
3
4
5
6
7
8
9
class MyController < ApplicationController

  # Toggle authentication method based on request type
  before_filter do |c|
    c.use_session_auth if c.request.format.html?
    c.use_token_auth if c.request.format.xml?
  end

end

Or you can use these methods to provide a clean way of turning sessions off (from the changeset example):

1
2
3
4
5
6
class MyController < ApplicationController

  # Turn off sessions for all non-html requests
  sessions :off, :if => Proc.new { |request| not request.format.html? }

end

All in all a tidy way to get at that pesky but deterministic request mime-type. These aren’t just limited to the stock recognized mime-types, they can also be used for any mime-types you’ve registered yourself:

1
2
3
4
5
6
7
8
9
# Because I think we all agree I deserve my own mime-type
Mime::Type.register "text/ryan", :ryan

class MyController < ApplicationController

  # Turn off sessions for all ryan requests
  sessions :off, :if => Proc.new { |request| request.format.ryan? }

end

tags: rubyonrails, rails

What's New in Edge Rails: ActiveRecord Explicit Caching

Posted by ryan
at 9:27 AM on Wednesday, February 07, 2007

A tiny but useful update was just added to edge Rails that lets you specify a block for which a query cache will be present. The query cache will cache select statements and guarantee that identical select statements will only hit the database once during the block. Any inserts, updates or deletes will clear the cache as the result of any cached queries may have changed.

1
2
3
4
5
6
User.cache do
  me = User.find(1)   # DB hit
  again = User.find(1)   # Cache hit
  me.update_attribute(:name => 'Not Ryan')  # Cache cleared
  me = User.find(1)   # DB hit
end

While you might not think this is very useful in your various controller methods which should be of limited scope, think of your views that may call the same authentication queries several times within the view body. While a simple @is_admin || = user.get_role('ADMIN') custom cache mechanism would work just fine, you now have the options to wrap your view within a query cache and have it handled for you.

The query cache is keyed on the raw SQL statement, so it’s very minimalist in its complexity. It doesn’t know that your identical query with different order conditions is the same query as before – and will hit the db again. It only caches identical SQL statements, literally.

tags: rubyonrails, rails, activerecord caching