Rails routes with optional parameters priorities - ruby-on-rails

I have an strange issue in my routes file.
This is the part that I need to understand
This routes doesn't work
# V3
# V3 - Home Page
match '/:locale' => 'v3/home#index', :constraints => V3Constraint, :as => :home
# V3 - Search
match '(/:locale)/products/search' => 'v3/products#search', :constraints => V3Constraint
# V3 - Categories index
match '(/:locale)/categories/(:parent_category((/*path)/:category))/(:full)' => 'v3/products#index', :constraints => V3Constraint, :as => :category
# V3 - Prduct Page
match '/:locale/products/:product' => 'v3/products#show', :constraints => V3Constraint, :as => :product
match '(/:locale)/search_amazon' => 'v3/products#search_amazon', :constraints => V3Constraint
# EOF V3
But this work
#V3 - Search
match '(/:locale)/products/search' => 'v3/products#search', :constraints => V3Constraint
# V3 - Categories index
match '(/:locale)/categories/(:parent_category((/*path)/:category))/(:full)' => 'v3/products#index', :constraints => V3Constraint, :as => :category
# V3 - Product Page
match '/:locale/products/:product' => 'v3/products#show', :constraints => V3Constraint, :as => :product
match '(/:locale)/search_amazon' => 'v3/products#search_amazon', :constraints => V3Constraint
# V3 - Home Page
match '/:locale' => 'v3/home#index', :constraints => V3Constraint, :as => :home
If I made the Home Page route have less priority than the others it works, but if it was on the top like the other
this route:
match '(/:locale)/search_amazon' => 'v3/products#search_amazon', :constraints => V3Constraint
will be leading to the home page.
Can any please explain why this is has to happen ?
Thanks.

Having a route like this <yourdomain>/search_amazon will match the first one of these two routes
match '(/:locale)/search_amazon' => 'v3/products#search_amazon', :constraints => V3Constraint
In this case, it will match because locale is optional here.
match '/:locale' => 'v3/home#index', :constraints => V3Constraint, :as => :home
While here it will match making search_amazon as the value for locale.

Related

Why default locale does not work?

In my application controller, I am forcing locale handling as a before filter:
before_filter :set_locale
def set_locale
#I18n.default_locale is en
I18n.locale = extract_locale_from_tld || I18n.default_locale
end
def extract_locale_from_tld
parsed_locale = params[:locale] || ((lang = request.env['HTTP_ACCEPT_LANGUAGE']) && lang[/^[a-z]{2}/])
#so, english is the default language.
parsed_locale= 'en' if parsed_locale.nil?
I18n.available_locales.include?(parsed_locale.to_sym) ? parsed_locale : nil
end
However, if I tried to visit http://localhost:3000/ko/lab it would result into routing error which is error 404 eventually.
Any locale out of the following locates will result into routing error:
Any advice?
EDIT
My route.er:
# -*- encoding : utf-8 -*-
MyApp::Application.routes.draw do
mount Alchemy::Engine => 'blog'
Rails.application.routes.draw do
filter :pagination, :uuid, :locale
end
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks",
:sessions => "users/sessions",
:registrations => "users/registrations"}
resources :authentications
resources :experiments
get 'experiments/:id/info_edit' => 'experiments#info_edit',:constraints => { :id => /\d+/ }
get 'sitemap.xml', :to => 'sitemap#index', :defaults => {:format => 'xml'}
match 'lang' => 'home#set_lang', :via => [:get]
#match 'free_trial' => 'home#free_trial', :via => [:get]
match 'useful_links' => 'home#useful_links', :via => [:get]
match 'home' => 'home#home', :via => [:get]
match 'contact-us' => 'contact#new', :as => 'contact_us', :via => :get
match 'contact' => 'contact#create', :as => 'contact', :via => :post
match 'dashboard' => 'experiments#index', :via => [:get]
post 'notifications' => 'subscriptions#instant_payment_notification'
match 'users_experiments' => 'experiments#users_experiments', :via => [:get]
match 'hire_us' => 'home#hire_us', :via => [:get]
get 'lab' => 'experiments#lab'
get 'experiments/:id/review-edit' => 'experiments#review', :as => :review
get 'experiments/:id/cancel-edit' => 'experiments#cancel_edit', :as => :cancel_edit
get 'experiments/:id/approve-edit' => 'experiments#approve', :as => :approve
get 'experiments/:id/reject-edit' => 'experiments#reject', :as => :reject
get 'experiments/:id/profile' => 'experiments#profile', :as => :profile
match 'amazon' => 'experiments#amazon', :via => [:get]
match 'trial_account' => 'home#trial_account', :via => [:get]
match 'student_account' => 'home#student_account', :via => [:get]
match 'school_account' => 'home#school_account', :via => [:get]
match 'create_account' => 'home#registration_redirect', :via => [:get]
match 'users/create_account' => 'home#registration_entrance', :via => [:get]
match 'registration_redirect' => 'home#registration_redirect', :via=>[:post]
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
root :to => 'home#home'
get "/auth/oauth2/callback" => "auth0#callback"
get "/auth/verification_complete" => "auth0#verification_complete"
get "/auth/failure" => "auth0#failure"
end
My server log:
Started GET "/ko/lab" for 127.0.0.1 at 2017-09-12 08:58:56 +0300
Processing by ApplicationController#routing_error as HTML
Parameters: {"path"=>"ko/lab"} User Load (202.1ms) SELECT
"users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id"
ASC LIMIT 1 [["id", 12899]] Completed 404 Not Found in 205ms ko/lab
excluded from capture: DSN not set
ActionController::RoutingError (ko/lab):
app/controllers/application_controller.rb:35:in routing_error'
lib/rack/seoredirect.rb:20:incall'
Default local does work but you don't have a route that matches /:locale/lab. Its that simple.
You can create localized routes by using scope - Rails does not do this for you.
scope '(:locale)', locale: /#{I18n.available_locales.join('|')}/ do
get '/' => 'home#home' # this will map /en to home#home
get 'lab' => 'experiments#lab'
# ...
end
This is probably a good time to refactor a really messy routes file by using the resources helper to its full extent:
resources :experiments do
member do
get :info_edit
# ...
end
end
See http://guides.rubyonrails.org/routing.html#adding-more-restful-actions

