Topic: Routing Problems

I have setup named routing like this:

In routes:

map.artist 'artist/:artisttitle',:controller =>'artists', :action=>'show'

in Artist Controller:
def show
@artist = Artist.find(:first, :conditions => ['title = ?',params[:artisttitle]])
end

in Index:
<%=link_to album.artist.title.downcase,artist_url(:artisttitle => album.artist.title.downcase)%>

Everything Works Beautifully with artists like these:
Pink Floyd    ->   /artist/pink+floyd
Tilly and the Wall   ->  /artist/tilly+and+the+wall
Sufjan Stevens    ->    /artist/sufjan+stevens

However, in the rare occasion of an artist like:
M.Ward    ->  Error: no route found to match "/artist/m.ward" with {:method=>:get}

It obviously has to do with the period, so what do i do to fix it?

Re: Routing Problems

In Rails 1.2 the period is considered a separator character like the forward slash, so this is probably why it isn't matching the route properly. One workaround may be to escape any period (with %2e) before giving it to the link_to method. Untested.

Railscasts - Free Ruby on Rails Screencasts

Re: Routing Problems

i'm not really sure how i would do that?

Re: Routing Problems

After a little investigation it looks like escaping the period won't work because url_for/link_to does its own escaping after that, so the percent sign is escaped. Instead what I would do is create a "permalink" column (or something similar) in the artists table. You can automatically set this column when creating the record:

class Artist < ActiveRecord::Base
  before_create :create_permalink
 
  def create_permalink
    self.permalink = title.downcase.gsub(/[\W.]+/, '-')
  end
end

Or something like that. You can then use this permalink column for creating the URL and fetching the record.

Railscasts - Free Ruby on Rails Screencasts

Re: Routing Problems

another method could be to add a sanitize_title method in your artist model.

Like so:

artist model

class Artist < ActiveRecord::Base
  #...other code
 
  def sanitized_title
    title.downcase.gsub(/[\W.]+/, '-')
  end

  #... other code
end


any view
<%=link_to album.artist.title.downcase,artist_url(:artisttitle => album.artist.sanitized_title)%>

--jake

---------------------------------------------------------------------
Rails Development - Agile rails consulting and development for startups on a budget
Flvorful Blog - Some ramblings
Flvorful's Open Source Projects - Some handy hacks for your rails projects.

Re: Routing Problems

Good suggestion. The only problem is without the data in the database it is difficult to fetch the entry in the show action.

Railscasts - Free Ruby on Rails Screencasts

Re: Routing Problems

ryanb wrote:

Good suggestion. The only problem is without the data in the database it is difficult to fetch the entry in the show action.

right, but wouldnt that be the case for any param that wasnt in the DB.  If someone did /artist/some?cool>artist+another+name

Wouldnt that screw up the action also and try to fetch the wrong (or non-existant) item from the DB


--jake

---------------------------------------------------------------------
Rails Development - Agile rails consulting and development for startups on a budget
Flvorful Blog - Some ramblings
Flvorful's Open Source Projects - Some handy hacks for your rails projects.

Re: Routing Problems

Sorry I wasn't clear, I was referring to valid artists that were in the database, but the "sanitized_title" variation of the artist isn't in the database. So, it's not easy to fetch the artist in the show action without a column containing the sanitized_title.

Or maybe I misunderstood your last post.

Railscasts - Free Ruby on Rails Screencasts

Re: Routing Problems

sanitize_title would be a "virtual column" and not actually in the database. It's just a method that takes title and alters it whenever called.

Re: Routing Problems

ryanb wrote:

Sorry I wasn't clear, I was referring to valid artists that were in the database, but the "sanitized_title" variation of the artist isn't in the database. So, it's not easy to fetch the artist in the show action without a column containing the sanitized_title.

Or maybe I misunderstood your last post.

its not fetching a column named sanitized_title, its fetching title, sanitizing and returning.  Of course, the same problem would still exist of not being able to fetch title.


From re-reading the orinigal post, i Think the problem is when someone enter a name like "M.Ward" and rails tries to create a URL for link to and its creates a link that points to: /artist/m.ward

This is what the sanitize title would be used for.  In this case, the artist title will always be in the database, otherwise the link to wouldnt work in the first place.

So when creating links for the titles, instead of linking to the artist's real title, you would link to the sanitized version that would basically clean up titles like that.

does that make sense...


--jake

(its so hard to convey programming logic without speaking it sometimes)

---------------------------------------------------------------------
Rails Development - Agile rails consulting and development for startups on a budget
Flvorful Blog - Some ramblings
Flvorful's Open Source Projects - Some handy hacks for your rails projects.

Re: Routing Problems

I believe something has gone wrong...
I tried the sanitized_title first.

The links are being changed

Sun+Kil+Moon  =>  Sun-Kil-Moon

But if I type:
 Http://webpage/artist/sun+kil+moon  -> Renders Show Page Perfectly
