Internationalized I18n URL helpers - ruby-on-rails

Is it possible to have URL helpers in Rails behave differently for different locales, eg.
<%= link_to "Something", example_path %>
in English would go to site.com/something, and in another language to site.com/lang/blahblah
Currently, my routes are defined like
scope '(:locale)', :locale => /otherlang/ do
get '/' => 'home#show'
get 'otherlang-about' => 'about#show'
get 'otherlang-something/:id' => 'example#show'
end
get 'about' => 'about#show'
get 'something/:id' => 'example#show'
root 'home#show'

Yes it is possible, We are using this gem https://github.com/enriclluelles/route_translator in my company to get different routes_url for each languages but still pointing to the same controller#method.
You just need to define a route.yml file to define the translation for each routes.

Related

rails sunspot gem friendly SEO url's?

How does one get SEO friendly url's in sunspot?,
The method of search form is GET as suggested from the rails docs, but now i have a very long query string that looks terrible, is it possible to have it something like
/search/param1/bla/param2/bla
instead of the long
?search&param1=somevalue&param2=someval2
You could modify your search route to include the params. Something like this within your routes.rb:
match '/search/:param1/:param2' => 'search_controller#search_action', :as => :search_with_params, :via => :get
Then a user would visit:
/search/value1/value2
Which gives you params[:param1] and params[:param2] to access the values from the url.
If those 2 params are not required for all searches I believe you would also need a route just for the search action:
match '/search' => 'search_controller#search_aciton', :as => :search, :via => :get

Routing more than one action to the same controller and action

