Forum: Ruby on Rails How to use custom url formats?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Mike Schinkel (Guest)
on 2006-01-11 06:27
I'm new to Rails and am trying to use a field called "code" instead of
"id" in my URLs.  For example, assuming I've got a database of
motorcycles makes where the codes are "Honda", "Yamaha", "Suzuki", and
"Kawasaki", etc.  To show the info about Honda I want to use this url:

   http://www.mysite.com/makes/honda/

instead of:

   http://www.mysite.com/makes/show/1/

I have a controller called makes_controller.rb, a model called make.rb,
and a layout called makes.rhtml.  What would I need to modify?  And if
you don't mind, could you be specific about where the changes go since
I'm new to rails.

Mucho thanks in advance.
Kevin O. (Guest)
on 2006-01-11 06:36
Mike Schinkel wrote:
> I'm new to Rails and am trying to use a field called "code" instead of
> "id" in my URLs.  For example, assuming I've got a database of
> motorcycles makes where the codes are "Honda", "Yamaha", "Suzuki", and
> "Kawasaki", etc.  To show the info about Honda I want to use this url:
>
>    http://www.mysite.com/makes/honda/
>
> instead of:
>
>    http://www.mysite.com/makes/show/1/
>
> I have a controller called makes_controller.rb, a model called make.rb,
> and a layout called makes.rhtml.  What would I need to modify?  And if
> you don't mind, could you be specific about where the changes go since
> I'm new to rails.
>
> Mucho thanks in advance.

try 'routes.rb'

and read this...

http://manuals.rubyonrails.com/read/chapter/65
Duane J. (Guest)
on 2006-01-11 06:49
(Received via mailing list)
On Jan 10, 2006, at 9:27 PM, Mike Schinkel wrote:

>
> I have a controller called makes_controller.rb, a model called
> make.rb,
> and a layout called makes.rhtml.  What would I need to modify?  And if
> you don't mind, could you be specific about where the changes go since
> I'm new to rails.
>
> Mucho thanks in advance.
>

When you create a new rails project, there is a directory structure
that gets built.  Something like this:

(your app's root)
|- app
|- db
|- config
|- public
|- test
|- log
|- vendor

etc.

In the config directory is routes.rb where you can edit the "pattern"
for your urls.

You'll want to add this one *above* the default route (the default
looks like "connect ':controller/:action/:id'"):

connect 'makes/:code', :controller => 'makes', :action => 'show'

The reason we hard-code 'makes' in to the pattern and then go ahead
and tell it that the controller is 'makes' too is because we want to
be sure that the routing system knows this route is specifically for
anything in the url that begins with 'makes/'.

One other note:  You would normally use this instead:

connect 'makes/:id', :controller => 'makes', :action => 'show'

but I used 'code' because it seemed like you wanted that in
particular.  Not sure if it's important or not :)

Take care,
Duane J.
(canadaduane)
http://blog.inquirylabs.com/
Mike Schinkel (Guest)
on 2006-01-11 07:06
Wow, that was quick!  Thanks.

Routes solved 1/2 of the problem.  For good measure, here is what I have
in routes.rb:

	# i.e. http://www.imcdb.com/makes/
  	map.connect ':controller', :action => 'list'

  	# i.e. http://www.imcdb.com/makes/list/
  	map.connect ':controller/list', :action => 'list'

  	# i.e. http://www.imcdb.com/makes/new/
  	map.connect ':controller/new', :action => 'new'

  	# i.e. http://www.imcdb.com/makes/honda/
  	map.connect ':controller/:code', :action => 'show'

  	# i.e. http://www.imcdb.com/makes/honda/edit/
  	map.connect ':controller/:code/:action'

One of the remaining problems is that I can "Show" links in the List
action look like this (and the edit and destroy links are similar):

	http://localhost:3000/makes/1
	http://localhost:3000/makes/2
	http://localhost:3000/makes/3
	http://localhost:3000/makes/4

Further, when I type http://localhost:3000/makes/honda/ I get:

	ActiveRecord::RecordNotFound in Makes#show
	Couldn't find Make without an ID

