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
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
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
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
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
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
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
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
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