Customizable parameter name in routing.

Hi Nickolas,

Le 06.10.12 13:19, Nickolas a �crit :

There is a function "resources" in the class "SingletonResource" that provides 7 routes for an indicated resource, like this: GET /photos GET /photos/:id etc.

Also, there are some gems(as "friendly_id") that give a possibility to store an arbitrary string in :id parameter, what helps to have frendlier links like /photos/big-ben.

But for several reasons this approach makes me feel odd. The fact that in the :id is stored, for example, a name of a model is not quite elegant. And also it leads to such code in controller:

@photo = Photo.find_by_name(params[:id])

Well, you as a developer may choose what the :id placeholder will contain. It's not always the 'name' of the model but any _identificator_ (a string one also) that will tie with your record.

When using friendly_id, your controller code will be exactly the same as without the gem (it is its purpose)

@photo = Photo.find(params[:id])

Now in the params hash the user may have put either a numeric id OR a friendly id (generally the user don't write that, the route generation will do). In the context of friendly_id both are correct.

Which can be hardy called beautiful. "params[:name]" should fit much better. To avoid this, the gem mentioned above redefines the "find" method in choosen model, but I do not like it too. It can easily provoke gem conflicts, because there is a lot of gems that do it too. E.g., commonly a gem which adds "soft delete" also redefines this method that makes impossible to use them together or can break functionality somehow later.

There's nothing wrong with params[:id] containing "rails-tutorial", this is a controller concern, the semantic is: "We have a request to find a resource identified with params[:id]". Nowhere in Rails we say that this id IS an ActiveRecord record's id attribute. Of course for convenience and when using the whole stack, this last statement is what we want, but it's our controller code that controls this semantic.

For the issues of having multiple gems patching rails, this is another issue (or non issue when these gems are well written) (BTW, for soft deletes, use scopes instead)

So, my suggestion is to add a :param_name option to "resources" method so we can have the behavior like this:

resources :photos, :param_name => 'name'

GET /photos/:name

Could it be useful if I add such feature? In addition, there is a whole bunch of questions on stackoveflow with the same desire.

I'm -1 on this.

Technically it’s not wrong, but when it comes to readability, it’s much better to say params[:slug] or params[:name] if that’s what it is.

I would like to have the ability to set the name of that param. Anyone from core team cares enough to accept/reject this idea?

Isn't this what to_param is for?

He is talking about the other side when the URL parameters get deserialized into the params hash.

You can alias the param name in a before_filter in your controller (or application controller if you need this everywhere):

before_filter :alias_id

private

def alias_id

params[:slug] = parmas.delete(:id)

end

I think the generalized version of this problem/pain point is that there doesn’t seem to be a good way to deserialize data coming into a rails app. For example, you might want to run certain parameters in your models through Base64.encode64 before you send them out as JSON, and would like to run them through Base64.decode64 when then come in as a parameter. Or perhaps you have a Money object that get serialized into a currency field and an amount field, and you’d like to convert back to a Money object for your controller code to work with.

Seeing how active model serialize provides a neat way to do the serialization step, it only seems natural that we have an equally elegant way for the other direction as well. before filter works okay, but could be quite difficult to read/maintain/manage when you have a lot of them.

Hi.

I think that using resources:photos,:param_name=>‘name’ has some sense.

First, it allows me to put all this logic in config/routes.rb where it belongs.

Second, it allows me to get beautiful route map: GET /photos/:name instead of GET /photos/:id.

Third, it seems to me that Rails is all about aliasing and this feature would be pretty nice alias.

it seems to me that Rails is all about aliasing

LOL... this made my day :smiley:

It does only half of the job. It changes the content of the parameter passed, but not it’s name.

The idea is to be able to change the name.

-1 on this also for reasons Piotr explained.

But reasons indicated by Piotr are favourable. Why?

Pretty sure he meant Pascal