My app has a model msa with a :name
and :short_name
.
On the msa index page, there is a drop-down menu of all msa.names so the user can route to the show page of the selected msa.
This functionality is coded with a collection_select that routes to a custom method in the msa controller.
msa index view:
<%= form_with url: 'msas/redirect', method: :post, local: true do |f| %>
<%= f.collection_select(:id, Msa.all, :id, :name)%>
<%= f.submit "Search" %>
<% end %>
msa controller redirect method:
def redirect
@msa=Msa.find(params[:id])
redirect_to msa_path(@msa, short_name: @msa.short_name, id: @msa.id)
end
Rather than have routes that read localhost:3000/msa/1, I want them to read localhost:3000/search/:short_name.
My routes.rb:
scope format: false do
resources :msas, :only => [:show], path: '/search', param: :short_name
end
resources :msas, :except => [:show]
Everything seems to work ok, except the route appears like this in the browser:
localhost:3000/search/Chicago?id=1
I tried remove the id: @msa.id from the redirect method, but ended up with this error:
Couldn't find Msa without an ID
which was keyed off the set_msa
method in the msa controller.
I'm wondering two things: a) have I strayed too far from typical rails convention, and b) if there is a way to do this and not reveal the id# of my msa models to the world?
If there is a way to do this and not reveal the id# of my msa models to the world?
Just remove the id
from the path helper
redirect_to msa_path(@msa, short_name: @msa.short_name)
and counter the error by defining a new method and removing the entry for show
method in the set_msa
like so
before_action :set_custom_msa, only: [:show]
before_action :set_msa, only: [:edit, :update,..] #remove the entry for show
private
def set_custom_msa
@msa = Msa.find_by(short_name: params[:short_name])
end
Have I strayed too far from typical rails convention
No! but if your final goal is to hide :id
from the URL and to make user-friendly URLs, then I would suggest you to look at friendly_id