Reputation: 13
we're trying to get our site to have less scrapeable AND more readable urls so e.g. www.loomio.org/discussions/3122 becomes www.loomio.org/d/3saA4ds9/lets-go-to-the-moon we only really want the human-readable slug on show-links, so www.loomio.org/d/3saA4ds9/edit should be the url for editing that discussion
the solution so far follows the top answer here: Ruby on Rails: How to override the 'show' route of a resource?
modify routes.rb
:
get '/d/:id/:slug', to: 'discussions#show', as: :discussion
resources :discussions, path: 'd', except: [:edit, :show] do
get :activity_counts, on: :collection
member do
post :update_description
post :add_comment
post :show_description_history
get :new_proposal
post :edit_title
put :move
end
end
install gem FriendlyID; make and populated a :key
column on Discussion table; add the following to discussion.rb
(model):
KEY_LENGTH = 10
extend FriendlyId
friendly_id :key
write a custom path helper for group_path. in groups_helper.rb
:
def group_url(group, options={})
url_for(options.merge(:controller => 'groups', :action => 'show',
:id => group.key, :slug => group.full_name.parameterize))
end
def group_path(group, options={})
group_url(group, options.merge(:only_path => true))
end
rake routes produces: group GET /g/:id/:slug(.:format) groups#show
and while calling group_path(group)
seems to work in some cases, I'm also seeing strange unrelated urls get generated, like :
http://loomio.org/group_requests/TegFOIx4DB/start_new_group?action=show&controller=groups%2Fgroups&slug=19-tory
in console, I'm also getting errors such as:
[5] pry(main)> g = Group.last
[6] pry(main)> app.group_path(g)
ActionController::RoutingError: No route matches {:controller=>"groups", :action=>"show", :id=>#<Group id: 2811, name: "Sylvester Buckridge", created_at: "2013-12-10 06:25:42", updated_at: "2013-12-10 06:25:42", privacy: "public", members_invitable_by: "members", parent_id: nil, email_new_motion: true, hide_members: false, beta_features: false, description: "A description for this group", memberships_count: 1, archived_at: nil, max_size: 300, cannot_contribute: false, distribution_metric: nil, sectors: nil, other_sector: nil, discussions_count: 0, motions_count: 0, country_name: nil, setup_completed_at: "2013-12-10 05:25:01", next_steps_completed: false, full_name: "Sylvester Buckridge", payment_plan: "undetermined", viewable_by_parent_members: false, key: "rkdlTytOin">}
from /home/s01us/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.16/lib/action_dispatch/routing/route_set.rb:540:in `raise_routing_error'
I've tried putting the group_path and grop_url methods in ApplicationController
and ApplicationHelper
to no avail.
calling
group_path( group.key, group.fullname.parameterize )
works, but would ideally like to be able to only have to call e.g.
group_path(@group)
Upvotes: 1
Views: 344
Reputation: 1392
as far as i understand the problem, you could use the good old hack with defining the to_param
method on your model
class Group < ActiveRecord::Base
def to_param
"#{id}-#{slug}"
end
end
The beauty of this solution is that you won't need to do anything else. Rails will automatically use the to_param
method as your record ID when it generates an URL from a record. You can do anything
redirect_to group_path(@group)
redirect_to @grup
# etc
and your Group.find
should eat it as it is 123-smth-smth
, usually it is smart enough to extract the integer part of the id
Upvotes: 3