Dynamic Routes with Rails 3

Dynamic routes with Rails 3

You'll have to write a "catch-all" rule:

On routes.rb:

get '*my_precioussss' => 'sauron#one_action_to_rule_them_all'

Your precious controller:

class SauronController < ApplicationController
def one_action_to_rule_them_all
@element = find_by_slug(params[:my_precioussss])
render @element.kind # product, category, etc
end
end

Then you write one view for each "kind" of element: product.html.erb, category.html.erb, etc.

Make sure you write your find_by_slug implementation.

You can change one_action_to_rule_them_all to pikachu_i_choose_you and SauronController to PokemonController, will work too.

How to Use Rails 3 Routes with Dynamic Segments

The route declaration I was using was almost functional. For some reason there is an issue with using a hyphen and not having grade_level as its own /-separated substring. When I switched to using the route declaration:

match "/:muscle_group/grade/:grade_level/:id" => "exercises#show"

Instead of the original:

match "/:muscle_group/grade-:grade_level/:id" => "exercises#show"

http://localhost:3000/abdominal/grade/1/5 is then a valid route.

I would prefer to have this route with the hyphen and wish I knew how to make that work, but it is not a top priority. If anyone knows how to make it work with the hyphen, please let me know.

Dynamically Create Route aliases in Rails 3

With the help of my dear Friend sevenseacat everything worked out great:

What did I do:

1)Added the needed Alias fields/columns to table

2)Created the Alias model / controller
This code is pseudo code but you will get the picture

  def show
object = Model.where("lower(alias) =?", params[:alias].downcase).first || OtherModel.where("lower(alias) =?", params[:alias].downcase).first
if object.class.name == "Model"
@model = Model.find_by_id!(object.model_id)
render "model/show"
elsif object.class.name == "OtherModel"
@othermodel = OtherModel.find_by_id!(object.othermodel_id)

I18n.locale = object.locale
render "othermodel/show"
else
not_found
end
end

3)Created the route

get '*alias', to: 'alias#show', as: 'alias'

Just for information not_found:

  def not_found
raise ActionController::RoutingError.new(t("activemodel.errors.messages.not_found"))
end

Note 1

This is without the cross table validation

Thank you all for the help :)

rails 3 dynamic routes

I personally use Friendly Id to handle pretty URLs with hooks into ActiveRecord(really nice by the way). This gem has nested resource support as well.

Dynamic routes in rails

You can use globbing in your config/routes.rb:

get "/api/*path", to: "api#index"

Which would be accessible in the controller via params[:path]

Details can be found in the rails guide.

Dynamic routes on runtime in Rails

I needed to figure out building routes off a database model myself in a Rails 4 application (which is called "ComingSoon" in the examples below. I wanted pages that could be edited on the back-end and given a user-friendly name, which is stored in the Page#name field. So "About Us" titled page typically becomes "about_us" name, which leads to "http://localhost:3000/about_us" The following is the technique I came up with:

Create a new model in app/models/dynamic_router.rb

class DynamicRouter
def self.load
ComingSoon::Application.routes.draw do
Page.all.each do |pg|
get "/#{pg.name}", :to => "pages#show", defaults: { id: pg.id }, as: "pages_#{pg.name}"
end
end
end

def self.reload
ComingSoon::Application.routes_reloader.reload!
end
end

The key above is that I pass the page's id as one of the parameters, so look up is still on the Page#id field, which is, IMHO, a lot better than using the friendly plugin or lookups on slugerized values.

Add the following line to your config/routes.rb

ComingSoon::Application.routes.draw do

# ...

DynamicRouter.load
end

Finally, when the Page is updated, we need to reload the routes, so add an after_safe callback on the Page model:

class Page < ActiveRecord::Base
after_save :reload_routes

def reload_routes
DynamicRouter.reload
end
end

I plan to refine this further to only reload routes if the name attribute is changed and perhaps simply edit the existing route rather than reloading everything if performance proves to be an issue (which at the moment, its not).



Related Topics



Leave a reply



Submit