I've programmed in ASP and SQL Server before so am very familar with the
concept of database driven websites, but I can't figure out exactly what
syntax to use.  For example, I tried adding the following to the 'Make'
class:

	def to_param
		code
	end

but it tells me:

	NameError in Makes#list
	Showing app/views/makes/list.rhtml where line #15 raised:

	undefined local variable or method `code' for #<Make:0x3986410>

I'm so confused!  Your help is definitely appreciated in advance.
Mike Schinkel (Guest)
on 2006-01-11 07:34
Further, when I try to add ".code" to "make" in list.rhtml list so:

	<% for make in @makes %>
	  <tr>
	  <% for column in Make.content_columns %>
	    <td><%=h make.send(column.name) %></td>
	  <% end %>
	    <td><%= link_to 'Show', :action => 'show', :code => make.code
%></td>
	    <td><%= link_to 'Edit', :action => 'edit', :code => make.code
%></td>
	    <td><%= link_to 'Destroy', { :action => 'destroy', :code =>
make.code }, :confirm => 'Are you sure?' %></td>
	  </tr>
	<% end %>

I get the following error:

	NoMethodError in Makes#list
	Showing app/views/makes/list.rhtml where line #15 raised:

	undefined method `code' for #<Make:0x3a7c080>

VERY confused!

(BTW, I've been reading 'Agile Web D. with Rails' and it
implies that the above should work, or at least I think it does.)
Sebastian Grä�l (Guest)
on 2006-01-11 07:40
(Received via mailing list)
Rails searches for an Record in the db with ID = "honda"... got it?


Am 11.01.2006 um 05:27 schrieb Mike Schinkel:
Mike Schinkel (Guest)
on 2006-01-11 07:42
Sebastian Grä�l wrote:
> Rails searches for an Record in the db with ID = "honda"... got it?
>
> Am 11.01.2006 um 05:27 schrieb Mike Schinkel:

That part is obvious; it's the standard behavior. I'm trying to get
something other than standard behaviour.  What I'm asking is how do I
get it to search for a Record in the db with code = "honda"?
Kevin O. (Guest)
on 2006-01-11 20:00
Mike Schinkel wrote:
> Sebastian Grä�l wrote:
>> Rails searches for an Record in the db with ID = "honda"... got it?
>>
>> Am 11.01.2006 um 05:27 schrieb Mike Schinkel:
>
> That part is obvious; it's the standard behavior. I'm trying to get
> something other than standard behaviour.  What I'm asking is how do I
> get it to search for a Record in the db with code = "honda"?

you will need to add ':conditions => ["code = ?", params[:code] ]' to
your finds.
Particularly the paginate function in the list action.

_Kevin
Mike Schinkel (Guest)
on 2006-01-11 23:11
>> That part is obvious; it's the standard behavior. I'm trying to get
>> something other than standard behaviour.  What I'm asking is how do I
>> get it to search for a Record in the db with code = "honda"?
>
> you will need to add ':conditions => ["code = ?", params[:code] ]' to
> your finds.
> Particularly the paginate function in the list action.

Thanks.  This isn't working.

Using this URL:

  http://localhost:3000/makes/honda/

And this "show" in "makes_controller.rb":

  def show
    @make = Make.find(params[:id], :conditions => ["code = ?",
params[:code] ])
  end

I get this error:

  ActiveRecord::RecordNotFound in Makes#show
  Couldn't find Make without an ID AND (code = '1')

Changing to:

  def show
    @make = Make.find(params[:code], :conditions => ["code = ?",
params[:code] ])
  end

I get this error:

  ActiveRecord::RecordNotFound in Makes#show
  Couldn't find Make with ID=honda AND (code = 'honda')

Changing to:

  def show
    @make = Make.find(:all, :conditions => ["code = ?", params[:code] ])
  end

