1

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)
Community
  • 1
  • 1
mix
  • 13
  • 2
  • 1
    [solved], changed route: get '/d/:id(/:slug)', to: 'discussions#show', as: :discussion – mix Dec 15 '13 at 23:56
  • If you have / had the answer, then please provide it as an answer to your question, and then accept the answer. It may seem self-serving, but it is the correct answer that can help others that find this Q&A – New Alexandria Nov 17 '15 at 15:34

1 Answers1

3

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

Nikolay
  • 1,392
  • 1
  • 9
  • 15
  • thanks for the suggestion. Have played with this already. the prblems with this are that we don't want the id in the param, and we only want the to_param modification on the show path. – mix Dec 12 '13 at 21:43
  • sure, but it doesn't really matter, you can use an url slug in there instead of an ID, and search by the slug in your controller. the point is that you should override the `to_param` method to get this kind of behavior in rails instead of writing a bunch of custom path helpers – Nikolay Dec 13 '13 at 03:33