# Find() performance

**URL:** <https://www.ruby-forum.com/t/find-performance/79674>\
**Category:** Rails\
**Created:** [December 18, 2006, 12:19am UTC](https://www.ruby-forum.com/t/find-performance/79674 "2006-12-18T00:19:33Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![chadster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/46a35a/32.png) [@chadster](https://www.ruby-forum.com/u/chadster)\
**Post date:** [December 18, 2006, 12:19am UTC](https://www.ruby-forum.com/t/find-performance/79674/1 "2006-12-18T00:19:33Z")

</div>

I want my application URL’s to have the name of products in the URL as  
opposed to the id, like so:

/product/windows+xp instead of /product/view/1  
/product/windows+xp/edit instead of /product/edit/1

I assume the best way then would be in the controller to use:

def view  
@product = Product.find\_by\_name(params[:name])  
end

instead of

def view  
@product = Product.find(params[:id])  
end

So my question is:

1. Would find\_by\_name degrade performance significantly because I’m  
searching by name now and not by row?

If so, 2) is there a better way to handle the find in a more efficient  
way  
and still use the string name in the URL’s?

Happy holidays,  
Chad

---

<div class="post-metadata">

**Author:** ![chadster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/46a35a/32.png) [@chadster](https://www.ruby-forum.com/u/chadster)\
**Post date:** [December 18, 2006, 12:23am UTC](https://www.ruby-forum.com/t/find-performance/79674/2 "2006-12-18T00:23:34Z")

</div>

That seems like a reasonable approach to me, assuming you configure the  
routes accordingly.  
Performance will be slower due to the nature of the search, but not by  
much. I would suggest dropping an index onto the name field.

---

<div class="post-metadata">

**Author:** ![chadster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/46a35a/32.png) [@chadster](https://www.ruby-forum.com/u/chadster)\
**Post date:** [December 18, 2006, 6:15am UTC](https://www.ruby-forum.com/t/find-performance/79674/3 "2006-12-18T06:15:33Z")

</div>

askegg wrote:

> That seems like a reasonable approach to me, assuming you configure the  
> routes accordingly.  
> Performance will be slower due to the nature of the search, but not by  
> much. I would suggest dropping an index onto the name field.

I’ve forgotten where I saw the post, but it recommended taking the  
approach of including the id and the name (which can change). In fact  
the name can be arbitrary and can be ignored. ie, allow

/product/1-windows+xp/edit  
/product/2-windows+98

etc.

Then you just ignore the non-id part, and have no performance problems,  
and the urls will still work if you rename the product.

---

<div class="post-metadata">

**Author:** ![chadster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/46a35a/32.png) [@chadster](https://www.ruby-forum.com/u/chadster)\
**Post date:** [December 18, 2006, 6:46am UTC](https://www.ruby-forum.com/t/find-performance/79674/4 "2006-12-18T06:46:17Z")

</div>

A nice way to do this is to use the acts\_as\_sluggable plugin:

[http://www.agilewebdevelopment.com/plugins/acts\_as\_sluggable](http://www.agilewebdevelopment.com/plugins/acts_as_sluggable)  
[http://dev.2750flesk.com/acts\_as\_sluggable/](http://dev.2750flesk.com/acts_as_sluggable/)

You can then use it in your model like this:

class Article \< ActiveRecord::Base

```
acts_as_sluggable :with => 'title'

```

end

A link in your view would be:

link\_to ‘Read article’, :action =\> ‘show’, :id =\> @article

And the URL it generates would look like:

/articles/show/76-omg-my-cat-is-so-cute-lol

I’m using acts\_as\_sluggable in a couple different Rails applications  
and it’s working very nicely for me, a live example is:

[http://www.lovemygarden.net/resources/article/1-testing-and-amending-garden-soil](http://www.lovemygarden.net/resources/article/1-testing-and-amending-garden-soil)

yours,  
sness.  
[http://www.sness.net](http://www.sness.net)

---

<div class="post-metadata">

**Author:** ![chadster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/46a35a/32.png) [@chadster](https://www.ruby-forum.com/u/chadster)\
**Post date:** [February 5, 2007, 9:40pm UTC](https://www.ruby-forum.com/t/find-performance/79674/5 "2007-02-05T21:40:05Z")

</div>

sness wrote:

> And the URL it generates would look like:
> 
> /articles/show/76-omg-my-cat-is-so-cute-lol

Is there a way to add a route that drops the “show” from the URL? I’m  
using this route to drop “show” from the URL, but it only works if the  
:id part of the URL is an integer:

map.connect ‘:controller/:id’, :action =\> ‘show’, :requirements =\> { :id  
=\> /\d+/ }

Any help is appreciated.

---

<div class="post-metadata">

**Author:** ![chadster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/46a35a/32.png) [@chadster](https://www.ruby-forum.com/u/chadster)\
**Post date:** [February 5, 2007, 10:07pm UTC](https://www.ruby-forum.com/t/find-performance/79674/6 "2007-02-05T22:07:16Z")

</div>

On 12/17/06, Chad A. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> def view  
> @product = Product.find\_by\_name(params[:name])  
> end
> 
> instead of
> 
> def view  
> @product = Product.find(params[:id])  
> end

This link does a good job of explaining, and linking to other resources  
on  
the subject.  
[http://www.tonyspencer.com/2007/02/04/better-search-engine-friendly-urls-with-ruby-on-rails/](http://www.tonyspencer.com/2007/02/04/better-search-engine-friendly-urls-with-ruby-on-rails/)

So my question is:

---

<div class="post-metadata">

**Author:** ![chadster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/46a35a/32.png) [@chadster](https://www.ruby-forum.com/u/chadster)\
**Post date:** [February 5, 2007, 10:28pm UTC](https://www.ruby-forum.com/t/find-performance/79674/7 "2007-02-05T22:28:19Z")

</div>

On 12/17/06, _Chad A._ \<removed\_email\_address@domain.invalid

> ```
> If so, 2) is there a better way to handle the find in a more
> efficient way
> and still use the string name in the URL's?
> 
> ```

Take a look at Tressle  
[http://trestle.rubyforge.org/](http://trestle.rubyforge.org/)  
and  
[http://www.rubyinside.com/trestles-replacing-rails-scaffolding-with-something-better-138.html](http://www.rubyinside.com/trestles-replacing-rails-scaffolding-with-something-better-138.html)

/people Lists existing person records  
/people/new GET Shows an empty person form  
POST Creates a new person record from request  
parameters  
/people/99 Shows the person record having ID 99  
/people/99/edit GET Shows a person form for the record having ID 99  
POST Updates the person record having ID 99 using request  
parameters  
/people/99/destroy GET Redirects to /people/99/edit with a notice  
that the user must click the form’s  
Destroy

```
                            button in order to destroy a record
  POST Deletes the person record having ID 99 after
                            prompting the user for confirmation

```

Personally I hate the verb-object form and I hate the :id as an  
absolute.  
We see in wikis and blogs the use of a name parameter

/people/jack

There are many settings where you don’t want the user/hacker to step  
through  
the numbers.

I’m a user of TWiki as a wiki and I find the  
“[http://twiki.org/cgi-bin/view/web/topic](http://twiki.org/cgi-bin/view/web/topic)”  
annoying. The “cgi-bin/view” is not needed, and as Nils Jonsson’s  
article  
points out, the move from view to edit is easier if the verb is a  
suffix.

One day I’ll figure out the mapping for

```
  /web/topic /web/topic/edit
  /web.topic /web.topic/edit
  /web.topic?edit
  /web.topic?edit&skin=cosmos
  /web/topic?raw=on

```

and so forth

–  
We know nothing about motivation. All we can do is write books about it.  
–Peter F. Drucker