I get this error:

  NoMethodError in Makes#show
  Showing app/views/makes/show.rhtml where line #3 raised:

  undefined method `Name' for []:Array

  Extracted source (around line #3):

  1: <% for column in Make.content_columns %>
  2: <p>
  3:   <b><%= column.human_name %>:</b> <%=h @make.send(column.name) %>
  4: </p>
  5: <% end %>
  6:

There are other problems no ones answered, but I can't even get past
this. Help?

Thanks in advance.

-Mike
P.S. You can read all my questions here:
http://www.ruby-forum.com/topic/51328
joey__ (Guest)
on 2006-01-11 23:25
Mike Schinkel wrote:
> Changing to:
>
>   def show
>     @make = Make.find(:all, :conditions => ["code = ?", params[:code] ])
>   end

Change the above to
   def show
     @make = Make.find(:first, :conditions => ["code = ?", params[:code]
])
   end

or even
   def show
     @make = Make.find_by_code(params[:code])
   end

The second example makes use of RoR's dynamic finders.

Hope this works

joey__
Nick S. (Guest)
on 2006-01-11 23:31
(Received via mailing list)
You almost had it. Change the .find(:all...) to .find(:first...)

And the make.code part should work alright, ecspecially if your finds
are working as you have listed....not sure on that one. Whats your
list method look like?

-Nick
Mike Schinkel (Guest)
on 2006-01-12 09:02
joey__ wrote:
> Change the above to
>  def show
>   @make = Make.find(:first, :conditions => ["code = ?", params[:code] ])
>  end
>
> or even
>  def show
>   @make = Make.find_by_code(params[:code])
>  end
>

Thanks!  FYI, the first works but the second gives this error:

   NoMethodError in Makes#show
   undefined method `find_by_code' for Make:Class

Also, can you tell me why :first worked but :all did not? What's the
difference when my conditions limit to one record?
Mike Schinkel (Guest)
on 2006-01-12 09:25
Nick S. wrote:
> not sure on that one. Whats your list method look like?

Here's app/views/makes/list.rhtml:

	<table>
	  <tr>
	  <% for column in Make.content_columns %>
	    <th><%= column.human_name %></th>
	  <% end %>
	  </tr>

	<% for make in @makes %>
	  <tr>
	  <% for column in Make.content_columns %>
	    <td><%=h make.send(column.name) %></td>
	  <% end %>
	    <td><%= link_to 'Show', :action => 'show', :code => make %></td>
	    <td><%= link_to 'Edit', :action => 'edit', :code => make %></td>
	    <td><%= link_to 'Destroy',
	    	    	    { :action => 'destroy', :code => make },
	    	    	    :confirm => 'Are you sure?' %>
	    </td>
	  </tr>
	<% end %>
	</table>

Here is the list method in app\controllers\makes_controller.rb:

	def list
	   @make_pages, @makes = paginate :makes, :per_page => 10
	end

These result in URLs to Show that look like this:

	http://localhost:3000/makes/1

Instead of the desired:

	http://localhost:3000/makes/honda

I tried adding ".code" to "make" in list.rhtml above, but get this
error:

	NoMethodError in Makes#list
	Showing app/views/makes/list.rhtml where line #15 raised:

	undefined method `code' for #<Make:0x36f2fe0>

Again, thanks in advance for helping me understand what I'm doing wrong
here.

-Mike
Eden B. (Guest)
on 2006-01-12 09:30
(Received via mailing list)
I just want to chime in that I am also having problems with dynamic
finders.  I thought it might be related to the complexity of my
configuration (legacy schema MSSQL DB from linux rails app server using
freeTDS and ODBC), but if others are having problems with dynamic
finders,
then maybe it is more general.  The thread I started in this mailing
list is
called "Repost - Do dynamic finders work with legacy schemas?"**.  I
also
opened a ticket against ActiveRecord in Trac (Ticket #3452).  Can anyone
else confirm a problem like this (find(with conditions) works, but
find_by_condition doesnt)?

Eden
Mike Schinkel (Guest)
on 2006-01-12 09:39
I think I figured it out.  I was trying:

   make.code

But instead I needed to do:

   make.attributes['Code']

BTW, is there any other way that isn't as verbose?
Mike Schinkel (Guest)
on 2006-01-12 10:20
Mike Schinkel wrote:
> I think I figured it out.  I was trying:
>
>    make.code
>
> But instead I needed to do:
>
>    make.attributes['Code']
>
> BTW, is there any other way that isn't as verbose?

Duh... make.Code works (I'm not used to case-sensitivity, yet ironically
I'm usually anal about consistent casing!)
This topic is locked and can not be replied to.