Http://webpage/artist/sun-kil-moon   -> Code Breaks Telling Me I Have A Nil Object

I think it could be my Routes:
map.artist 'artist/:artisttitle',:controller =>'artists', :action=>'show'

Or Maybe I have to add a "sanitized_title" Row to the database?

Re: Routing Problems

change sanitized_title to:

  def sanitized_title
    title.downcase.gsub(/[\W.]+/, '+')
  end

that should fix it


--jake


ldenman wrote:

I believe something has gone wrong...
I tried the sanitized_title first.

The links are being changed

Sun+Kil+Moon  =>  Sun-Kil-Moon

But if I type:
 Http://webpage/artist/sun+kil+moon  -> Renders Show Page Perfectly
Http://webpage/artist/sun-kil-moon   -> Code Breaks Telling Me I Have A Nil Object

I think it could be my Routes:
map.artist 'artist/:artisttitle',:controller =>'artists', :action=>'show'

Or Maybe I have to add a "sanitized_title" Row to the database?

---------------------------------------------------------------------
Rails Development - Agile rails consulting and development for startups on a budget
Flvorful Blog - Some ramblings
Flvorful's Open Source Projects - Some handy hacks for your rails projects.

Re: Routing Problems

It didn't work..Now my URL's are coming out as:

http://site/artist/sun%2Bkil%2Bmoon

Re: Routing Problems

ok

revert that back and change show to:

def show
  @artist = Artist.find(:first, :conditions => ['title = ?',params[:artisttitle].gsub(/-+/,' ')])
end

--jake

---------------------------------------------------------------------
Rails Development - Agile rails consulting and development for startups on a budget
Flvorful Blog - Some ramblings
Flvorful's Open Source Projects - Some handy hacks for your rails projects.

Re: Routing Problems

Jake, thanks for all the help!
We are almost there.
It successfully changes all "+"s to "-"s
so, sun-kil-moon works now.

However, M.Ward still does not. It changes M.War to m-ward, but the app still gives me an error.
I think i may just add a validation check for a period.

This sort of sucks though because I also have a blog. If i were to add a Period to the end of the title, it would break my app....Any other ideas?

Last edited by ldenman (2006-12-30 15:54:45)

Re: Routing Problems

can you post your model and controller for this particluar problem?

--jake

---------------------------------------------------------------------
Rails Development - Agile rails consulting and development for startups on a budget
Flvorful Blog - Some ramblings
Flvorful's Open Source Projects - Some handy hacks for your rails projects.

Re: Routing Problems

class ArtistsController < ApplicationController
before_filter :login_required, :except => [:index, :show]
def index
@artists = Artist.find(:all, :order => 'title', :include => @albums)
end
def show
@artist = Artist.find(:first, :conditions => ['title = ?',params[:artisttitle].gsub(/-+/,' ')])
end

def new_artist
@artists = Artist.new
end

def create_artist
@artist = Artist.new(params[:artist])
@artist.added_by = @session['user'].login
if @artist.save
redirect_to :controller => 'artists'
else
render :action => 'index'
end
end

def create_artist_from_album
@artist = Artist.new(params[:artist])
@artist.added_by = @session['user'].login
if @artist.save
render :partial => 'albums/artistdropdown'
else
render :action => 'index'
end
end

end


class Artist < ActiveRecord::Base
has_many :albums
validates_uniqueness_of :title

def sanitized_title
    title.downcase.gsub(/[\W.]+/, '-')
  end
end


create_table "artists", :force => true do |t|
    t.column "title",    :string,    :limit => 250
    t.column "added_by", :string,    :limit => 250
    t.column "added_at", :timestamp

Last edited by ldenman (2006-12-30 16:06:37)

Re: Routing Problems

sorry, also the schema for the models

--jake

Last edited by jake3030 (2006-12-30 16:03:46)

---------------------------------------------------------------------
Rails Development - Agile rails consulting and development for startups on a budget
Flvorful Blog - Some ramblings
Flvorful's Open Source Projects - Some handy hacks for your rails projects.

Re: Routing Problems

updated

Re: Routing Problems

ok

2 possible solutions:

1.  add a new column used for title searching that is a copy of title but has all punctuation removed.  Then you can do title searches on this column and maintain data integrity.  In the event that you get multiple results, you can just present the user with a list of possible options and they can choose.

just add a before_save method in the artists model that copies and sanitizes the real title over to the search title.  Make sure it is a before_save so that the search title is recreated any time the an artist's info is changed.

2.  remove punctuation from the title itself, im not to fond of this method.  You lose the original title.

With either method, i would probably add a check to the new_artist form that would check to see if the user was trying to add an artist already in the database.  This would help make your data more accurate.

--jake

---------------------------------------------------------------------
Rails Development - Agile rails consulting and development for startups on a budget
Flvorful Blog - Some ramblings
Flvorful's Open Source Projects - Some handy hacks for your rails projects.