# Does Rails need more useful URL helpers?

**URL:** <https://www.ruby-forum.com/t/does-rails-need-more-useful-url-helpers/58761>\
**Category:** Rails\
**Created:** [April 25, 2006, 6:38pm UTC](https://www.ruby-forum.com/t/does-rails-need-more-useful-url-helpers/58761 "2006-04-25T18:38:41Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![furrot](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/3da27b/32.png) [@furrot](https://www.ruby-forum.com/u/furrot)\
**Post date:** [April 25, 2006, 6:38pm UTC](https://www.ruby-forum.com/t/does-rails-need-more-useful-url-helpers/58761/1 "2006-04-25T18:38:41Z")

</div>

Similar topic to my last post, but a different brand of methods. In  
particular, the url\_for and link\_to methods have come to bother me at  
times. I will mention one instance in particular:

I am designing a high-end administrative interface. This interface  
supports paging, sorting and limiting to specific field values. Thus I  
have params named page, sort and limit.

The lack of elegance I see comes when I make new links or add new  
parameters. To keep the administrator on the same page time and time  
again, I have to add “:page =\> params[:page]” to every link in my  
scaffold’s edit.rhtml, list.rhtml and new.rhtml as well as to my helpers  
that generate paging, sorting and limiting links. As I add more  
parameters, the link\_to commands in these files grow more and more  
unreadable and the number of places I have to explicitly specify every  
parameter in the query string increases.

I attempted to use :overwrite\_params, but then all of a sudden link\_to  
does not seem to recognize my routes. It starts dumping URL-defined  
params into the query string.

When I read about link\_to, the description said that it intuitively  
understood the hierarchy of parameters. If the :action changed, the :id  
was nulled. If the :controller changed, :action and :id were nulled. And  
so forth.

The problem is once you get into params in the query string such as  
params[:page]. It seems to me that a link\_to specifying only :sort =\>  
sort should not overwrite :page or :limit. Params in the query string  
should act as brothers. No one param should be the parent of another;  
setting one should not unset the others. They are not in a hierarchy.  
They merely exist side-by-side. Changing the way rails nulls query  
string parameters would keep those params out of my paging, sorting and  
limiting helpers, which I feel should ideally not have to know about  
each other. And if there is some reason this should not be the default,  
perhaps it should at least be an option. Or perhaps :overwrite\_params  
needs to be fixed. Or perhaps I am using it incorrectly?

This also wouldn’t address every repeated instance of “:page =\>  
params[:page]” in my views. Changing :action still needs to null query  
string parameters. Or does it? Should query string parameters be  
considered children of even :action or :controller? Is :page necessarily  
subordinate to :action =\> ‘list’? To me it seems :page should be  
subordinate to the :controller but not the action. Perhaps some method  
of explicitly specifying query string parameter hierarchies is in order.

---

<div class="post-metadata">

**Author:** ![furrot](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/3da27b/32.png) [@furrot](https://www.ruby-forum.com/u/furrot)\
**Post date:** [April 26, 2006, 4:08pm UTC](https://www.ruby-forum.com/t/does-rails-need-more-useful-url-helpers/58761/2 "2006-04-26T16:08:15Z")

</div>

That’s definitely a very nice solution! Obviously it breaks down when  
users do not have cookies enabled. In the case of an administrative  
panel, we are free to require our customer to enable cookies. For the  
similar public environment to come, this solution would become less  
desirable.

One thought, though: why use the params array at all? Why not just leave  
the variables in the session? The default paginator looks for its page  
number in the params variable, but I believe you can roll-your-own  
Paginator and tell it to use the session variable:

@element\_count = Element.count (or count\_by\_sql or parent.element.count  
as needed)  
@element\_pages = Paginator.new self, @element\_count, 20,  
@session[self.name][:page]

I haven’t actually tried this, though I assume it’d work fine. I had to  
generate my own paginators for this same administrative panel because I  
designed it to operate both with and without a limiting id at each  
descent into the hierarchy. This complicated matters and forced me to  
use my own paginator, but the benefits were definitely worth it, and  
doing so is hardly difficult.

---

<div class="post-metadata">

**Author:** ![furrot](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/3da27b/32.png) [@furrot](https://www.ruby-forum.com/u/furrot)\
**Post date:** [April 26, 2006, 5:33pm UTC](https://www.ruby-forum.com/t/does-rails-need-more-useful-url-helpers/58761/3 "2006-04-26T17:33:32Z")

</div>

Using a session for paging is usually a bad idea.

1. Multiple windows result in unexpected results.

2. Bookmarks don’t reference the right page and GETS aren’t idempotent.

If you want reliable paging that always works you need to include  
everything in the URL. If you add sorting and filtering/limiting, make  
sure to mark those links nofollow and/or use javascript, because Google  
will kill you when it indexes every possible sort and filter  
combination.

---

<div class="post-metadata">

**Author:** ![furrot](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/3da27b/32.png) [@furrot](https://www.ruby-forum.com/u/furrot)\
**Post date:** [April 25, 2006, 8:12pm UTC](https://www.ruby-forum.com/t/does-rails-need-more-useful-url-helpers/58761/4 "2006-04-25T20:12:55Z")

</div>

Hello Stephen,

2006/4/25, Stephen F. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> I am designing a high-end administrative interface. This interface  
> supports paging, sorting and limiting to specific field values. Thus I  
> have params named page, sort and limit.

I see your point. The way I coded around that is to store the page,  
sort and limit in the session. If the incoming request has those  
parameters, I overwrite the session, else I use the session’s values.  
Here’s how I do it:

class UsersController \< ApplicationController  
before\_filter :process\_filters

def index  
@users, @user\_pages = paginate(:users, :limit =\> @limit, :page =\>  
@page, :order =\> @sort)  
end

def process\_filters  
# That generates a namespace for the common parameters  
session[self.name] ||= Hash.new

```
@page = params[:page] || session[self.name][:page] || 1
session[self.name][:page] = @page

# Same kind of code for limit and order/sort

```

end  
end

Hope that helps !

---

<div class="post-metadata">

**Author:** ![furrot](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/3da27b/32.png) [@furrot](https://www.ruby-forum.com/u/furrot)\
**Post date:** [April 26, 2006, 7:00pm UTC](https://www.ruby-forum.com/t/does-rails-need-more-useful-url-helpers/58761/5 "2006-04-26T19:00:00Z")

</div>

Here’s another approach…

create a model to hold the page state.

The way I did this goes something like this…

user has\_many :page\_views  
PageView belongs\_to :user

page\_view  
id :integer  
page\_url :string  
setting :text

The ‘setting’ attribute just holds a yaml encoding of the params hash.  
the ‘page\_url’ is the uri for the request without the params  
Then in a before filter, you can load the previous params and overwrite  
the bits that changed.  
in an ‘after’ filter, you write the modified params back to the table.

The nice part here is that it remembers settings for each user, it  
doesn’t forget the settings when it logs off, and it keeps your session  
from getting cluttered.

On Wednesday, April 26, 2006, at 5:33 PM, Guest wrote:

> combination.
> 
> –  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).
> 
> * * *
> 
> Rails mailing list  
> removed\_email\_address@domain.invalid  
> [http://lists.rubyonrails.org/mailman/listinfo/rails](http://lists.rubyonrails.org/mailman/listinfo/rails)

\_Kevin

---

<div class="post-metadata">

**Author:** ![furrot](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/3da27b/32.png) [@furrot](https://www.ruby-forum.com/u/furrot)\
**Post date:** [July 18, 2006, 9:22pm UTC](https://www.ruby-forum.com/t/does-rails-need-more-useful-url-helpers/58761/6 "2006-07-18T21:22:32Z")

</div>

Kevin O. wrote:

> Here’s another approach…
> 
> create a model to hold the page state.
> 
> user has\_many :page\_views  
> PageView belongs\_to :user
> 
> page\_view  
> id :integer  
> page\_url :string  
> setting :text

The default\_url\_options method I mentioned last failed terribly.  
Clashing variable names and an inability to define where they should  
expire caused params to persist longer than they should have. My company  
has decided to lean towards params lasting too short than too long and I  
tend to agree with them.

The above version also seems quite excellent, but it won’t work when a  
view is not tied to a user object, as with the Admin panels in which I  
was trying to implement sorting.

After more months of Rails use and experience, I continue to think param  
overriding needs a review. Where :controller, :action and :id do not  
change, link\_to’s should retain the current URL’s params except where  
explicitly and individually overridden. It makes sense for :id to be  
nulled when :action is set because of the hierarchy of the route. But  
params in not specified in a route should not be overridden in the same  
manner. They should all be treated as siblings at the same hierarchical  
depth. They should only be nulled when a param from the route changes,  
not when any of their siblings changes. To do otherwise continues to  
seem unintuitive to me.

---

<div class="post-metadata">

**Author:** ![furrot](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/3da27b/32.png) [@furrot](https://www.ruby-forum.com/u/furrot)\
**Post date:** [May 1, 2006, 5:30pm UTC](https://www.ruby-forum.com/t/does-rails-need-more-useful-url-helpers/58761/7 "2006-05-01T17:30:42Z")

</div>

While searching for the solution to another problem, I came across the  
following URL: [Sessions w/o cookies still broken - Rails - Ruby-Forum](http://www.ruby-forum.com/topic/1612). Based on the  
example code given in this article, I implemented the following method  
in my ApplicationController class:

def default\_url\_options(options)  
{  
:page =\> params[:page],  
:sort =\> params[:sort],  
:limit =\> params[:limit]  
}  
end

And it works like a charm! I just didn’t know the method existed. Next  
time I will examine the base classes like ActionController::Base more  
carefully.

I wonder if a review of how parameters override other parameters is  
still in order or whether the above method solves all the needed  
problems? It effectively provides a single location for the developer to  
specify all parameters that should remain from one link to another  
regardless of any other parameter modifications. This can even be  
specified on a per-controller basis.
