Rails routes with clean urls - ruby-on-rails

My problem is i want to remove the querystring part of this URL and make it clean.
http://staging.mysite.com/mycontroller?name=/philippines/about-manila
currently i have MyController.index() and I parse the name parameter in this method.
What i would eventually want is this :
http://staging.mysite.com/mycontroller/philippines/about-manila
the parameter part 'philippines/about-manila' can have arbitrary number of parameters, like
http://staging.mysite.com/mycontroller/philippines/about-manila/people
How can i do this in routes?

It sounds like you want route globbing. If you use:
map.my_route '/mycontroller/*parts',
:controller => :mycontroller,
:action => :index
and then go to the URL http://staging.mysite.com/mycontroller/philippines/about-manila/people, then your mycontroller controller's index action will be called, and params[:parts] will contain the array ["philippines", "about-manila", "people"].

Is it really arbitrary — or just variable?
If it's just variable, you can enclose optional parameters in parentheses:
match '/:city(/:section(/:subsection))', :controller => :mycontroller,
:action => :index
For Rails 2.x:
map.connect '/:city(/:section(/:subsection))', :controller => :mycontroller,
:action => :index

For Rails 2.x you can use
map.my_route '/:my_param', :controller => :mycontroller, :action => :index
Then in your controller you can access
params[:my_param]
If you want links just go with
my_route_path(:my_param => "mytekst")

Related

How to pass a default query param with Rails 2.3.x routing

I'm trying to do something trivial. I have a bunch of URLs that I need to map like the following:
http://example.com/foo
http://example.com/foo/something
Both need to go to the same controller/action. The problem I'm having is when http://example.com/foo is invoked, I need to specify a default query parameter. I thought that's what the :defaults hash does in routes.rb, but unfortunately the following doesn't work:
map.connect 'foo', :controller => 'something', :action => 'anaction',
:defaults => { :myparam => 'foobar' }
This should route http://example.com/foo to the something controller, anaction action, and make params[:myparam] point to the string "foobar".
I'm assuming for the second example http://example.com/foo/something, I'll need an additional route.
What's the best way to tackle this?
I wouldn't complicate things by adding such logic to my routes file, I'd just do it in my action:
params[:my_param] ||= 'foobar'
Untested, but:
map.connect 'foo', :controller => 'something', :action => 'anaction', :myparam => 'foobar'
It looks like the :controller and :action arguments in there are not in any way special, but just end up feeding into params. The 2.3.8 documentation seems to confirm this.
More formally, you can include
arbitrary parameters in the route,
thus:
map.connect ':controller/:action/:id', :action => 'show', :page => 'Dashboard'
This will
pass the :page parameter to all
incoming requests that match this
route.

Get SEO friendly URLS with Rails without method_missing?

Currently we are using method_missing to catch for calls to SEO friendly actions in our controllers rather than creating actions for every conceivable value for a variable. What we want are URLS like this:
/students/BobSmith
and NOT /students/show/342
IS there a cleaner solution than method_missing?
Thank you!
You can define a route for that particular format fairly easily.
map.connect "/students/:name", :controller => :students, :action => :show, :requirements => {:name => /[A-Z][A-Z]+/}
Then in your show action you can find by name using params[:name].
You can create a catch-all route. Put this at the bottom of config/routes.rb with whatever controller and action you want:
map.connect '*path', :controller => '...', :action => '...'
The segments of the route will be available to your controller in the params[:path] array.

Rails routes matching query parameters

Rails routes are great for matching RESTful style '/' separated bits of a URL, but can I match query parameters in a map.connect config. I want different controllers/actions to be invoked depending on the presence of a parameter after the '?'.
I was trying something like this...
map.connect "api/my/path?apple=:applecode", :controller => 'apples_controller', :action => 'my_action'
map.connect "api/my/path?banana=:bananacode", :controller => 'bananas_controller', :action => 'my_action'
For routing purposes I don't care about the value of the parameter, as long as it is available to the controller in the params hash
The following solution is based on the "Advanced Constraints" section of the "Rails Routing from the Outside In" rails guide (http://guides.rubyonrails.org/routing.html).
In your config/routes.rb file, include a recognizer class have a matches? method, e.g.:
class FruitRecognizer
def initialize(fruit_type)
#fruit_type = fruit_type.to_sym
end
def matches?(request)
request.params.has_key?(#fruit_type)
end
end
Then use objects from the class as routing constraints, as in:
map.connect "api/my/path", :contraints => FruitRecognizer.new(:apple), :controller => 'apples_controller', :action => 'my_action'
Unless there is a concrete reason why you can't change this, why not just make it restful?
map.connect "api/my/path/bananas/:id, :controller => "bananas_controller", :action => "my_action"
If you have many parameters, why not use a POST or a PUT so that your parameters don't need to be exposed by the url?

? in routes.rb with map.with_options ruby

I'm using named routes in my ruby code. I come from the phpworld where you'll pass information using $_GET and $_POST. I was wondering if there's a way to put this into the routes.rb like this:
map.with_options :controller => 'test' do |m|
m.someurl 'someurl?search=someterm', :action => 'index'
end
Currently it's returning can't convert Hash into String. Thanks!
Justin
If you want to just use a Query String, you don't need to tell your route at all. The params object will contain any passed parameters.
map.with_options :controller => 'test' do |m|
m.some_url 'someurl', :action => 'index'
end
Then when you use the helper method:
some_url_path(:search=> "someterm")
Will create the query string value for you.
However, if you want to pass a parameter to a controller, you can bind them in your route:
map.connect ':controller/:action/:id/:search'
In your controller you can then access:
params[:search]
In your case this would up being something like:
map.with_options :controller => 'test' do |m|
m.some_url 'someurl' :action => 'index'
end
The Rails Routing Guide provides an excellent overview on the subject.

routes.rb explicitly choose template

I would like to create one .erb file to be the output for a number of tiny actions that are just returning JSON. So with routes similar to:
map.json 'contacts_json', :controller => 'contacts', :action => 'get_json'
map.json 'cal_json', :controller => 'calendar', :action => 'get_json'
...
but this requires I create a contacts erb, and a calendar erb so on and so forth. Is there a way to explicitly tell them to use a json erb? Something like:
map.json 'contacts_json', :controller => 'contacts', :action => 'get_json', :view => 'layouts/json.html.erb'
I'm not sure it answers your question but using render :text => #foobar.to_json does wonders in some cases.
No -- you specify what view template to render in the controller action.

Resources