I am trying to get something like this working on my Rails app:
match '/:language', :to => 'posts#search_result'
match '/:tag', :to => 'posts#search_result'
match '/:language/:tag', :to => 'posts#search_result'
I am using this search_result action to filter some posts depending of the language and the tag.
The problem is that sometimes :tag will be nil or :language will be nil; so i have these 3 possibilities when calling the action:
<%=link_to "Spanish", {:controller => 'posts', :action => 'search_result', :language => "spanish"} %>
<%= link_to "Spanish", {:controller => 'posts', :action => 'search_result', :language => "spanish", :tag => #tag} %>
<%=link_to "#{tag.name}", {:controller => 'posts', :action => 'search_result', :tag => #tag} %>
And I am expection to have URLs like:
/spanish (for the first case)
/spanish/rails (where rails is a tag, for the second case)
/rails (for the third case)
But right now i am getting the rigth thing for the first and third case, but for the second case i am getting:
/spanish?tag=rails
or again /spanish (depending on if i had selected a tag first or a language first).
I hope i explained myself right. Any idea??. thanks!.
The router cannot tell the difference between a :language and a :tag.
Just because your routes say "language" and "tag" when you are constructing your code in the view.. remember that in the html this has been translated into just plain ole URLs eg /spanish or /rails
the route then has to be figured out from this URL.
Now as I said, the router can't tell that a particular word is a language or a tag... and the plain-ole-URL doesn't have the word "tag" or "language" in it anymore... so your two routes here:
match '/:language', :to => 'posts#search_result'
match '/:tag', :to => 'posts#search_result'
are both the same kind of URL
Just a single token after the slash. Here are some examples that will match that route:
/greek
/spanish
/rails
/urdu
/whatever
They will all match the first route that matches on "a single token after a slash"... which means your router will match all of them to the "language" route and will never ever match the "/:tag" route, because it's already matched on the route above.
he he: it's all greek to the router ;)
Edit:
Hi, this is helping me a lot to understand how routing works.. but still i can't see it clear. I understand what you said, and so basically i understand i should do something like match '/tags/:tag to at least only route to posts#search_result the URLS starting by /tag .. what would be a solution??
yes, "/tags/:tag" would be clear and unambiguous, but if you want it to truly flexible in tag vs language you would be better served by the simple:
match '/posts/search', :to => 'posts#search_result'
which can use any of your link_to examples above to generate eg:
/posts/search?tag=rails
/posts/search?language=spanish
/posts/search?language=spanish&tag=rails
It's also far more clear what is being passed and why.
The description of the third URL is "I'm searching for a set of posts which have language = spanish and tag = rails"
Your URL should reflect the resource (which in this case is a set of posts) everything else is better done as query params.
Instead of defining /:language and /:language/:tag separately, define them together, with /:tag as an optional URI element.
match '/:language(/:tag)', :to => 'posts#search_result'
I believe routes are matched (and URIs generated from them) in the order that the routes are defined. You defined /:lang before you defined /:lang/:tag, so it matched /:lang and made :tag a GET parameter. I suppose you could optimize the ordering of your definitions, but I believe using the above syntax is the preferred method.

Creating a named route for a controller with static actions using Rails 3 routing API

I have a basic controller with named actions representing static pages:
class YourTripController < ApplicationController
def when_to_visit
end
def booking_a_trip
end
...
end
I want a named route to access these actions like:
your_trip_path(:when_to_visit)
your_trip_path(:booking_a_trip)
Seems simple enough right? But I also want to have the URLs use dashs rather then underscores for the generated paths:
example.com/your-trip/when-to-visit
example.com/your-trip/booking-a-trip
Given these constraints what does my route/s look like?
I've tried many approaches and this is the closest I've got so far:
controller :your_trip, :path => 'your-trip', :as => :your_trip do
get "when_to_visit", :path => 'when-to-visit'
get "booking_a_trip", :path => 'booking-a-trip'
end
This correctly routes me to the right action but using a url helper such as your_trip_path(:when_to_visit) results in:
No route matches {:action=>"when_to_visit", :controller=>"your_trip"}
Match url to controller#action and specify route name with :as:
get "your-trip/when-to-visit" => "your_trip#when_to_visit", :as => "when_to_visit"
Url helpers work too:
rails c
Loading development environment (Rails 3.0.3)
ruby-1.8.7-p302 :001 > app.when_to_visit_path
=> "/your-trip/when-to-visit"
Looks like with the help of routing-filter gem it might be possible write a custom route filter for hyphenated urls. That's of course an overkill for simple cases with just a couple of static pages.
Your version with tiny modification works:
controller :your_trip, :path => 'your-trip', :as => :your_trip do
get "when_to_visit", :path => 'when-to-visit', :as => :when_to_visit
get "booking_a_trip", :path => 'booking-a-trip', :as => :booking_a_trip
end
Routes are then named as:
your_trip_when_to_visit
your_trip_booking_a_trip

Rails hide controller name

i have match ":id" => "people#show" in my routes.rb
now i can access http://localhost:3000/1
but,in views <%= link_to 'Show', people %> it will generate http://localhost:3000/people/1 ,
i want to it to be http://localhost:3000/1
You could do something like this to ensure that only numeric ids are matched:
match '/:id' => 'people#show', :constraints => {:id => /\d+/}
A good alternative might be to use some kind of identifier, even if it's not the controller name: http://localhost:3000/p/1. This will at least ensure that if you add other controllers and actions you don't end up having to change your routing structure.
You could write a custom route to match that in config/routes.rb. At the bottom of your routes.rb file you will have a route like match ':controller(/:action(/:id(.:format)))'
or something like resources :people. You might have to write a route that matches the route type you want.
You have to create a named route.
match ':id' => 'people#show', :as => :person
And fix your views to use your new method person_path(user_id).

How can I use uncountable nouns in resource routes with Rails 3?

I have a model called Aircraft, inflected as uncountable, and it's
driving me nuts. What is the correct way to handle this in Rails 3 "beta
4"?
resources :aircraft do
member do
get :flights
end
end
# Of course these work for some actions and not others.
match 'aircraft', :to => 'aircraft#index', :as => :aircraft
match 'aircraft/:id', :to => 'aircraft#show', :as => :aircraft_instance
I think it's just:
resources :aircraft, :singular => :aircraft_instance
Then you link_to them like so:
link_to 'Singular aircraft', aircraft_instance_path(#aircraft)
link_to 'All aircraft', aircraft_path(#aircraft)
Edit
It looks like beta4 thinks aircrafts in the plural of aircraft:
rails console
> :aircraft.to_s.pluralize
=> "aircrafts"
If you just put resources :aircraft into your routes, can you link_to both aircraft_path(#aircraft) and aircrafts_path successfully? If so, you may need to write an initializer for ActiveSupport::Inflector to define your own custom inflection.

Resources