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
How to Add Migration with Multiple References to the Same Model in One Table? Ruby/Rails
String#Encode Not Fixing "Invalid Byte Sequence in Utf-8" Error
Google Maps, Ruby on Rails, Zoom Level with One Marker
Equivalent of "Continue" in Ruby
Rails - the System Cannot Find the Path Specified
Error Installing Nokogiri on Bundle Install But Already Installed
Rails 4 Unpermitted Parameters for Array
Sorting a Ruby Array of Objects by an Attribute That Could Be Nil
Error: Failed to Build Gem Native Extension When Installing Rails on MAC Mountian Lion Os
Using Custom To_JSON Method in Nested Objects
Add "# Coding: Utf-8" to All Files
Node.Js Not Found by Rails/Execjs
Tell Ruby Program to Wait Some Amount of Time
How to Have Multiple Versions of Ruby and Rails, and Their Combinations on Windows