Quick Tip: Rails 2.1 Time Zones
September 13th, 2008
My last quick tip involved setting your time zone in Ubuntu Hardy, so now, how do you set your time zone in a Ruby on Rails application? Rails 2.1 makes it much easier to manage time zone settings than it was previously.
Add the following to your environment configuration file:
config/environment.rb
config.time_zone = 'Arizona'
Replace Arizona with your own time zone. You can find a list of valid values by running any of the following rake tasks:
rake time:zones:all
rake time:zones:local
rake time:zones:us
Your data will still be stored in UTC time, but it will be converted into the specified time zone when it is type cast on retrieval.
Update: If you set both your server’s time zone and your applications time zone then you may see some incorrect times. I believe this is because you’ll be storing local times and the Rails app will be trying to convert them to local – a double conversion. So be careful.
References
Quick Tip: Setting time zone on Ubuntu Hardy
September 13th, 2008
I’ve been pretty enamored with SliceHost recently. They make it very easy to setup a slice, configure it and get your product deployed quickly (I’m down to 30 min). I hadn’t noticed until just recently that I’ve never set a time zone on any slice I’ve configured. So, here’s how you do it, simple and easy.
- SSH into your slice
- Run this command:
sudo dpkg-reconfigure tzdata - Select your geographic area and location
That’s it, hope it helps!
If you want your own slice, consider using my Slicehost referral link. Thanks!
Quick Tip: Form Partials
September 1st, 2008
Partials are a great way to keep your view code separated logically. Prior to Rails 2.1 if you wanted to reuse a form partial in, for example, a new and edit view, then you needed to pass the form into the partial somehow.
Given the following form partial:
views/users/_form.html.erb
<div>
<%= form.label :name -%>
<%= form.text_field :name -%>
</div>
Pre-Rails 2.1
You might consider passing the form in as a local, like so.
views/users/new.html.erb or views/users/edit.html.erb
<% form_for @user do |form| -%>
<%= render :partial => 'form', :locals => { :form => form } -%>
<% end -%>
Rails 2.1
There’s now a shortcut for this common method of rendering a form partial.
views/users/new.html.erb or views/users/edit.html.erb
<% form_for @user do |form| -%>
<%= render :partial => form -%>
<% end -%>
Nice! Cleans things up a bit.
Quick Tip: SSH Backspace
August 26th, 2008
I just ran across this informative post by Jonathan Tron that solved an annoyance I’ve had for a while: backspace not doing what I want when I use SSH.
Change your Terminal Preferences
- In Terminal, select Preferences | Settings | Advanced.
- Select ‘Delete sends Ctrl-H’
You may need to do this again if you change your terminal style.
Specify a setting for nano
- On your server open ~/.nanorc
- Add ‘set rebinddelete’
And now you should have backspace working correctly for at least a few things…
Quick Tip: Route Associations
August 26th, 2008
Are you used to writing your routes like this?
map.resources :notes do |notes|
notes.resource :author
notes.resources :comments
notes.resources :attachments
end
Don’t fret, there may be hope for you yet. For these simple routes you can use the has_one or has_many route association options.
- has_one – use it for a singleton resource
- has_many – use it for plural resources
Refactored routes
map.resources :notes, :has_one => :author, :has_many => [:comments, :attachments]
Give it a try!
Keep in mind I said simple. If you’re doing something more complex they might not be the best choice.
Additional Resources
Quick Tip: has_many :through => checkboxes
August 25th, 2008
It’s really easy to create a many-to-many relationship that can be assigned through checkboxes. Check it out!
Let’s say you have Users and Groups. A User can belong to a Group and a Group can have many Users – we call this a Membership, like so (migrations omitted for brevity):
app/models/user.rb
class User < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :groups, :through => :memberships
end
app/models/group.rb
class Group < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :users, :through => :memberships
end
app/models/membership.rb
class Membership < ActiveRecord::Base
belongs_to :group
belongs_to :user
end
We can now assign groups to members in a relatively easy manner with no extra work needed in the models. Behold!
app/views/users/edit.html.erb
<h1>User <%= @user.id -%></h1>
<h2>Group Memberships</h2>
<% form_for @user do -%>
<% Group.all.each do |group| -%>
<div>
<%= check_box_tag :group_ids, group.id, @user.groups.include?(group), :name => 'user[group_ids][]' -%>
<%= label_tag :group_ids, group.id -%>
</div>
<% end -%>
<%= submit_tag -%>
<% end -%>
Errr… something like that. Anyway, the important thing to note is the use of group_ids. The values will get submitted as group_ids, a member of the User. Where did that come from? We don’t have an attribute or method on the model for it, so where’d it come from? Well, seems that it is auto-generated for you to allow something like I just showed.
When this form is submitted, any checked Groups will be associated through Memberships to the User by way of the magic *_ids= method. Should work the other way too with user_ids checkboxes on a group. No extra code needed. Awesome, right?
Bonus: If you uncheck all the checkboxes, then nothing gets posted, doh! So make sure to merge a default value with your parameters like this to ensure the *_ids= method gets called:
app/controllers/users_controller.rb
@user.attributes = {'group_ids' => []}.merge(params[:user] || {})
Super Bonus: When you’re defaulting the group_ids in the controller make sure to use the key as a string, not a symbol. Or if you do use a symbol then make it a Hash with_indifferent_access.
Super Monkey Ball: A monkey encased in a ball who collects bananas.
Quick Tip: Capistrano SSH Ports
August 24th, 2008
If you have changed the SSH port number on your server, then you need to let Capistrano know how to connect. Luckily, it’s pretty easy.
Add the following to your deployment file, replacing 8888 with your port number.
config/deploy.rb
ssh_options[:port] = 8888
This will apply that port number to connections made by Capistrano. If you need to specify the port for each server (app, web, db) then tack it on to the end of their declarations.
role :app, "65.74.169.199:8030"
role :web, "65.74.169.199:8031"
role :db, "65.74.169.199:8032", :primary => true
I haven’t verified that one, but it supposedly works. Happy deployments!
Quick Tip: SSH Config
August 22nd, 2008
It’s easy to create shortcuts for all those servers you need to SSH into. There should be a file in your .ssh directory called config. Simply add a few lines to this file and you can refer to those servers by their short name.
Example (~/.ssh/config)
Host foo
Hostname some.long.hostname.you.cannot.remember.com
User myuser
Port 1234
Now you can use your new host when you SSH.
ssh foo
If you want to get even fancier, read the man page for additional options.
man ssh_config
Setup as many as you need and free yourself from SSH hostname hell!