Rails constraint on route that contains dynamic segment

I have the following two routes in my Rails app:
match '/users/:username' => 'users#show', :via => :get, :as => :user
match '/users(/:filter)' => 'users#index', :via => :get, :as => :users
This is so that I can have routes like:
/users/cameron
/users/popular
Where the first is a user, and the second is a filter.
However the routing in Rails will always hit the first route, because it doesn't know the difference between :username and :filter.
For posts I avoid this problem by doing:
match '/posts/:id' => 'posts#show', :via => :get, :as => :post, :id => /[0-9]/
But this only works because posts are always integers. For example: /posts/21
How can I apply a constraint to my user routes so that they don't trip over each other and without having to add a prefix to either of them.
I've tried this approach (based on the link provided by #Mario
match '/users/:username' => 'users#show', :via => :get, :as => :user, :constraints => lambda { |request| User.usernames.include?(request.params[:username]) }
and in my User model:
def self.usernames
User.pluck(:username)
end

How to use same route path for both locales

I have this code in routes.rb.
scope ":locale", :locale => /es/ do
match "inicio" => "home#index", :as => "home"
match "acerca-de" => "about#index", :as => "about"
match "servicios" => "services#index", :as => "services"
match "blog" => "blog#index", :as => "blog"
match "contacto" => "contact#index", :as => "contact"
end
scope ":locale", :locale => /en/ do
match "home" => "home#index", :as => "home"
match "about" => "about#index", :as => "about"
match "services" => "services#index", :as => "services"
match "blog" => "blog#index", :as => "blog"
match "contact" => "contact#index", :as => "contact"
end
What I'm trying to do is have a route like /es/acerca-de and /en/about which use the same controller and have the same url_path() so when I'm at spanish language the about_path() sends you to /en/about but when I'm at english language the about_path() sends you to /es/acerca-de.
Done!
I the answer was practically in the ruby on rails guides...
This is the code in routes.rb
scope ":locale", :locale => /es|en/ do
match "inicio" => "home#index", :as => "home"
match "acerca-de" => "about#index", :as => "about"
match "servicios" => "services#index", :as => "services"
match "blog" => "blog#index", :as => "blog"
match "contacto" => "contact#index", :as => "contact"
end
and added this in application_controller
class ApplicationController < ActionController::Base
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
Saba::Application.reload_routes!
end

In routes, match to #index does not work...why?

I'm setting up my website such that
www.website.com/articles/2013/07 will list all articles from 2013 in July and
www.website.com/articles/2013 will list all articles in 2013
www.website.com/articles/2013/07/title-of-article will list just the specific article
However, I am able to get only the first and last of the above 3 to work. Entering the url
www.website.com/articles/2013 is not working properly. Specifically, I get a noMethodError in Articles#show which doesn't make sense to me because I have matched the route to Articles#index.
Can someone please explain what's going on here? I don't see where I am making a mistake.
Routes:
match "/articles/:year", :to => "articles#index",
:constraints => { :year => /\d{4}/ }, :as=> :posts_year
match "/articles/:year/:month", :to => "articles#index",
:constraints => { :year => /\d{4}/, :month => /\d{1,2}/ }, :as => :posts_month
match "/articles/:year/:month/:slug", :to => "articles#show",
:constraints => { :year => /\d{4}/, :month => /\d{1,2}/, :slug => /[a-z0-9\-]+/ }, :as => :posts_date
and in my model I have:
def year
created_at.year
end
def month
created_at.strftime("%m")
end
Do you have resources :articles in your routes file? If you do, that explains the error. Move resources :articles below the routes you mentioned in your question and everything should work fine. Alternatively you could change it to:
resources :articles, :except => :show
Guessing that if you've defined articles as a resource, then the default show/:id route is taking precedence over your :posts_year route. Maybe try resources :articles, :except => [:show]

Ruby on Rails Routing match parameters not showing up

I have the following routes
match 'tracks/:id/entire_graph'=> "tracks#entire_graph", :as => "entire_graph"
match 'tracks/:id/entire_graph/:rid'=> "tracks#entire_graph", :as => "entire_graph2"
match 'tracks/:id/:rid' => "tracks#blahh", :as => "refer_your_friends"
resources :tracks
match '/auth/:provider/callback' => 'authentications#create'
match '/auth/failure' => 'authentications#failure'
match '/tracks/:id/:rid/facebookpost' => 'tracks#facebook_post', :as => "facebook_post_track"
match '/tracks/:id/:rid/twitterpost' => 'tracks#twitter_post', :as => "twitter_post_track"
resources :authentications
My problem is regarding the 'tracks/:id/:rid' route.
I am trying to call it like this: 'tracks/9/15'
I get a value for params[:id], but params[:rid] = nil, and I cannot figure out why.

Resources