By default in Rails, a resource has a URL that indicates what kind of resource it is, and what its id number is. So you might have a website with information about bands, and the URL www.music.com/bands/123 might refer to the Rolling Stones.
For lots of reasons it'd be preferable to be able to have www.music.com/bands/the-rolling-stones instead. Here's a straightforward way to do this - but note, as things stand it will break any incoming links you might have.
The basic idea is that rather than retrieving a record based on its id, we retrieve records based on another field that corresponds to the desired URL. We'll call this field munged_name.
So first we need to create the following migration
class AddMungedNameToBands < ActiveRecord::Migration
def self.up
add_column 'bands', 'munged_name', :string
end
def self.down
remove_column 'bands', 'munged_name'
end
end
Then, to the Band model, add
def to_param
name.gsub(/\s/, "-").gsub(/[^\w&-]/,'').downcase
end
With Rails, every object has a to_param method. By default, ActiveRecord objects return the object's id. Here, we override that with a method that returns the band's name, with any spaces replaced with dashes (the first regexp), any punctuation stripped out (the second regexp), and converted to lower case. This is apparently known as munging. So now, applying the to_param method to a Band object returns the munged form of the band's name
Also to the Band model, add
def calculate_munged_name
self.munged_name = to_param
end
This sets the munged_name field and will be called after record has been created.
To the create and update methods of the bands controller, add
@band.calculate_munged_name
just after @band has been set
Given that we already have records in our database we need to give them munged names, so at the console do
>> Band.find(:all).each do |b|
b.calculate_munged_name
b.save
end
Finally, in the show, edit, update, and destroy methods of the bands controller, change
@band = Band.find(params[:id]
to
@band = Band.find_by_munged_name(params[:id])
Friday, January 30, 2009
Tuesday, September 30, 2008
Setting up ssh keys
At the command line on your local computer
1. ssh-keygen -t rsa
2. Enter a passphrase
3. scp ~/.ssh/id_rsa.pub user@remotehost.com:~/.ssh/id_rsa_temp.pub
(will need to enter your password for user@remotehost here)
Then
4. ssh user@remotehost
5. chmod ~/.ssh 700
6. cat ~/.ssh/id_rsa_temp.pub >> ~/.ssh/authorized-keys
7. rm ~/.ssh/id_rsa_temp.pub
8. chmod 600 ~/.ssh/authorized_keys (not strictly necessary)
9. log out of your shell
10. log back in
11. ssh user@remotehost.com (should now be prompted for key passphrase)
To set it up so you can log in with no passphrase:
1. ssh-agent bash
2. ssh-add (then enter key passphrase)
3. ssh user@remotehost.com
1. ssh-keygen -t rsa
2. Enter a passphrase
3. scp ~/.ssh/id_rsa.pub user@remotehost.com:~/.ssh/id_rsa_temp.pub
(will need to enter your password for user@remotehost here)
Then
4. ssh user@remotehost
5. chmod ~/.ssh 700
6. cat ~/.ssh/id_rsa_temp.pub >> ~/.ssh/authorized-keys
7. rm ~/.ssh/id_rsa_temp.pub
8. chmod 600 ~/.ssh/authorized_keys (not strictly necessary)
9. log out of your shell
10. log back in
11. ssh user@remotehost.com (should now be prompted for key passphrase)
To set it up so you can log in with no passphrase:
1. ssh-agent bash
2. ssh-add (then enter key passphrase)
3. ssh user@remotehost.com
Ferret on shared hosting
I'm using ferret for a full text search on an app deployed on site5. These are the steps I took to get it set up:
1. Install the ferret gem
2. Tell the rails app where to find the gem:
It seems that it is necessary to do this in environment.rb and not in config/environments/production.rb.
3. On shared hosting you can't run daemons so the DRb server approach for updating the ferret index won't work. I followed instructions here to set up a rake tast to update the index instead. I also commented out the production part in config/ferret_server.yml.
I then call this in my code via:
as detailed in this railscast.
1. Install the ferret gem
2. Tell the rails app where to find the gem:
# config/environment.rb
# Be sure to restart your server when you modify this file
# Uncomment below to force Rails into production mode when
# you don't control web/app server and can't set it the proper way
ENV['RAILS_ENV'] ||= 'production'
if ENV['RAILS_ENV'] == 'production'
ENV['GEM_PATH'] = '/home/forfolks/gems:/usr/lib/ruby/gems/1.8'
endIt seems that it is necessary to do this in environment.rb and not in config/environments/production.rb.
3. On shared hosting you can't run daemons so the DRb server approach for updating the ferret index won't work. I followed instructions here to set up a rake tast to update the index instead. I also commented out the production part in config/ferret_server.yml.
# app/models/product.rb
def before_save
# disable automatic ferret indexing...move it to a cron job
self.disable_ferret(:always)
end# ferret_index.rake
desc "Updates the ferret index for the application."
task :ferret_index => [ :environment ] do | t |
Product.rebuild_index
# here I could add other model index rebuilds
puts "Completed Ferret Index Rebuild"
endI then call this in my code via:
system "rake ferret_index &"as detailed in this railscast.
Monday, September 29, 2008
Tuesday, September 16, 2008
Rails ActionMailer on Site5 2
So, it turned out that it wasn't as straight forward as I thought. I dumped the config stuff after the 'Rails::Initializer.run do |config| ' part in environment.rb and tried to send an email. The server timed out and gave a 'Rails Application failed to start' error, which meant that the fcgi process was being killed (I looked in the site's error log in Backstage to figure this out.)
Couldn't work out what was going on, because it had worked in the console. Eventually I went back to the console. I tried
to see what settings it was reading. It dumped a load of default-looking settings to the command line. Somewhere my configuration settings were being over-ridden.
Eventually I discovered that this was happening in config/initializers/mail.rb. It seems that the initializers are run after the main initializer stuff in environment.rb. I put my config stuff in there instead and it worked :) .
Couldn't work out what was going on, because it had worked in the console. Eventually I went back to the console. I tried
ActionMailer::Base.smtp_settingsto see what settings it was reading. It dumped a load of default-looking settings to the command line. Somewhere my configuration settings were being over-ridden.
Eventually I discovered that this was happening in config/initializers/mail.rb. It seems that the initializers are run after the main initializer stuff in environment.rb. I put my config stuff in there instead and it worked :) .
Wednesday, September 10, 2008
Rails ActionMailer on Site5
ActionMailer is the rails class that allows you to send emails from within a rails app. To get it working I did the following:
1. Visit the 'Backstage' admin area and create an email account for 'email_user' with password 'email_password'. At this point it should tell you the SMTP server is 'mail.mydomain.com'.
At this stage I decided that I would try to get it working in the console first. So I went to my application root and typed 'script/console production' and then
2. Set the configuration
3. Created a mailer
This relied on the (blank) template 'App/Views/Page/about.html.erb' existing in my application folder.
4. Sent the message
This then sent me the message. Which I thought was pretty cool.
1. Visit the 'Backstage' admin area and create an email account for 'email_user' with password 'email_password'. At this point it should tell you the SMTP server is 'mail.mydomain.com'.
At this stage I decided that I would try to get it working in the console first. So I went to my application root and typed 'script/console production' and then
2. Set the configuration
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => "localhost",
:port => 25,
:authentication => :login,
:user_name => 'email_user+mydomain.com',
:password => 'email_password'
}3. Created a mailer
class Page < ActionMailer::Base
def about
recipients 'tom.closeman@gmail.com'
subject "Wey hey - it works - again"
from "email_user@forfolkssake.com"
end
end
This relied on the (blank) template 'App/Views/Page/about.html.erb' existing in my application folder.
4. Sent the message
Page.deliver_about
This then sent me the message. Which I thought was pretty cool.
Copying production data to development environment
I wanted to copy all the data from the production environment on the server to my development environment on my laptop. The following worked:
1. In the Backstage area of site5 choose SiteAdmin > Web Site Tools > Download an SQL database backup and then choose the development database.
This produces an SQL dump of the database and all the data therein.
2. Download and save this file (say we save it as 'production_dump.sql' in 'some_path')
3. Run the following
(Syntax is "mysql -hHOSTNAME -uUSER -pPASSWORD DATABASE < DUMPED_TEXTFILE")
4. Download any files that may have been uploaded to the server using facilities such as attachment_fu.
1. In the Backstage area of site5 choose SiteAdmin > Web Site Tools > Download an SQL database backup and then choose the development database.
This produces an SQL dump of the database and all the data therein.
2. Download and save this file (say we save it as 'production_dump.sql' in 'some_path')
3. Run the following
mysql -h localhost -u root -p password myapp_development < some_path/production_dump.sql
(Syntax is "mysql -hHOSTNAME -uUSER -pPASSWORD DATABASE < DUMPED_TEXTFILE")
4. Download any files that may have been uploaded to the server using facilities such as attachment_fu.
Subscribe to:
Comments (Atom)