ruby-on-railsrubyroutesruby-on-rails-5ancestry

Rails - to_param changes slash to "%2F", possible to override this?


I'm using the gem Ancestry, and trying to build my routes to show the hierarchy between parents and children.

Location.rb

def to_param
  if self.ancestors?
    get_location_slug(parent_id) + "/" + "#{slug}"
  else
    "#{slug}"
  end
end

def get_location_slug(location_id)
  location = Location.find(location_id)
  "#{location.slug}"
end

This works 99% perfectly, and is showing my routes cleanly - but it is showing "%2F" instead of a "/" in my route with a parent:

localhost:3000/locations/location-1 (perfect)
localhost:3000/locations/location-1%2Flocation-2 (not quite perfect)

Routes.rb (sharing just in case)

match 'locations/:id' => 'locations#show', :as => :location, :via => :get
match 'locations/:parent_id/:id' => 'locations#show', as: :location_child, via: :get

Bonus question: This currently covers root Locations and child Locations. How could I extend this to cover grandchild Locations and great grandchild Locations? Thanks in advance!


Solution

  • Just wanted to share my solution, hopefully helps someone.

    Firstly, I cleaned up the method in my model:

    def to_param
      slug
    end
    

    Then, tweaked my routes:

    get 'locations/:id', to: 'locations#show', as: :location
    get 'locations/:parent_id/:id', to: 'locations#show_child', as: :location_child
    

    Then, I created a new method in my Application helper to generate these URLs for locations with/without a parent:

    def get_full_location_path(location)
      if location.ancestors?
        location_child_path(location.root, location)
      else
        location_path(location)
      end
    end
    

    And lastly, in my views I simply call my helper method to generate the correct URL:

    <%= link_to location.name, get_full_location_path(location) %>
    

    This seems to be working nicely, but my next task is to extend this to cover grandparents and great-grandparents. Any advice is appreciated!